From 5d01c254c8de65bfbcb1155d2d7531cc4898dfb4 Mon Sep 17 00:00:00 2001 From: KorryKatti <143781663+KorryKatti@users.noreply.github.com> Date: Mon, 18 Nov 2024 23:17:25 +0530 Subject: [PATCH 001/151] Update 01-zig-weird.qmd --- Chapters/01-zig-weird.qmd | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Chapters/01-zig-weird.qmd b/Chapters/01-zig-weird.qmd index 7f564f7e..c1539784 100644 --- a/Chapters/01-zig-weird.qmd +++ b/Chapters/01-zig-weird.qmd @@ -359,6 +359,26 @@ zig run src/main.zig ``` Hello, world! ``` +### Important Note for Windows Users + +On Windows, certain global initializations that rely on runtime resources, such as `std.io.getStdOut().writer()`, may fail. This happens because global variables in Zig are initialized at **compile-time**, and operations like accessing `stdout` or opening files are restricted to runtime. + +### Example +**Incorrect:** +```{zig} +#| eval: false +#| auto_main: false +const stdout = std.io.getStdOut().writer(); // ❌ Compile-time error on Windows +``` +Correct: + +```{zig} +#| eval: false +#| auto_main: false +pub fn main() void { + const stdout = std.io.getStdOut().writer(); // ✅ Runtime initialization +} +``` ### Compiling the entire project {#sec-compile-project} From 96e86e97db6c11a9af399cb8162ceafa5eb559c2 Mon Sep 17 00:00:00 2001 From: KorryKatti <143781663+KorryKatti@users.noreply.github.com> Date: Thu, 21 Nov 2024 21:21:46 +0530 Subject: [PATCH 002/151] Update 03-structs.qmd --- Chapters/03-structs.qmd | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Chapters/03-structs.qmd b/Chapters/03-structs.qmd index 11b4861f..ef7c740c 100644 --- a/Chapters/03-structs.qmd +++ b/Chapters/03-structs.qmd @@ -282,15 +282,18 @@ switch statement two times, before ending at the `3` branch. #| auto_main: false #| build_type: "lib" #| eval: false -xsw: switch (@as(u8, 1)) { - 1 => { - try stdout.print("First branch\n", .{}); - continue :xsw 2; - }, - 2 => continue :xsw 3, - 3 => return, - 4 => {}, -} + xsw: switch (@as(u8, 1)) { + 1 => { + try stdout.print("First branch\n", .{}); + continue :xsw 2; + }, + 2 => continue :xsw 3, + 3 => return, + 4 => {}, + else => { + try stdout.print("Unmatched case, value: {d}\n", .{@as(u8, 1)}); + }, + } ``` From 426b59ba234ad2eb27ffef0a089d90ac9ed824d0 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 24 Nov 2024 20:17:42 -0300 Subject: [PATCH 003/151] Fix indentation --- Chapters/03-structs.qmd | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Chapters/03-structs.qmd b/Chapters/03-structs.qmd index ef7c740c..1dd3552d 100644 --- a/Chapters/03-structs.qmd +++ b/Chapters/03-structs.qmd @@ -282,18 +282,20 @@ switch statement two times, before ending at the `3` branch. #| auto_main: false #| build_type: "lib" #| eval: false - xsw: switch (@as(u8, 1)) { - 1 => { - try stdout.print("First branch\n", .{}); - continue :xsw 2; - }, - 2 => continue :xsw 3, - 3 => return, - 4 => {}, - else => { - try stdout.print("Unmatched case, value: {d}\n", .{@as(u8, 1)}); - }, - } +xsw: switch (@as(u8, 1)) { + 1 => { + try stdout.print("First branch\n", .{}); + continue :xsw 2; + }, + 2 => continue :xsw 3, + 3 => return, + 4 => {}, + else => { + try stdout.print( + "Unmatched case, value: {d}\n", .{@as(u8, 1)} + ); + }, +} ``` From a0532a5b0c56ef04076c7e4e66e7a3e1ef3a1a36 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 24 Nov 2024 20:20:27 -0300 Subject: [PATCH 004/151] Recompile book with changes from #95 --- _freeze/Chapters/03-structs/execute-results/html.json | 8 +++++--- docs/Chapters/03-structs.html | 7 ++++++- docs/index.html | 4 ++-- docs/search.json | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/_freeze/Chapters/03-structs/execute-results/html.json b/_freeze/Chapters/03-structs/execute-results/html.json index 55c219e2..a9593c0d 100644 --- a/_freeze/Chapters/03-structs/execute-results/html.json +++ b/_freeze/Chapters/03-structs/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "d6fc1ed4bd224ef816cd041a3496fc12", + "hash": "fe9a62d3c3cabeb2802974d2becced51", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `order`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object have type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e. four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n```\n:::\n\n\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It is important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n}\n```\n:::\n\n\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n```\n:::\n\n\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function get's executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, is worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression get's executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n```\n:::\n\n\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that get's printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n```\n:::\n\n\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n // code to execute\n}\n```\n:::\n\n\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It is the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e. the logical test is equal to false), the function raises an assertion error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e. constant) object\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n x = x + 2;\n return x;\n}\n\npub fn main() !void {\n const y = add2(4);\n std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n x = x + 2;\n ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e. `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n const d: u32 = 2;\n x.* = x.* + d;\n}\n\npub fn main() !void {\n var x: u32 = 4;\n add2(&x);\n std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n pub fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n pub fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nEvery method that you declare in your struct that is marked with the keyword `pub`,\nbecomes a public method of this particular struct.\n\nSo every method that you create inside your struct, is, at first, a private method\nof that struct. Meaning that, this method can only be called from within this\nstruct. But, if you mark this method as public, with the keyword `pub`, then,\nyou can call the method directly from an instance of the `User` struct.\n\nIn other words, the functions marked by the keyword `pub`\nare members of the public API of that struct.\nFor example, if I did not mark the `print_name()` method as public,\nthen, I could not execute the line `u.print_name()`. Because I would\nnot be authorized to call this method directly in my code.\n\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n```\n:::\n\n\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt is not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n```\n:::\n\n\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods is affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e. change the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n```\n:::\n\n\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it is not about the input object, it is about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special party in this place. More specifically, it is\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and it is\ntrying to infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n```\n:::\n\n\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e. we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it is explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n```\n:::\n\n\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe, and there are situations where these assumptions do not hold. For example,\nwhen casting an integer value into a float value, or vice-versa, it is not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n```\n:::\n\n\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e. they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n:::\n\n\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e. a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" get's executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object get's saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n .{ .max_threads = num_threads }\n);\n```\n:::\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `order`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object have type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e. four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n```\n:::\n\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It is important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n else => {\n try stdout.print(\n \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n );\n },\n}\n```\n:::\n\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n```\n:::\n\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function get's executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, is worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression get's executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that get's printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n // code to execute\n}\n```\n:::\n\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It is the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e. the logical test is equal to false), the function raises an assertion error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e. constant) object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n x = x + 2;\n return x;\n}\n\npub fn main() !void {\n const y = add2(4);\n std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n x = x + 2;\n ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e. `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n const d: u32 = 2;\n x.* = x.* + d;\n}\n\npub fn main() !void {\n var x: u32 = 4;\n add2(&x);\n std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n pub fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n pub fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nEvery method that you declare in your struct that is marked with the keyword `pub`,\nbecomes a public method of this particular struct.\n\nSo every method that you create inside your struct, is, at first, a private method\nof that struct. Meaning that, this method can only be called from within this\nstruct. But, if you mark this method as public, with the keyword `pub`, then,\nyou can call the method directly from an instance of the `User` struct.\n\nIn other words, the functions marked by the keyword `pub`\nare members of the public API of that struct.\nFor example, if I did not mark the `print_name()` method as public,\nthen, I could not execute the line `u.print_name()`. Because I would\nnot be authorized to call this method directly in my code.\n\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n```\n:::\n\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt is not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n```\n:::\n\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods is affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e. change the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n```\n:::\n\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it is not about the input object, it is about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special party in this place. More specifically, it is\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and it is\ntrying to infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n```\n:::\n\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e. we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it is explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n```\n:::\n\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe, and there are situations where these assumptions do not hold. For example,\nwhen casting an integer value into a float value, or vice-versa, it is not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n```\n:::\n\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e. they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n:::\n\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e. a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" get's executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object get's saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n .{ .max_threads = num_threads }\n);\n```\n:::\n", + "supporting": [ + "03-structs_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/docs/Chapters/03-structs.html b/docs/Chapters/03-structs.html index e4dfa23f..a9014775 100644 --- a/docs/Chapters/03-structs.html +++ b/docs/Chapters/03-structs.html @@ -464,7 +464,12 @@

2 => continue :xsw 3, 3 => return, 4 => {}, -} + else => { + try stdout.print( + "Unmatched case, value: {d}\n", .{@as(u8, 1)} + ); + }, +} diff --git a/docs/index.html b/docs/index.html index cdf70e0c..6725b3d8 100644 --- a/docs/index.html +++ b/docs/index.html @@ -7,7 +7,7 @@ - + Introduction to Zig \n\n\n\n \n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria have a bachelor degree in Economics from Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\nan Associate Developer for Apache Spark 3.0 certified by Databricks.\n\n[^blip]: \n\n\nThe author have more than 4 years of experience in the data industry. Developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nbrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer that loves to\nlearn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n\n- System version: Linux, 6.8.0-48-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.2051+b1361f237.\n- Quarto version: 1.5.57.\n\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti)\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy an eBook or a physical copy\nof the book on Amazon:\n\n\n\n\n\n\n \n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria have a bachelor degree in Economics from Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\nan Associate Developer for Apache Spark 3.0 certified by Databricks.\n\n[^blip]: \n\n\nThe author have more than 4 years of experience in the data industry. Developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nbrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer that loves to\nlearn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-49-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.2051+b1361f237.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang)\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/contributors.txt b/contributors.txt index 17bbcd5c..18cad9e2 100644 --- a/contributors.txt +++ b/contributors.txt @@ -11,3 +11,4 @@ Chris Boesch,@chrboesch Bruno,@PoorlyDefinedBehaviour Ilia Choly,@icholy Korri Katti,@KorryKatti +Vedang Manerikar,@vedang diff --git a/docs/index.html b/docs/index.html index 6725b3d8..73c18985 100644 --- a/docs/index.html +++ b/docs/index.html @@ -7,7 +7,7 @@ - + Introduction to Zig \n\n\n\n \n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria have a bachelor degree in Economics from Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\nan Associate Developer for Apache Spark 3.0 certified by Databricks.\n\n[^blip]: \n\n\nThe author have more than 4 years of experience in the data industry. Developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nbrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer that loves to\nlearn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-49-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.2051+b1361f237.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang)\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy an eBook or a physical copy\nof the book on Amazon:\n\n\n\n\n\n\n \n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria have a bachelor degree in Economics from Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\nan Associate Developer for Apache Spark 3.0 certified by Databricks.\n\n[^blip]: \n\n\nThe author have more than 4 years of experience in the data industry. Developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nbrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer that loves to\nlearn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-49-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.2371+c013f45ad.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang)\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/docs/Chapters/01-memory.html b/docs/Chapters/01-memory.html index 23a683fc..0e748f6f 100644 --- a/docs/Chapters/01-memory.html +++ b/docs/Chapters/01-memory.html @@ -367,14 +367,16 @@

In contrast, if the type of this struct that you are declaring, includes a data member that is an array, but this array has a known fixed size, like [60]u8 (which declares an array of 60 u8 values), then, this type, or, this struct that you are declaring, becomes a type with a known fixed size at compile-time. And because of that, in this case, the zig compiler does not need to know at compile-time the exact value of any object of this type. Since the compiler can find the necessary size to store this object by looking at the size of its type.

Let’s look at an example. In the source code below, we have two constant objects (name and array) declared. Because the values of these particular objects are written down, in the source code itself ("Pedro" and the number sequence from 1 to 4), the zig compiler can easily discover the values of these constant objects (name and array) during the compilation process. This is what “known at compile time” means. It refers to any object that you have in your Zig source code whose value can be identified at compile time.

-
const name = "Pedro";
-const array = [_]u8{1, 2, 3, 4};
-_ = name; _ = array;
-
-fn input_length(input: []const u8) usize {
-    const n = input.len;
-    return n;
-}
+
fn input_length(input: []const u8) usize {
+    const n = input.len;
+    return n;
+}
+
+pub fn main() !void {
+    const name = "Pedro";
+    const array = [_]u8{1, 2, 3, 4};
+    _ = name; _ = array;
+}

The other side of the spectrum are objects whose values are not known at compile time. Function arguments are a classic example of this. Because the value of each function argument depends on the value that you assign to this particular argument, when you call the function.

For example, the function input_length() contains an argument named input, which is an array of constant u8 integers ([]const u8). It is impossible to know the value of this particular argument at compile time. And it also is impossible to know the size/length of this particular argument. Because it is an array that do not have a fixed size specified explicitly in the argument type annotation.

@@ -401,13 +403,15 @@

Every time you make a function call in Zig, an amount of space in the stack is reserved for this particular function call (Chen and Guo 2022; Zig Software Foundation 2024). The value of each function argument given to the function in this function call is stored in this stack space. Also, every local object that you declare inside the function scope is usually stored in this same stack space.

Looking at the example below, the object result is a local object declared inside the scope of the add() function. Because of that, this object is stored inside the stack space reserved for the add() function. The r object (which is declared outside of the add() function scope) is also stored in the stack. But since it is declared in the “outer” scope, this object is stored in the stack space that belongs to this outer scope.

-
const r = add(5, 27);
-_ = r;
-
-fn add(x: u8, y: u8) u8 {
-    const result = x + y;
-    return result;
-}
+
fn add(x: u8, y: u8) u8 {
+    const result = x + y;
+    return result;
+}
+
+pub fn main() !void {
+    const r = add(5, 27);
+    _ = r;
+}

So, any object that you declare inside the scope of a function is always stored inside the space that was reserved for that particular function in the stack memory. This also counts for any object declared inside the scope of your main() function for example. As you would expect, in this case, they are stored inside the stack space reserved for the main() function.

One very important detail about the stack memory is that it frees itself automatically. This is very important, remember that. When objects are stored in the stack memory, you don’t have the work (or the responsibility) of freeing/destroying these objects. Because they will be automatically destroyed once the stack space is freed at the end of the function scope.

@@ -444,16 +448,16 @@

So, using again the add() function as an example, if you rewrite this function so that it returns a pointer to the local object result, the zig compiler will actually compile your program, with no warnings or errors. At first glance, it looks that this is good code that works as expected. But this is a lie!

If you try to take a look at the value inside of the r object, or, if you try to use this r object in another expression or function call, then, you would have undefined behaviour, and major bugs in your program (Zig Software Foundation 2024, see “Lifetime and Ownership”3 and “Undefined Behaviour”4 sections).

-
// This code compiles successfully. But it has
-// undefined behaviour. Never do this!!!
-
-// The `r` object is undefined!
-const r = add(5, 27);
-_ = r;
-
-fn add(x: u8, y: u8) *const u8 {
-    const result = x + y;
-    return &result;
+
fn add(x: u8, y: u8) *const u8 {
+    const result = x + y;
+    return &result;
+}
+
+pub fn main() !void {
+    // This code compiles successfully. But it has
+    // undefined behaviour. Never do this!!!
+    // The `r` object is undefined!
+    const r = add(5, 27); _ = r;
 }

This “invalid pointer to stack variable” problem is very known across many programming language communities. If you try to do the same thing, for example, in a C or C++ program (i.e. returning an address to a local object stored in the stack), you would also get undefined behaviour in the program.

@@ -642,9 +646,9 @@

defer aa.deinit(); const allocator = aa.allocator(); -const in1 = allocator.alloc(u8, 5); -const in2 = allocator.alloc(u8, 10); -const in3 = allocator.alloc(u8, 15); +const in1 = try allocator.alloc(u8, 5); +const in2 = try allocator.alloc(u8, 10); +const in3 = try allocator.alloc(u8, 15); _ = in1; _ = in2; _ = in3;

diff --git a/docs/Chapters/01-zig-weird.html b/docs/Chapters/01-zig-weird.html index 7b4a3931..ac94c65e 100644 --- a/docs/Chapters/01-zig-weird.html +++ b/docs/Chapters/01-zig-weird.html @@ -906,6 +906,10 @@

"Type 4: {}\n", .{@TypeOf(string_obj)} ); } +
+
Type 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons
+  st [4]i32Type 4: []const u8
+
Type 1: [4]i32
 Type 2: *const [16:0]u8
@@ -918,17 +922,17 @@ 

The encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in the string. For example, the character “H” is stored in UTF-8 as the decimal number 72. This means that the number 72 is the unicode point for the character “H”. Each possible character that can appear in a UTF-8 encoded string have its own unicode point.

For example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point) 570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which is 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why, the unicode point 570 is actually stored inside the computer’s memory as the bytes C8 BA.

-
const std = @import("std");
-const stdout = std.io.getStdOut().writer();
-pub fn main() !void {
-    const string_object = "Ⱥ";
-    _ = try stdout.write(
-        "Bytes that represents the string object: "
-    );
-    for (string_object) |char| {
-        try stdout.print("{X} ", .{char});
-    }
-}
+
const std = @import("std");
+const stdout = std.io.getStdOut().writer();
+pub fn main() !void {
+    const string_object = "Ⱥ";
+    _ = try stdout.write(
+        "Bytes that represents the string object: "
+    );
+    for (string_object) |char| {
+        try stdout.print("{X} ", .{char});
+    }
+}
Bytes that represents the string object: C8 BA 
@@ -940,19 +944,19 @@

If you need to iterate through the characters of a string, instead of its bytes, then, you can use the std.unicode.Utf8View struct to create an iterator that iterates through the unicode points of your string.

In the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in this string is represented by three bytes. But the for loop iterates four times, one iteration for each character/unicode point in this string:

-
const std = @import("std");
-const stdout = std.io.getStdOut().writer();
-
-pub fn main() !void {
-    var utf8 = try std.unicode.Utf8View.init("アメリカ");
-    var iterator = utf8.iterator();
-    while (iterator.nextCodepointSlice()) |codepoint| {
-        try stdout.print(
-            "got codepoint {}\n",
-            .{std.fmt.fmtSliceHexUpper(codepoint)},
-        );
-    }
-}
+
const std = @import("std");
+const stdout = std.io.getStdOut().writer();
+
+pub fn main() !void {
+    var utf8 = try std.unicode.Utf8View.init("アメリカ");
+    var iterator = utf8.iterator();
+    while (iterator.nextCodepointSlice()) |codepoint| {
+        try stdout.print(
+            "got codepoint {}\n",
+            .{std.fmt.fmtSliceHexUpper(codepoint)},
+        );
+    }
+}
got codepoint E382A2
 got codepoint E383A1
@@ -976,10 +980,10 @@ 

-
const name: []const u8 = "Pedro";
-try stdout.print(
-    "{any}\n", .{std.mem.eql(u8, name, "Pedro")}
-);
+
const name: []const u8 = "Pedro";
+try stdout.print(
+    "{any}\n", .{std.mem.eql(u8, name, "Pedro")}
+);
true
@@ -987,24 +991,23 @@

-
const name: []const u8 = "Pedro";
-try stdout.print(
-    "{any}\n", .{std.mem.startsWith(u8, name, "Pe")}
-);
+
const name: []const u8 = "Pedro";
+try stdout.print(
+    "{any}\n", .{std.mem.startsWith(u8, name, "Pe")}
+);
true

The concat() function, as the name suggests, concatenate two or more strings together. Because the process of concatenating the strings involves allocating enough space to accomodate all the strings together, this concat() function receives an allocator object as input.

-
const str1 = "Hello";
-const str2 = " you!";
-const str3 = try std.mem.concat(
-    allocator, u8, &[_][]const u8{ str1, str2 }
-);
-try stdout.print("{s}\n", .{str3});
+
const str1 = "Hello";
+const str2 = " you!";
+const str3 = try std.mem.concat(
+    allocator, u8, &[_][]const u8{ str1, str2 }
+);
+try stdout.print("{s}\n", .{str3});
-
Hello you!

As you can imagine, the replace() function is used to replace substrings in a string by another substring. This function works very similarly to the replace() method from Python strings. Therefore, you provide a substring to search, and every time that the replace() function finds this substring within the input string, it replaces this substring with the “replacement substring” that you provided as input.

In the example below, we are taking the input string “Hello”, and replacing all occurrences of the substring “el” inside this input string with “34”, and saving the results inside the buffer object. As result, the replace() function returns an usize value that indicates how many replacements were performed.

diff --git a/docs/Chapters/02-debugging.html b/docs/Chapters/02-debugging.html index 74a25692..4463b19c 100644 --- a/docs/Chapters/02-debugging.html +++ b/docs/Chapters/02-debugging.html @@ -356,14 +356,17 @@

const result = add(34, 16); std.debug.print("Result: {d}\n", .{result}); }

+
+
Result: 50
+
Result: 50

You could also achieve the exact same result by getting a file descriptor object to stderr, then, creating a writer object to stderr, then, using the print() method of this writer object, like in the example below:

-
const std = @import("std");
-const stderr = std.io.getStdErr().writer();
-// some more lines ...
-_ = try stderr.print("Result: {d}", .{result});
+
const std = @import("std");
+const stderr = std.io.getStdErr().writer();
+// some more lines ...
+_ = try stderr.print("Result: {d}", .{result});
@@ -379,83 +382,83 @@

5.2.2 Let’s debug a program

As an example, let’s use LLDB to navigate and investigate the following piece of Zig code:

-
const std = @import("std");
-const stdout = std.io.getStdOut().writer();
-
-fn add_and_increment(a: u8, b: u8) u8 {
-    const sum = a + b;
-    const incremented = sum + 1;
-    return incremented;
-}
-
-pub fn main() !void {
-    var n = add_and_increment(2, 3);
-    n = add_and_increment(n, n);
-    _ = try stdout.print("Result: {d}!\n", .{n});
-}
+
const std = @import("std");
+const stdout = std.io.getStdOut().writer();
+
+fn add_and_increment(a: u8, b: u8) u8 {
+    const sum = a + b;
+    const incremented = sum + 1;
+    return incremented;
+}
+
+pub fn main() !void {
+    var n = add_and_increment(2, 3);
+    n = add_and_increment(n, n);
+    _ = try stdout.print("Result: {d}!\n", .{n});
+}
Result: 13!

There is nothing wrong with this program. But it is a good start for us. First, we need to compile this program with the zig build-exe command. For this example, suppose that I have compiled the above Zig code into a binary executable called add_program.

-
zig build-exe add_program.zig
+
zig build-exe add_program.zig

Now, we can start LLDB with add_program, like this:

-
lldb add_program
+
lldb add_program

From now on, LLDB is started, and you can know that I’m executing LLDB commands by looking at the prefix (lldb). If something is prefixed with (lldb), then you know that it is a LLDB command.

The first thing I will do, is to set a breakpoint at the main() function, by executing b main. After that, I just start the execution of the program with run. You can see in the output below, that the execution stopped at the first line in the function main(), as we expected.

-
(lldb) b main
-Breakpoint 1: where = debugging`debug1.main + 22
-    at debug1.zig:11:30, address = 0x00000000010341a6
-(lldb) run
-Process 8654 launched: 'add_program' (x86_64)
-Process 8654 stopped
-* thread #1, name = 'add_program',
-    stop reason = breakpoint 1.1 frame #0: 0x10341a6
-    add_program`debug1.main at add_program.zig:11:30
-   8    }
-   9    
-   10   pub fn main() !void {
--> 11       var n = add_and_increment(2, 3);
-   12       n = add_and_increment(n, n);
-   13       try stdout.print("Result: {d}!\n", .{n});
-   14   }
+
(lldb) b main
+Breakpoint 1: where = debugging`debug1.main + 22
+    at debug1.zig:11:30, address = 0x00000000010341a6
+(lldb) run
+Process 8654 launched: 'add_program' (x86_64)
+Process 8654 stopped
+* thread #1, name = 'add_program',
+    stop reason = breakpoint 1.1 frame #0: 0x10341a6
+    add_program`debug1.main at add_program.zig:11:30
+   8    }
+   9    
+   10   pub fn main() !void {
+-> 11       var n = add_and_increment(2, 3);
+   12       n = add_and_increment(n, n);
+   13       try stdout.print("Result: {d}!\n", .{n});
+   14   }

I can start navigating through the code, and checking the objects that are being generated. If you are not familiar with the commands available in LLDB, I recommend you to read the official documentation of the project3. You can also look for cheat sheets, which quickly describes all commands available for you4.

Currently, we are in the first line at the main() function. In this line, we create the n object, by executing the add_and_increment() function. To execute the current line of code, and go to the next line, we can run the n LLDB command. Let’s execute this command.

After we executed this line, we can also look at the value stored inside this n object by using the p LLDB command. The syntax for this command is p <name-of-object>.

If we take a look at the value stored in the n object (p n), notice that it stores the hexadecimal value 0x06, which is the number 6 in decimal. We can also see that, this value have a type unsigned char, which is an unsigned 8-bit integer. We have talked already about this at Section 1.8, that u8 integers in Zig are equivalent to the C data type unsigned char.

-
(lldb) n
-Process 4798 stopped
-* thread #1, name = 'debugging',
-    stop reason = step over frame #0: 0x10341ae
-    debugging`debug1.main at debug1.zig:12:26
-   9    
-   10   pub fn main() !void {
-   11       var n = add_and_increment(2, 3);
--> 12       n = add_and_increment(n, n);
-   13       try stdout.print("Result: {d}!\n", .{n});
-   14   }
-(lldb) p n
-(unsigned char) $1 = '\x06'
+
(lldb) n
+Process 4798 stopped
+* thread #1, name = 'debugging',
+    stop reason = step over frame #0: 0x10341ae
+    debugging`debug1.main at debug1.zig:12:26
+   9    
+   10   pub fn main() !void {
+   11       var n = add_and_increment(2, 3);
+-> 12       n = add_and_increment(n, n);
+   13       try stdout.print("Result: {d}!\n", .{n});
+   14   }
+(lldb) p n
+(unsigned char) $1 = '\x06'

Now, on the next line of code, we are executing the add_and_increment() function once again. Why not step inside this function? Shall we? We can do that, by executing the s LLDB command. Notice in the example below that, after executing this command, we have entered into the context of the add_and_increment() function.

Also notice in the example below that, I have walked two more lines in the function’s body, then, I execute the frame variable LLDB command, to see at once, the value stored in each of the variables that were created inside the current scope.

You can see in the output below that, the object sum stores the value \f, which represents the form feed character. This character in the ASCII table, corresponds to the hexadecimal value 0x0C, or, in decimal, the number 12. So, this means that the result of the expression a + b executed at line 5, resulted in the number 12.

-
(lldb) s
-Process 4798 stopped
-* thread #1, name = 'debugging',
-    stop reason = step in frame #0: 0x10342de
-    debugging`debug1.add_and_increment(a='\x02', b='\x03')
-    at debug1.zig:4:39
--> 4    fn add_and_increment(a: u8, b: u8) u8 {
-   5        const sum = a + b;
-   6        const incremented = sum + 1;
-   7        return incremented;
-(lldb) n
-(lldb) n
-(lldb) frame variable
-(unsigned char) a = '\x06'
-(unsigned char) b = '\x06'
-(unsigned char) sum = '\f'
-(unsigned char) incremented = '\x06'
+
(lldb) s
+Process 4798 stopped
+* thread #1, name = 'debugging',
+    stop reason = step in frame #0: 0x10342de
+    debugging`debug1.add_and_increment(a='\x02', b='\x03')
+    at debug1.zig:4:39
+-> 4    fn add_and_increment(a: u8, b: u8) u8 {
+   5        const sum = a + b;
+   6        const incremented = sum + 1;
+   7        return incremented;
+(lldb) n
+(lldb) n
+(lldb) frame variable
+(unsigned char) a = '\x06'
+(unsigned char) b = '\x06'
+(unsigned char) sum = '\f'
+(unsigned char) incremented = '\x06'
@@ -464,15 +467,15 @@

-
const std = @import("std");
-const stdout = std.io.getStdOut().writer();
-const expect = std.testing.expect;
-
-pub fn main() !void {
-    const number: i32 = 5;
-    try expect(@TypeOf(number) == i32);
-    try stdout.print("{any}\n", .{@TypeOf(number)});
-}
+
const std = @import("std");
+const stdout = std.io.getStdOut().writer();
+const expect = std.testing.expect;
+
+pub fn main() !void {
+    const number: i32 = 5;
+    try expect(@TypeOf(number) == i32);
+    try stdout.print("{any}\n", .{@TypeOf(number)});
+}
i32
diff --git a/docs/Chapters/03-structs.html b/docs/Chapters/03-structs.html index a9014775..a469e292 100644 --- a/docs/Chapters/03-structs.html +++ b/docs/Chapters/03-structs.html @@ -570,9 +570,10 @@

You can do that by providing a second set of items to iterate over. More precisely, you provide the range selector 0.. to the for loop. So, yes, you can use two different iterators at the same time in a for loop in Zig.

But remember from Section 1.4 that, every object you create in Zig must be used in some way. So if you declare two iterators in your for loop, you must use both iterators inside the for loop body. But if you want to use just the index iterator, and not use the “value iterator”, then, you can discard the value iterator by maching the value items to the underscore character, like in the example below:

-
for (name, 0..) |_, i| {
-    try stdout.print("{d} | ", .{i});
-}
+
const name = "Pedro";
+for (name, 0..) |_, i| {
+    try stdout.print("{d} | ", .{i});
+}
0 | 1 | 2 | 3 | 4 |

@@ -679,6 +680,9 @@

add2(&x); std.debug.print("Result: {d}\n", .{x}); } +
+
Result: 6
+
Result: 6

Even in this code example above, the x argument is still immutable. Which means that the pointer itself is immutable. Therefore, you cannot change the memory address that it points to. However, you can dereference the pointer to access the value that it points to, and also, to change this value, if you need to.

@@ -694,33 +698,33 @@

If you look at the User struct below, you can see the struct keyword. Notice the data members of this struct: id, name and email. Every data member has its type explicitly annotated, with the colon character (:) syntax that we described earlier in Section 1.2.2. But also notice that every line in the struct body that describes a data member, ends with a comma character (,). So every time you declare a data member in your Zig code, always end the line with a comma character, instead of ending it with the traditional semicolon character (;).

Next, we have registered an init() function as a method of this User struct. This init() method is the constructor method that we will use to instantiate every new User object. That is why this init() function returns a new User object as result.

-
const std = @import("std");
-const stdout = std.io.getStdOut().writer();
-const User = struct {
-    id: u64,
-    name: []const u8,
-    email: []const u8,
-
-    pub fn init(id: u64,
-                name: []const u8,
-                email: []const u8) User {
-
-        return User {
-            .id = id,
-            .name = name,
-            .email = email
-        };
-    }
-
-    pub fn print_name(self: User) !void {
-        try stdout.print("{s}\n", .{self.name});
-    }
-};
-
-pub fn main() !void {
-    const u = User.init(1, "pedro", "email@gmail.com");
-    try u.print_name();
-}
+
const std = @import("std");
+const stdout = std.io.getStdOut().writer();
+const User = struct {
+    id: u64,
+    name: []const u8,
+    email: []const u8,
+
+    pub fn init(id: u64,
+                name: []const u8,
+                email: []const u8) User {
+
+        return User {
+            .id = id,
+            .name = name,
+            .email = email
+        };
+    }
+
+    pub fn print_name(self: User) !void {
+        try stdout.print("{s}\n", .{self.name});
+    }
+};
+
+pub fn main() !void {
+    const u = User.init(1, "pedro", "email@gmail.com");
+    try u.print_name();
+}
pedro
@@ -732,23 +736,23 @@

2.3.1 Anonymous struct literals

You can declare a struct object as a literal value. When we do that, we normally specify the data type of this struct literal by writing its data type just before the opening curly brace. For example, I could write a struct literal value of the type User that we have defined in the previous section like this:

-
const eu = User {
-    .id = 1,
-    .name = "Pedro",
-    .email = "someemail@gmail.com"
-};
-_ = eu;
+
const eu = User {
+    .id = 1,
+    .name = "Pedro",
+    .email = "someemail@gmail.com"
+};
+_ = eu;

However, in Zig, we can also write an anonymous struct literal. That is, you can write a struct literal, but not specify explicitly the type of this particular struct. An anonymous struct is written by using the syntax .{}. So, we essentially replaced the explicit type of the struct literal with a dot character (.).

As we described in Section 2.4, when you put a dot before a struct literal, the type of this struct literal is automatically inferred by the zig compiler. In essence, the zig compiler will look for some hint of what is the type of that struct. This hint can be the type annotation of a function argument, or the return type annotation of the function that you are using, or the type annotation of an existing object. If the compiler does find such type annotation, it will use this type in your literal struct.

Anonymous structs are very commonly used as inputs to function arguments in Zig. One example that you have seen already constantly, is the print() function from the stdout object. This function takes two arguments. The first argument, is a template string, which should contain string format specifiers in it, which tells how the values provided in the second argument should be printed into the message.

While the second argument is a struct literal that lists the values to be printed into the template message specified in the first argument. You normally want to use an anonymous struct literal here, so that the zig compiler do the job of specifying the type of this particular anonymous struct for you.

-
const std = @import("std");
-pub fn main() !void {
-    const stdout = std.io.getStdOut().writer();
-    try stdout.print("Hello, {s}!\n", .{"world"});
-}
+
const std = @import("std");
+pub fn main() !void {
+    const stdout = std.io.getStdOut().writer();
+    try stdout.print("Hello, {s}!\n", .{"world"});
+}
Hello, world!
@@ -759,11 +763,11 @@

Section 12.1). What this means is that you cannot create a new data type, and mark it as variable with the var keyword. So struct declarations are always constant. You cannot declare a new struct type using the var keyword. It must be const.

In the Vec3 example below, this declaration is allowed because I’m using the const keyword to declare this new data type.

-
const Vec3 = struct {
-    x: f64,
-    y: f64,
-    z: f64,
-};
+
const Vec3 = struct {
+    x: f64,
+    y: f64,
+    z: f64,
+};
@@ -772,34 +776,34 @@

It is not mandatory to use this self argument. But why would you not use this self argument? There is no reason to not use it. Because the only way to get access to the data stored in the data members of your struct is to access them through this self argument. If you don’t need to use the data in the data members of your struct inside your method, you very likely don’t need a method. You can just declare this logic as a simple function, outside of your struct declaration.

Take the Vec3 struct below. Inside this Vec3 struct we declared a method named distance(). This method calculates the distance between two Vec3 objects, by following the distance formula in euclidean space. Notice that this distance() method takes two Vec3 objects as input, self and other.

-
const std = @import("std");
-const m = std.math;
-const Vec3 = struct {
-    x: f64,
-    y: f64,
-    z: f64,
-
-    pub fn distance(self: Vec3, other: Vec3) f64 {
-        const xd = m.pow(f64, self.x - other.x, 2.0);
-        const yd = m.pow(f64, self.y - other.y, 2.0);
-        const zd = m.pow(f64, self.z - other.z, 2.0);
-        return m.sqrt(xd + yd + zd);
-    }
-};
+
const std = @import("std");
+const m = std.math;
+const Vec3 = struct {
+    x: f64,
+    y: f64,
+    z: f64,
+
+    pub fn distance(self: Vec3, other: Vec3) f64 {
+        const xd = m.pow(f64, self.x - other.x, 2.0);
+        const yd = m.pow(f64, self.y - other.y, 2.0);
+        const zd = m.pow(f64, self.z - other.z, 2.0);
+        return m.sqrt(xd + yd + zd);
+    }
+};

The self argument corresponds to the Vec3 object from which this distance() method is being called from. While the other is a separate Vec3 object that is given as input to this method. In the example below, the self argument corresponds to the object v1, because the distance() method is being called from the v1 object, while the other argument corresponds to the object v2.

-
const v1 = Vec3 {
-    .x = 4.2, .y = 2.4, .z = 0.9
-};
-const v2 = Vec3 {
-    .x = 5.1, .y = 5.6, .z = 1.6
-};
-
-std.debug.print(
-    "Distance: {d}\n",
-    .{v1.distance(v2)}
-);
+
const v1 = Vec3 {
+    .x = 4.2, .y = 2.4, .z = 0.9
+};
+const v2 = Vec3 {
+    .x = 5.1, .y = 5.6, .z = 1.6
+};
+
+std.debug.print(
+    "Distance: {d}\n",
+    .{v1.distance(v2)}
+);
Distance: 3.3970575502926055

@@ -814,40 +818,40 @@

But what if we do have a method that alters the state of the object, by altering the values of its data members, how should we annotate self in this instance? The answer is: “we should annotate self as a pointer of x, instead of just x”. In other words, you should annotate self as self: *x, instead of annotating it as self: x.

If we create a new method inside the Vec3 object that, for example, expands the vector by multiplying its coordinates by a factor of two, then, we need to follow this rule specified in the previous paragraph. The code example below demonstrates this idea:

-
const std = @import("std");
-const m = std.math;
-const Vec3 = struct {
-    x: f64,
-    y: f64,
-    z: f64,
-
-    pub fn distance(self: Vec3, other: Vec3) f64 {
-        const xd = m.pow(f64, self.x - other.x, 2.0);
-        const yd = m.pow(f64, self.y - other.y, 2.0);
-        const zd = m.pow(f64, self.z - other.z, 2.0);
-        return m.sqrt(xd + yd + zd);
-    }
-
-    pub fn twice(self: *Vec3) void {
-        self.x = self.x * 2.0;
-        self.y = self.y * 2.0;
-        self.z = self.z * 2.0;
-    }
-};
+
const std = @import("std");
+const m = std.math;
+const Vec3 = struct {
+    x: f64,
+    y: f64,
+    z: f64,
+
+    pub fn distance(self: Vec3, other: Vec3) f64 {
+        const xd = m.pow(f64, self.x - other.x, 2.0);
+        const yd = m.pow(f64, self.y - other.y, 2.0);
+        const zd = m.pow(f64, self.z - other.z, 2.0);
+        return m.sqrt(xd + yd + zd);
+    }
+
+    pub fn twice(self: *Vec3) void {
+        self.x = self.x * 2.0;
+        self.y = self.y * 2.0;
+        self.z = self.z * 2.0;
+    }
+};

Notice in the code example above that we have added a new method to our Vec3 struct named twice(). This method doubles the coordinate values of our vector object. In the case of the twice() method, we annotated the self argument as *Vec3, indicating that this argument receives a pointer (or a reference, if you prefer to call it this way) to a Vec3 object as input.

-
var v3 = Vec3 {
-    .x = 4.2, .y = 2.4, .z = 0.9
-};
-v3.twice();
-std.debug.print("Doubled: {d}\n", .{v3.x});
+
var v3 = Vec3 {
+    .x = 4.2, .y = 2.4, .z = 0.9
+};
+v3.twice();
+std.debug.print("Doubled: {d}\n", .{v3.x});
Doubled: 8.4

Now, if you change the self argument in this twice() method to self: Vec3, like in the distance() method, you will get the compiler error exposed below as result. Notice that this error message is showing a line from the twice() method body, indicating that you cannot alter the value of the x data member.

-
// If we change the function signature of double to:
-    pub fn twice(self: Vec3) void {
+
// If we change the function signature of double to:
+    pub fn twice(self: Vec3) void {
t.zig:16:13: error: cannot assign to constant
         self.x = self.x * 2.0;
@@ -884,31 +888,31 @@ 

Because these weird values contain a dot character before them, we are asking the zig compiler to infer the types of these values inside the switch statement. Then, the zig compiler is looking into the current context where these values are being used, and it is trying to infer the types of these values.

Since they are being used inside a switch statement, the zig compiler looks into the type of the input object given to the switch statement, which is the order object in this case. Because this object have type AtomicOrder, the zig compiler infers that these values are data members from this type AtomicOrder.

-
pub inline fn fence(self: *Self, comptime order: AtomicOrder) void {
-    // many lines of code ...
-    if (builtin.sanitize_thread) {
-        const tsan = struct {
-            extern "c" fn __tsan_acquire(addr: *anyopaque) void;
-            extern "c" fn __tsan_release(addr: *anyopaque) void;
-        };
-
-        const addr: *anyopaque = self;
-        return switch (order) {
-            .unordered, .monotonic => @compileError(
-                @tagName(order)
-                ++ " only applies to atomic loads and stores"
-            ),
-            .acquire => tsan.__tsan_acquire(addr),
-            .release => tsan.__tsan_release(addr),
-            .acq_rel, .seq_cst => {
-                tsan.__tsan_acquire(addr);
-                tsan.__tsan_release(addr);
-            },
-        };
-    }
-
-    return @fence(order);
-}
+
pub inline fn fence(self: *Self, comptime order: AtomicOrder) void {
+    // many lines of code ...
+    if (builtin.sanitize_thread) {
+        const tsan = struct {
+            extern "c" fn __tsan_acquire(addr: *anyopaque) void;
+            extern "c" fn __tsan_release(addr: *anyopaque) void;
+        };
+
+        const addr: *anyopaque = self;
+        return switch (order) {
+            .unordered, .monotonic => @compileError(
+                @tagName(order)
+                ++ " only applies to atomic loads and stores"
+            ),
+            .acquire => tsan.__tsan_acquire(addr),
+            .release => tsan.__tsan_release(addr),
+            .acq_rel, .seq_cst => {
+                tsan.__tsan_acquire(addr);
+                tsan.__tsan_release(addr);
+            },
+        };
+    }
+
+    return @fence(order);
+}

This is how basic type inference is done in Zig. If we didn’t use the dot character before the values inside this switch statement, then, we would be forced to explicitly write the data types of these values. For example, instead of writing .release we would have to write AtomicOrder.release. We would have to do this for every single value in this switch statement, and this is a lot of work. That is why type inference is commonly used on switch statements in Zig.

@@ -918,60 +922,71 @@

Most languages have a formal way to perform type casting. In Rust for example, we normally use the keyword as, and in C, we normally use the type casting syntax, e.g. (int) x. In Zig, we use the @as() built-in function to cast an object of type “x”, into an object of type “y”.

This @as() function is the preferred way to perform type conversion (or type casting) in Zig. Because it is explicit, and, it also performs the casting only if it is unambiguous and safe. To use this function, you just provide the target data type in the first argument, and, the object that you want cast as the second argument.

-
const std = @import("std");
-const expect = std.testing.expect;
-test {
-    const x: usize = 500;
-    const y = @as(u32, x);
-    try expect(@TypeOf(y) == u32);
-}
+
const std = @import("std");
+const expect = std.testing.expect;
+test {
+    const x: usize = 500;
+    const y = @as(u32, x);
+    try expect(@TypeOf(y) == u32);
+}
+
+
1/1 filefe9b6a29a64b.test_0...OKAll 1 tests passed
+  d.
+

This is the general way to perform type casting in Zig. But remember, @as() works only when casting is unambiguous and safe, and there are situations where these assumptions do not hold. For example, when casting an integer value into a float value, or vice-versa, it is not clear to the compiler how to perform this conversion safely.

Therefore, we need to use specialized “casting functions” in such situations. For example, if you want to cast an integer value into a float value, then, you should use the @floatFromInt() function. In the inverse scenario, you should use the @intFromFloat() function.

In these functions, you just provide the object that you want to cast as input. Then, the target data type of the “type casting operation” is determined by the type annotation of the object where you are saving the results. In the example below, we are casting the object x into a value of type f32, because the object y, which is where we are saving the results, is annotated as an object of type f32.

-
const std = @import("std");
-const expect = std.testing.expect;
-test {
-    const x: usize = 565;
-    const y: f32 = @floatFromInt(x);
-    try expect(@TypeOf(y) == f32);
-}
+
const std = @import("std");
+const expect = std.testing.expect;
+test {
+    const x: usize = 565;
+    const y: f32 = @floatFromInt(x);
+    try expect(@TypeOf(y) == f32);
+}
+
+
1/1 filefe9b126af3c3.test_0...OKAll 1 tests passed
+  d.
+

Another built-in function that is very useful when performing type casting operations is @ptrCast(). In essence, we use the @as() built-in function when we want to explicit convert (or cast) a Zig value/object from a type “x” to a type “y”, etc. However, pointers (we are going to discuss pointers in more depth in Chapter 6) are a special type of object in Zig, i.e. they are treated differently from “normal objects”.

Everytime a pointer is involved in some “type casting operation” in Zig, the @ptrCast() function is used. This function works similarly to @floatFromInt(). You just provide the pointer object that you want to cast as input to this function, and the target data type is, once again, determined by the type annotation of the object where the results are being stored.

-
const std = @import("std");
-const expect = std.testing.expect;
-test {
-    const bytes align(@alignOf(u32)) = [_]u8{
-        0x12, 0x12, 0x12, 0x12
-    };
-    const u32_ptr: *const u32 = @ptrCast(&bytes);
-    try expect(@TypeOf(u32_ptr) == *const u32);
-}
+
const std = @import("std");
+const expect = std.testing.expect;
+test {
+    const bytes align(@alignOf(u32)) = [_]u8{
+        0x12, 0x12, 0x12, 0x12
+    };
+    const u32_ptr: *const u32 = @ptrCast(&bytes);
+    try expect(@TypeOf(u32_ptr) == *const u32);
+}
+
+
1/1 filefe9b7366fb7.test_0...OKAll 1 tests passed.
+

2.6 Modules

We already talked about what modules are, and also, how to import other modules into your current module via import statements. Every Zig module (i.e. a .zig file) that you write in your project is internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the Zig Standard Library into our current module.

-
const std = @import("std");
+
const std = @import("std");

When we want to access the functions and objects from the standard library, we are basically accessing the data members of the struct stored in the std object. That is why we use the same syntax that we use in normal structs, with the dot operator (.) to access the data members and methods of the struct.

When this “import statement” get’s executed, the result of this expression is a struct object that contains the Zig Standard Library modules, global variables, functions, etc. And this struct object get’s saved (or stored) inside the constant object named std.

Take the thread_pool.zig module from the project zap3 as an example. This module is written as if it was a big struct. That is why we have a top-level and public init() method written in this module. The idea is that all top-level functions written in this module are methods from the struct, and all top-level objects and struct declarations are data members of this struct. The module is the struct itself.

So you would import and use this module by doing something like this:

-
const std = @import("std");
-const ThreadPool = @import("thread_pool.zig");
-const num_cpus = std.Thread.getCpuCount()
-    catch @panic("failed to get cpu core count");
-const num_threads = std.math.cast(u16, num_cpus)
-    catch std.math.maxInt(u16);
-const pool = ThreadPool.init(
-    .{ .max_threads = num_threads }
-);
+
const std = @import("std");
+const ThreadPool = @import("thread_pool.zig");
+const num_cpus = std.Thread.getCpuCount()
+    catch @panic("failed to get cpu core count");
+const num_threads = std.math.cast(u16, num_cpus)
+    catch std.math.maxInt(u16);
+const pool = ThreadPool.init(
+    .{ .max_threads = num_threads }
+);
diff --git a/docs/Chapters/03-unittests.html b/docs/Chapters/03-unittests.html index 8abbb454..0d3e2651 100644 --- a/docs/Chapters/03-unittests.html +++ b/docs/Chapters/03-unittests.html @@ -322,6 +322,10 @@

const b: u8 = 2; try expect((a + b) == 4); }

+
+
1/1 file103bc24525048.test.testing simple sum...OK
+  KAll 1 tests passed.
+

You can have multiple test blocks written on the same Zig module. Also, you can mix test blocks with your source code, with no problems or consequences. If you mix test blocks with your normal source code, when you execute the build, build-exe, build-obj or build-lib commands from the zig compiler that we exposed at Section 1.2.4, these test blocks are automatically ignored by the compiler.

In other words, the zig compiler builds and execute your unit tests only when you ask it to. By default, the compiler always ignore test blocks written in your Zig modules. The compiler normally checks only if there are any syntax errors in these test blocks.

@@ -331,7 +335,7 @@

8.2 How to run your tests

If the zig compiler ignores any test block by default, how can you compile and run your unit tests? The answer is the test command from the zig compiler. By running the zig test command, the compiler will find every instance of a test block in your Zig modules, and, it will compile and run the unit tests that you wrote.

-
zig test simple_sum.zig
+
zig test simple_sum.zig
1/1 simple_sum.test.testing simple sum... OK
 All 1 tests passed.
@@ -344,19 +348,19 @@

-
const std = @import("std");
-const Allocator = std.mem.Allocator;
-fn some_memory_leak(allocator: Allocator) !void {
-    const buffer = try allocator.alloc(u32, 10);
-    _ = buffer;
-    // Return without freeing the
-    // allocated memory
-}
-
-test "memory leak" {
-    const allocator = std.testing.allocator;
-    try some_memory_leak(allocator);
-}
+
const std = @import("std");
+const Allocator = std.mem.Allocator;
+fn some_memory_leak(allocator: Allocator) !void {
+    const buffer = try allocator.alloc(u32, 10);
+    _ = buffer;
+    // Return without freeing the
+    // allocated memory
+}
+
+test "memory leak" {
+    const allocator = std.testing.allocator;
+    try some_memory_leak(allocator);
+}
Test [1/1] leak_memory.test.memory leak...
     [gpa] (err): memory address 0x7c1fddf39000 leaked: 
@@ -376,21 +380,25 @@ 

The code example below demonstrates such type of unit test in Zig. Notice that, inside the function alloc_error() we are allocating 100 bytes of memory, or, an array of 100 elements, for the object ibuffer. However, in the test block, we are using the FixedBufferAllocator() allocator object, which is limited to 10 bytes of space, because the object buffer, which we provided to the allocator object, have only 10 bytes of space.

That is why, the alloc_error() function raises an OutOfMemory error on this case. Because this function is trying to allocate more space than the allocator object allows. So, in essence, we are testing for a specific type of error, which is OutOfMemory. If the alloc_error() function returns any other type of error, then, the expectError() function would make the entire test fail.

-
const std = @import("std");
-const Allocator = std.mem.Allocator;
-const expectError = std.testing.expectError;
-fn alloc_error(allocator: Allocator) !void {
-    var ibuffer = try allocator.alloc(u8, 100);
-    defer allocator.free(ibuffer);
-    ibuffer[0] = 2;
-}
-
-test "testing error" {
-    var buffer: [10]u8 = undefined;
-    var fba = std.heap.FixedBufferAllocator.init(&buffer);
-    const allocator = fba.allocator();
-    try expectError(error.OutOfMemory, alloc_error(allocator));
-}
+
const std = @import("std");
+const Allocator = std.mem.Allocator;
+const expectError = std.testing.expectError;
+fn alloc_error(allocator: Allocator) !void {
+    var ibuffer = try allocator.alloc(u8, 100);
+    defer allocator.free(ibuffer);
+    ibuffer[0] = 2;
+}
+
+test "testing error" {
+    var buffer: [10]u8 = undefined;
+    var fba = std.heap.FixedBufferAllocator.init(&buffer);
+    const allocator = fba.allocator();
+    try expectError(error.OutOfMemory, alloc_error(allocator));
+}
+
+
1/1 file103bc545495c8.test.testing error...OKAll 1
+  1 tests passed.
+
1/1 oom.test.testing error... OK
 All 1 tests passed.
@@ -401,12 +409,12 @@

-
const std = @import("std");
-test "values are equal?" {
-    const v1 = 15;
-    const v2 = 18;
-    try std.testing.expectEqual(v1, v2);
-}
+
const std = @import("std");
+test "values are equal?" {
+    const v1 = 15;
+    const v2 = 18;
+    try std.testing.expectEqual(v1, v2);
+}
1/1 ve.test.values are equal?...
     expected 15, found 18
@@ -418,28 +426,32 @@ 

-
const std = @import("std");
-test "arrays are equal?" {
-    const array1 = [3]u32{1, 2, 3};
-    const array2 = [3]u32{1, 2, 3};
-    try std.testing.expectEqualSlices(
-        u32, &array1, &array2
-    );
-}
+
const std = @import("std");
+test "arrays are equal?" {
+    const array1 = [3]u32{1, 2, 3};
+    const array2 = [3]u32{1, 2, 3};
+    try std.testing.expectEqualSlices(
+        u32, &array1, &array2
+    );
+}
+
+
1/1 file103bc78cf09de.test.arrays are equal?...OKA
+  All 1 tests passed.
+
1/1 oom.test.arrays are equal?... OK
 All 1 tests passed.

At last, you might also want to use the expectEqualStrings() function. As the name suggests, you can use this function to test if two strings are equal or not. Just provide the two string objects that you want to compare, as inputs to the function.

If the function finds any existing differences between the two strings, then, the function will raise an error, and also, print an error message that shows the exact difference between the two string objects provided, as the example below demonstrates:

-
const std = @import("std");
-test "strings are equal?" {
-    const str1 = "hello, world!";
-    const str2 = "Hello, world!";
-    try std.testing.expectEqualStrings(
-        str1, str2
-    );
-}
+
const std = @import("std");
+test "strings are equal?" {
+    const str1 = "hello, world!";
+    const str2 = "Hello, world!";
+    try std.testing.expectEqualStrings(
+        str1, str2
+    );
+}
1/1 t.test.strings are equal?... 
 ====== expected this output: =========
diff --git a/docs/Chapters/05-pointers.html b/docs/Chapters/05-pointers.html
index 0949abf8..98ebe8b1 100644
--- a/docs/Chapters/05-pointers.html
+++ b/docs/Chapters/05-pointers.html
@@ -347,22 +347,25 @@ 

const pointer = &number; const doubled = 2 * pointer.*; std.debug.print("{d}\n", .{doubled});

+
+
10
+
10

This syntax to dereference the pointer is nice. Because we can easily chain it with methods of the value pointed by the pointer. We can use the User struct that we have created at Section 2.3 as an example. If you comeback to that section, you will see that this struct have a method named print_name().

So, for example, if we have an user object, and a pointer that points to this user object, we can use the pointer to access this user object, and, at the same time, call the method print_name() on it, by chaining the dereference method (*) with the print_name() method. Like in the example below:

-
const u = User.init(1, "pedro", "email@gmail.com");
-const pointer = &u;
-try pointer.*.print_name();
+
const u = User.init(1, "pedro", "email@gmail.com");
+const pointer = &u;
+try pointer.*.print_name();
pedro

We can also use pointers to effectively alter the value of an object. For example, I could use the pointer object to set the value of the object number to 6, like in the example below.

-
var number: u8 = 5;
-const pointer = &number;
-pointer.* = 6;
-try stdout.print("{d}\n", .{number});
+
var number: u8 = 5;
+const pointer = &number;
+pointer.* = 6;
+try stdout.print("{d}\n", .{number});
6
@@ -375,18 +378,18 @@

You can have a pointer that points to a constant object, or, a pointer that points to a variable object. But regardless of who this pointer is, a pointer must always respect the characteristics of the object that it points to. As a consequence, if the pointer points to a constant object, then, you cannot use this pointer to change the value that it points to. Because it points to a value that is constant. As we discussed at Section 1.4, you cannot change a value that is constant.

For example, if I have a number object, which is constant, I cannot execute the expression below where I’m trying to change the value of number to 6 through the pointer object. As demonstrated below, when you try to do something like that, you get a compile time error:

-
const number = 5;
-const pointer = &number;
-pointer.* = 6;
+
const number = 5;
+const pointer = &number;
+pointer.* = 6;
p.zig:6:12: error: cannot assign to constant
     pointer.* = 6;

If I change the number object to be a variable object, by introducing the var keyword, then, I can successfully change the value of this object through a pointer, as demonstrated below:

-
var number: u8 = 5;
-const pointer = &number;
-pointer.* = 6;
-try stdout.print("{d}\n", .{number});
+
var number: u8 = 5;
+const pointer = &number;
+pointer.* = 6;
+try stdout.print("{d}\n", .{number});
6
@@ -397,12 +400,12 @@

Until this point, the pointer object was always constant, but what this means for us? What is the consequence of the pointer object being constant? The consequence is that we cannot change the pointer object, because it is constant. We can use the pointer object in multiple ways, but we cannot change the memory address that is inside this pointer object.

However, if we mark the pointer object as a variable object, then, we can change the memory address pointed by this pointer object. The example below demonstrates that. Notice that the object pointed by the pointer object changes from c1 to c2.

-
const c1: u8 = 5;
-const c2: u8 = 6;
-var pointer = &c1;
-try stdout.print("{d}\n", .{pointer.*});
-pointer = &c2;
-try stdout.print("{d}\n", .{pointer.*});
+
const c1: u8 = 5;
+const c2: u8 = 6;
+var pointer = &c1;
+try stdout.print("{d}\n", .{pointer.*});
+pointer = &c2;
+try stdout.print("{d}\n", .{pointer.*});
5
 6
@@ -424,13 +427,13 @@

Pointer arithmetic is available in Zig, and they work the same way they work in C. When you have a pointer that points to an array, the pointer usually points to the first element in the array, and you can use pointer arithmetic to advance this pointer and access the other elements in the array.

Notice in the example below, that initially, the ptr object was pointing to the first element in the array ar. But then, I started to walk through the array, by advancing the pointer with simple pointer arithmetic.

-
const ar = [_]i32{1,2,3,4};
-var ptr = &ar;
-try stdout.print("{d}\n", .{ptr.*});
-ptr += 1;
-try stdout.print("{d}\n", .{ptr.*});
-ptr += 1;
-try stdout.print("{d}\n", .{ptr.*});
+
const ar = [_]i32{1,2,3,4};
+var ptr = &ar;
+try stdout.print("{d}\n", .{ptr.*});
+ptr += 1;
+try stdout.print("{d}\n", .{ptr.*});
+ptr += 1;
+try stdout.print("{d}\n", .{ptr.*});
1
 2
@@ -439,9 +442,9 @@ 

Behind the hood, slices already are pointers, and they also come with the len property, which indicates how many elements are in the slice. This is good because the zig compiler can use it to check for potential buffer overflows, and other problems like that.

Also, you don’t need to use pointer arithmetic to walk through the elements of a slice. You can simply use the slice[index] syntax to directly access any element you want in the slice. As I mentioned at Section 1.6, you can get a slice from an array by using a range selector inside brackets. In the example below, I’m creating a slice (sl) that covers the entire ar array. I can access any element of ar from this slice, and, the slice itself already is a pointer behind the hood.

-
const ar = [_]i32{1,2,3,4};
-const sl = ar[0..ar.len];
-_ = sl;
+
const ar = [_]i32{1,2,3,4};
+const sl = ar[0..ar.len];
+_ = sl;
@@ -450,8 +453,8 @@

-
var number: u8 = 5;
-number = null;
+
var number: u8 = 5;
+number = null;

p5.zig:5:14: error: expected type 'u8',
         found '@TypeOf(null)'
@@ -465,8 +468,8 @@ 

An optional object in Zig is an object that can be null. To mark an object as optional, we use the ? operator. When you put this ? operator right before the data type of an object, you transform this data type into an optional data type, and the object becomes an optional object.

Take the snippet below as an example. We are creating a new variable object called num. This object have the data type ?i32, which means that, this object contains either a signed 32-bit integer (i32), or, a null value. Both alternatives are valid values to the num object. That is why, I can actually change the value of this object to null, and, no errors are raised by the zig compiler, as demonstrated below:

-
var num: ?i32 = 5;
-num = null;
+
var num: ?i32 = 5;
+num = null;
@@ -475,18 +478,18 @@

In the example below, we are creating a variable object named num, and an optional pointer object named ptr. Notice that the data type of the object ptr indicates that it is either a null value, or a pointer to an i32 value. Also, notice that the pointer object (ptr) can be marked as optional, even if the object num is not optional.

What this code tells us is that, the num variable will never contain a null value. This variable will always contain a valid i32 value. But in contrast, the ptr object might contain either a null value, or, a pointer to an i32 value.

-
var num: i32 = 5;
-var ptr: ?*i32 = &num;
-ptr = null;
-num = 6;
+
var num: i32 = 5;
+var ptr: ?*i32 = &num;
+ptr = null;
+num = 6;

But what happens if we turn the table, and mark the num object as optional, instead of the pointer object. If we do that, then, the pointer object is not optional anymore. It would be a similar (although different) result. Because then, we would have a pointer to an optional value. In other words, a pointer to a value that is either a null value, or, a not-null value.

In the example below, we are recreating this idea. Now, the ptr object have a data type of *?i32, instead of ?*i32. Notice that the * symbol comes before of ? this time. So now, we have a pointer that points to a value that is either null , or, a signed 32-bit integer.

-
var num: ?i32 = 5;
-// ptr have type `*?i32`, instead of `?*i32`.
-const ptr = &num;
-_ = ptr;
+
var num: ?i32 = 5;
+// ptr have type `*?i32`, instead of `?*i32`.
+const ptr = &num;
+_ = ptr;

@@ -500,10 +503,10 @@

When you use an if statement, you use a pair of pipes to unwrap the optional value, and use this “unwrapped object” inside the if block. Using the example below as a reference, if the object num is null, then, the code inside the if statement is not executed. Otherwise, the if statement will unwrap the object num into the not_null_num object. This not_null_num object is guaranteed to be not null inside the scope of the if statement.

-
const num: ?i32 = 5;
-if (num) |not_null_num| {
-    try stdout.print("{d}\n", .{not_null_num});
-}
+
const num: ?i32 = 5;
+if (num) |not_null_num| {
+    try stdout.print("{d}\n", .{not_null_num});
+}
5
@@ -512,9 +515,9 @@

The idea behind the orelse keyword is: if the expression on the left side result in a not-null value, then, this not-null value is used. However, if this expression on the left side result in a null value, then, the value of the expression on the right side is used instead.

Looking at the example below, since the x object is currently null, the orelse decided to use the alternative value, which is the number 15.

-
const x: ?i32 = null;
-const dbl = (x orelse 15) * 2;
-try stdout.print("{d}\n", .{dbl});
+
const x: ?i32 = null;
+const dbl = (x orelse 15) * 2;
+try stdout.print("{d}\n", .{dbl});
30
@@ -522,18 +525,18 @@

You can use the if statement or the orelse keyword, when you want to solve (or deal with) this null value. However, if there is no clear solution to this null value, and the most logic and sane path is to simply panic and raise a loud error in your program when this null value is encountered, you can use the ? method of your optional object.

In essence, when you use this ? method, the optional object is unwrapped. If a not-null value is found in the optional object, then, this not-null value is used. Otherwise, the unreachable keyword is used. You can read more about this unreacheable keyword at the official documentation1. But in essence, when you build your Zig source code using the build modes ReleaseSafe or Debug, this unreacheable keyword causes the program to panic and raise an error during runtime, like in the example below:

-
const std = @import("std");
-const stdout = std.io.getStdOut().writer();
-fn return_null(n: i32) ?i32 {
-    if (n == 5) return null;
-    return n;
-}
-
-pub fn main() !void {
-    const x: i32 = 5;
-    const y: ?i32 = return_null(x);
-    try stdout.print("{d}\n", .{y.?});
-}
+
const std = @import("std");
+const stdout = std.io.getStdOut().writer();
+fn return_null(n: i32) ?i32 {
+    if (n == 5) return null;
+    return n;
+}
+
+pub fn main() !void {
+    const x: i32 = 5;
+    const y: ?i32 = return_null(x);
+    try stdout.print("{d}\n", .{y.?});
+}
thread 12767 panic: attempt to use null value
 p7.zig:12:34: 0x103419d in main (p7):
diff --git a/docs/Chapters/09-data-structures.html b/docs/Chapters/09-data-structures.html
index 75cbf5a3..c556478d 100644
--- a/docs/Chapters/09-data-structures.html
+++ b/docs/Chapters/09-data-structures.html
@@ -599,6 +599,10 @@ 

std.debug.print("Value: {d}\n", .{kv.value_ptr.*}); } }

+
+
Key: 54321 | Value: 89Key: 50050 | Value: 55Key: 5
+  57709 | Value: 41
+

Key: 54321 | Value: 89
 Key: 50050 | Value: 55
@@ -606,10 +610,10 @@ 

-
var kit = hash_table.keyIterator();
-while (kit.next()) |key| {
-    std.debug.print("Key: {d}\n", .{key.*});
-}
+
var kit = hash_table.keyIterator();
+while (kit.next()) |key| {
+    std.debug.print("Key: {d}\n", .{key.*});
+}

Key: 54321
 Key: 50050
@@ -630,9 +634,9 @@ 

This means that, with swapRemove() you remove the value from the hashtable, but you do not preserve the order in which the values were inserted into the structure. While orderedRemove() is able to retain the order in which these values were inserted.

But instead of providing an index as input to swapRemove() or orderedRemove(), like I described at Section 11.1.4, these methods here in an ArrayHashMap take a key as input, like the remove() method from a HashMap object. If you want to provide an index as input, instead of a key, you should use the swapRemoveAt() and orderedRemoveAt() methods.

-
var hash_table = AutoArrayHashMap(u32, u16)
-    .init(allocator);
-defer hash_table.deinit();
+
var hash_table = AutoArrayHashMap(u32, u16)
+    .init(allocator);
+defer hash_table.deinit();
@@ -640,33 +644,33 @@

<

One thing that you will notice in the other two types of hashtables that I have presented over the last sections, is that neither of them accepts a slice data type in their keys. What this means is that you cannot use a slice value to represent a key in these types of hashtable.

The most obvious consequence of this, is that you cannot use strings as keys in these hashtables. But it is extremely common to use strings as keys in hashtables.

Take this very simple Javascript code snippet as an example. We are creating a simple hashtable object named people. Then, we add a new entry to this hashtable, which is identified by the string 'Pedro'. This string is the key in this case, while the object containing different personal information such as age, height and city, is the value to be stored in the hashtable.

-
var people = new Object();
-people['Pedro'] = {
-    'age': 25,
-    'height': 1.67,
-    'city': 'Belo Horizonte'
-};
+
var people = new Object();
+people['Pedro'] = {
+    'age': 25,
+    'height': 1.67,
+    'city': 'Belo Horizonte'
+};

This pattern of using strings as keys is very common in all sorts of situations. That is why the Zig Standard Library offers a specific type of hashtable for this purpose, which is created through the StringHashMap() function. This function creates a hashtable that uses strings as keys. The only input of this function is the data type of the values that will be stored into this hashtable.

In the example below, I’m creating a hashtable to store the ages of different people. Each key in this hashtable is represented by the name of each person, while the value stored in the hashtable is the age of this person identified by the key.

That is why I provide the u8 data type (which is the data type used by the age values) as input to this StringHashMap() function. As the result, it creates a hashtable that uses string values as keys, and, that stores u8 values in it. Notice that an allocator object is provided at the init() method of the resulting object from the StringHashMap() function.

-
const std = @import("std");
-pub fn main() !void {
-    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
-    const allocator = gpa.allocator();
-    var ages = std.StringHashMap(u8).init(allocator);
-    defer ages.deinit();
-
-    try ages.put("Pedro", 25);
-    try ages.put("Matheus", 21);
-    try ages.put("Abgail", 42);
-
-    var it = ages.iterator();
-    while (it.next()) |kv| {
-        std.debug.print("Key: {s} | ", .{kv.key_ptr.*});
-        std.debug.print("Age: {d}\n", .{kv.value_ptr.*});
-    }
-}
+
const std = @import("std");
+pub fn main() !void {
+    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
+    const allocator = gpa.allocator();
+    var ages = std.StringHashMap(u8).init(allocator);
+    defer ages.deinit();
+
+    try ages.put("Pedro", 25);
+    try ages.put("Matheus", 21);
+    try ages.put("Abgail", 42);
+
+    var it = ages.iterator();
+    while (it.next()) |kv| {
+        std.debug.print("Key: {s} | ", .{kv.key_ptr.*});
+        std.debug.print("Age: {d}\n", .{kv.value_ptr.*});
+    }
+}
Key: Pedro | Age: 25
 Key: Abgail | Age: 42
@@ -679,7 +683,7 @@ 

Section 11.2.5. And you can also get values from the hashtable by using the same get() method. Like its ArrayHashMap brother, to delete values from this specific type of hashtable, we also use the orderedRemove() and swapRemove() methods, with the same effects that I have described at Section 11.2.4.

If we take the code example that was exposed at Section 11.2.5, we can achieve the exact same result with StringArrayHashMap():

-
var ages = std.StringArrayHashMap(u8).init(allocator);
+
var ages = std.StringArrayHashMap(u8).init(allocator);

@@ -722,24 +726,24 @@

Thus, if we have used a doubly linked list, we can use the insertBefore() method to store the pointer to the input node in the prev attribute. This would put the input node as the “previous node”, or, the node before the current node. In contrast, the insertAfter() method puts the pointer created to the input node in the next attribute of the current node, and as result, the input node becomes the “next node” of the current node.

Since we are using a singly linked list in this example, we have only the insertAfter() method available in the node objects that we create from our Lu32 type.

-
const std = @import("std");
-const SinglyLinkedList = std.SinglyLinkedList;
-const Lu32 = SinglyLinkedList(u32);
-
-pub fn main() !void {
-    var list = Lu32{};
-    var one = Lu32.Node{ .data = 1 };
-    var two = Lu32.Node{ .data = 2 };
-    var three = Lu32.Node{ .data = 3 };
-    var four = Lu32.Node{ .data = 4 };
-    var five = Lu32.Node{ .data = 5 };
-
-    list.prepend(&two); // {2}
-    two.insertAfter(&five); // {2, 5}
-    list.prepend(&one); // {1, 2, 5}
-    two.insertAfter(&three); // {1, 2, 3, 5}
-    three.insertAfter(&four); // {1, 2, 3, 4, 5}
-}
+
const std = @import("std");
+const SinglyLinkedList = std.SinglyLinkedList;
+const Lu32 = SinglyLinkedList(u32);
+
+pub fn main() !void {
+    var list = Lu32{};
+    var one = Lu32.Node{ .data = 1 };
+    var two = Lu32.Node{ .data = 2 };
+    var three = Lu32.Node{ .data = 3 };
+    var four = Lu32.Node{ .data = 4 };
+    var five = Lu32.Node{ .data = 5 };
+
+    list.prepend(&two); // {2}
+    two.insertAfter(&five); // {2, 5}
+    list.prepend(&one); // {1, 2, 5}
+    two.insertAfter(&three); // {1, 2, 3, 5}
+    three.insertAfter(&four); // {1, 2, 3, 4, 5}
+}

There are other methods available from the linked list object, depending if this object is a singly linked list or a doubly linked list, that might be very useful for you. You can find a summary of them in the bullet points below:

    @@ -756,30 +760,30 @@

    <

    Zig introduces a new data structure called MultiArrayList(). It is a different version of the dynamic array that we have introduced at Section 11.1. The difference between this structure and the ArrayList() that we know from Section 11.1, is that MultiArrayList() creates a separate dynamic array for each field of the struct that you provide as input.

    Consider the following code example. We create a new custom struct called Person. This struct contains three different data members, or, three different fields. As consequence, when we provide this Person data type as input to MultiArrayList(), this creates a “struct of three different arrays” called PersonArray. In other words, this PersonArray is a struct that contains three internal dynamic arrays in it. One array for each field found in the Person struct definition.

    -
    const std = @import("std");
    -const Person = struct {
    -    name: []const u8,
    -    age: u8,
    -    height: f32,
    -};
    -const PersonArray = std.MultiArrayList(Person);
    -
    -pub fn main() !void {
    -    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    -    const allocator = gpa.allocator();
    -    var people = PersonArray{};
    -    defer people.deinit(allocator);
    -
    -    try people.append(allocator, .{
    -        .name = "Auguste", .age = 15, .height = 1.54
    -    });
    -    try people.append(allocator, .{
    -        .name = "Elena", .age = 26, .height = 1.65
    -    });
    -    try people.append(allocator, .{
    -        .name = "Michael", .age = 64, .height = 1.87
    -    });
    -}
    +
    const std = @import("std");
    +const Person = struct {
    +    name: []const u8,
    +    age: u8,
    +    height: f32,
    +};
    +const PersonArray = std.MultiArrayList(Person);
    +
    +pub fn main() !void {
    +    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    +    const allocator = gpa.allocator();
    +    var people = PersonArray{};
    +    defer people.deinit(allocator);
    +
    +    try people.append(allocator, .{
    +        .name = "Auguste", .age = 15, .height = 1.54
    +    });
    +    try people.append(allocator, .{
    +        .name = "Elena", .age = 26, .height = 1.65
    +    });
    +    try people.append(allocator, .{
    +        .name = "Michael", .age = 64, .height = 1.87
    +    });
    +}

    In other words, instead of creating an array of “persons”, the MultiArrayList() function creates a “struct of arrays”. Each data member of this struct is a different array that stores the values of a specific field from the Person values that were added (or, appended) to this “struct of arrays”. One important detail is that each of these separate internal arrays stored inside PersonArray are dynamic arrays. This means that these arrays can grow in capacity automatically as needed, to accomodate more values.

    The Figure 11.5 exposed below presents a diagram that describes the PersonArray struct that we have created in the previous code example. Notice that the values of the data members present in each of the three Person values that we have appended into the PersonArray object , are scattered across three different internal arrays of the PersonArray object.

    @@ -795,9 +799,9 @@

    <

    You can easily access each of these arrays separately, and iterate over the values of each array. For that, you will need to call the items() method from the PersonArray object, and provide as input to this method, the name of the field that you want to iterate over. If you want to iterate through the .age array for example, then, you need to call items(.age) from the PersonArray object, like in the example below:

    -
    for (people.items(.age)) |*age| {
    -    try stdout.print("Age: {d}\n", .{age.*});
    -}
    +
    for (people.items(.age)) |*age| {
    +    try stdout.print("Age: {d}\n", .{age.*});
    +}
    Age: 15
     Age: 26
    @@ -806,15 +810,15 @@ 

    <

    In this example we are calling the items() method directly from the PersonArray object. However, it is recommended on most situations to call this items() method from a “slice object”, which you can create from the slice() method. The reason for this is that calling items() multiple times have better performance if you use a slice object.

    Therefore, if you are planning to access only one of the internal arrays from your “multi array struct”, it is fine to call items() directly from the multi array object. But if you need to access many of the internal arrays from your “multi array struct”, then, you will likely need to call items() more than once, and, in such circumstance, is better to call items() through a slice object. The example below demonstrates the use of such object:

    -
    var slice = people.slice();
    -for (slice.items(.age)) |*age| {
    -    age.* += 10;
    -}
    -for (slice.items(.name), slice.items(.age)) |*n,*a| {
    -    try stdout.print(
    -        "Name: {s}, Age: {d}\n", .{n.*, a.*}
    -    );
    -}
    +
    var slice = people.slice();
    +for (slice.items(.age)) |*age| {
    +    age.* += 10;
    +}
    +for (slice.items(.name), slice.items(.age)) |*n,*a| {
    +    try stdout.print(
    +        "Name: {s}, Age: {d}\n", .{n.*, a.*}
    +    );
    +}
    Name: Auguste, Age: 25
     Name: Elena, Age: 36
    diff --git a/docs/Chapters/09-error-handling.html b/docs/Chapters/09-error-handling.html
    index 2adad9db..597d0a92 100644
    --- a/docs/Chapters/09-error-handling.html
    +++ b/docs/Chapters/09-error-handling.html
    @@ -468,6 +468,10 @@ 

    error_value == A.OutOfMemory ); }

    +
    +
    1/1 file10459ffd0e21.test.coerce error value...OKA
    +  All 1 tests passed.
    +
    @@ -495,14 +499,14 @@

    Look at the code example below. Once again, we go back to the previous example where we were trying to open a file that doesn’t exist in my computer, but this time, I use catch to actually implement a logic to handle the error, instead of just stopping the execution right away.

    More specifically, in this example, I’m using a logger object to record some logs into the system, before I return the error, and stop the execution of the program. For example, this could be some part of the codebase of a complex system that I do not have full control over, and I want to record these logs before the program crashes, so that I can debug it later (e.g. maybe I cannot compile the full program, and properly debug it with a debugger. So, these logs might be a valid strategy to surpass this barrier).

    -
    const dir = std.fs.cwd();
    -const file = dir.openFile(
    -    "doesnt_exist.txt", .{}
    -) catch |err| {
    -    logger.record_context();
    -    logger.log_error(err);
    -    return err;
    -};
    +
    const dir = std.fs.cwd();
    +const file = dir.openFile(
    +    "doesnt_exist.txt", .{}
    +) catch |err| {
    +    logger.record_context();
    +    logger.log_error(err);
    +    return err;
    +};

    Therefore, we use catch to create a block of expressions that will handle the error. I can return the error value from this block of expressions, like I did in the above example, which, will make the program enter in panic mode, and, stop the execution. But I could also, return a valid value from this block of code, which would be stored in the file object.

    Notice that, instead of writing the keyword before the expression that might return the error, like we do with try, we write catch after the expression. We can open the pair of pipes (|), which captures the error value returned by the expression, and makes this error value available in the scope of the catch block as the object named err. In other words, because I wrote |err| in the code, I can access the error value returned by the expression, by using the err object.

    @@ -510,7 +514,7 @@

    The Zig official language reference, provides a great example of this “default value” strategy with catch. This example is reproduced below. Notice that we are trying to parse some unsigned integer from a string object named str. In other words, this function is trying to transform an object of type []const u8 (i.e. an array of characters, a string, etc.) into an object of type u64.

    But this parsing process done by the function parseU64() may fail, resulting in a runtime error. The catch keyword used in this example provides an alternative value (13) to be used in case this parseU64() function raises an error. So, the expression below essentially means: “Hey! Please, parse this string into a u64 for me, and store the results into the object number. But, if an error occurs, then, use the value 13 instead”.

    -
    const number = parseU64(str, 10) catch 13;
    +
    const number = parseU64(str, 10) catch 13;

    So, at the end of this process, the object number will contain either a u64 integer that was parsed successfully from the input string str, or, if an error occurs in the parsing process, it will contain the u64 value 13 that was provided by the catch keyword as the “default”, or, the “alternative” value.

    @@ -521,30 +525,30 @@

    <

    This means that, if the parseU64() expression returns a valid value, this value becomes available inside the scope of this “if branch” (i.e. the “true branch”) through the object that we listed inside the pair of pipe character (|), which is the object number.

    If an error occurs, we can use an “else branch” (or the “false branch”) of the if statement to handle the error. In the example below, we are using the else in the if statement to unwrap the error value (that was returned by parseU64()) into the err object, and handle the error.

    -
    if (parseU64(str, 10)) |number| {
    -    // do something with `number` here
    -} else |err| {
    -    // handle the error value.
    -}
    +
    if (parseU64(str, 10)) |number| {
    +    // do something with `number` here
    +} else |err| {
    +    // handle the error value.
    +}

    Now, if the expression that you are executing returns different types of error values, and you want to take a different action in each of these types of error values, the try and catch keywords, and the if statement strategy, becomes limited.

    For this type of situation, the official documentation of the language suggests the use of a switch statement together with an if statement (Zig Software Foundation 2024b). The basic idea is, to use the if statement to execute the expression, and use the “else branch” to pass the error value to a switch statement, where you define a different action for each type of error value that might be returned by the expression executed in the if statement.

    The example below demonstrates this idea. We first try to add (or register) a set of tasks to a queue. If this “registration process” occurs well, we then try to distribute these tasks across the workers of our system. But if this “registration process” returns an error value, we then use a switch statement in the “else branch” to handle each possible error value.

    -
    if (add_tasks_to_queue(&queue, tasks)) |_| {
    -    distribute_tasks(&queue);
    -} else |err| switch (err) {
    -    error.InvalidTaskName => {
    -        // do something
    -    },
    -    error.TimeoutTooBig => {
    -        // do something
    -    },
    -    error.QueueNotFound => {
    -        // do something
    -    },
    -    // and all the other error options ...
    -}
    +
    if (add_tasks_to_queue(&queue, tasks)) |_| {
    +    distribute_tasks(&queue);
    +} else |err| switch (err) {
    +    error.InvalidTaskName => {
    +        // do something
    +    },
    +    error.TimeoutTooBig => {
    +        // do something
    +    },
    +    error.QueueNotFound => {
    +        // do something
    +    },
    +    // and all the other error options ...
    +}
    @@ -554,14 +558,14 @@

    The basic idea is to provide an expression to the errdefer keyword. Then, errdefer executes this expression if, and only if, an error occurs during the execution of the current scope. In the example below, we are using an allocator object (that we have presented at Section 3.3) to create a new User object. If we are successful in creating and registering this new user, this create_user() function will return this new User object as its return value.

    However, if for some reason, an error value is generated by some expression that is after the errdefer line, for example, in the db.add(user) expression, the expression registered by errdefer get’s executed before the error value is returned from the function, and before the program enters in panic mode and stops the current execution.

    -
    fn create_user(db: Database, allocator: Allocator) !User {
    -    const user = try allocator.create(User);
    -    errdefer allocator.destroy(user);
    -
    -    // Register new user in the Database.
    -    _ = try db.register_user(user);
    -    return user;
    -}
    +
    fn create_user(db: Database, allocator: Allocator) !User {
    +    const user = try allocator.create(User);
    +    errdefer allocator.destroy(user);
    +
    +    // Register new user in the Database.
    +    _ = try db.register_user(user);
    +    return user;
    +}

    By using errdefer to destroy the user object that we have just created, we guarantee that the memory allocated for this user object get’s freed, before the execution of the program stops. Because if the expression try db.add(user) returns an error value, the execution of our program stops, and we lose all references and control over the memory that we have allocated for the user object. As a result, if we do not free the memory associated with the user object before the program stops, we cannot free this memory anymore. We simply lose our chance to do the right thing. That is why errdefer is essential in this situation.

    Just to state clearly the differences between defer and errdefer (which I described at Section 2.1.3 and Section 2.1.4), it might be worth to discuss the subject a bit further. You might still have the question “why use errdefer if we can use defer instead?” in your mind.

    @@ -581,30 +585,30 @@

    The union LakeTarget defined below allows the lake_target argument of send_event() to be either an object of type AzureBlob, or type AmazonS3, or type GoogleGCP. This union allows the send_event() function to receive an object of any of these three types as input in the lake_target argument.

    Remember that each of these three types (AmazonS3, GoogleGCP and AzureBlob) are separate structs that we have defined in our source code. So, at first glance, they are separate data types in our source code. But is the union keyword that unifies them into a single data type called LakeTarget.

    -
    const LakeTarget = union {
    -    azure: AzureBlob,
    -    amazon: AmazonS3,
    -    google: GoogleGCP,
    -};
    -
    -fn send_event(
    -    event: Event,
    -    lake_target: LakeTarget
    -) bool {
    -    // body of the function ...
    -}
    +
    const LakeTarget = union {
    +    azure: AzureBlob,
    +    amazon: AmazonS3,
    +    google: GoogleGCP,
    +};
    +
    +fn send_event(
    +    event: Event,
    +    lake_target: LakeTarget
    +) bool {
    +    // body of the function ...
    +}

    An union definition is composed by a list of data members. Each data member is of a specific data type. In the example above, the LakeTarget union have three data members (azure, amazon, google). When you instantiate an object that uses an union type, you can only use one of its data members in this instantiation.

    You could also interpret this as: only one data member of an union type can be activated at a time, the other data members remain deactivated and unaccessible. For example, if you create a LakeTarget object that uses the azure data member, you can no longer use or access the data members google or amazon. It is like if these other data members didn’t exist at all in the LakeTarget type.

    You can see this logic in the example below. Notice that, we first instantiate the union object using the azure data member. As a result, this target object contains only the azure data member inside of it. Only this data member is active in this object. That is why the last line in this code example is invalid. Because we are trying to instantiate the data member google, which is currently inactive for this target object, and as a result, the program enters in panic mode warning us about this mistake through a loud error message.

    -
    var target = LakeTarget {
    -    .azure = AzureBlob.init()
    -};
    -// Only the `azure` data member exist inside
    -// the `target` object, and, as a result, this
    -// line below is invalid:
    -target.google = GoogleGCP.init();
    +
    var target = LakeTarget {
    +    .azure = AzureBlob.init()
    +};
    +// Only the `azure` data member exist inside
    +// the `target` object, and, as a result, this
    +// line below is invalid:
    +target.google = GoogleGCP.init();
    thread 2177312 panic: access of union field 'google' while
         field 'azure' is active:
    @@ -613,21 +617,21 @@ 

    So, when you instantiate an union object, you must choose one of the data types (or, one of the data members) listed in the union type. In the example above, I choose to use the azure data member, and, as a result, all other data members were automatically deactivated, and you can no longer use them after you instantiate the object.

    You can activate another data member by completely redefining the entire enum object. In the example below, I initially use the azure data member. But then, I redefine the target object to use a new LakeTarget object, which uses the google data member.

    -
    var target = LakeTarget {
    -    .azure = AzureBlob.init()
    -};
    -target = LakeTarget {
    -    .google = GoogleGCP.init()
    -};
    +
    var target = LakeTarget {
    +    .azure = AzureBlob.init()
    +};
    +target = LakeTarget {
    +    .google = GoogleGCP.init()
    +};

    A curious fact about union types, is that, at first, you cannot use them in switch statements (which were presented at Section 2.1.2). In other words, if you have an object of type LakeTarget for example, you cannot give this object as input to a switch statement.

    But what if you really need to do so? What if you actually need to provide an “union object” to a switch statement? The answer to this question relies on another special type in Zig, which are the tagged unions. To create a tagged union, all you have to do is to add an enum type into your union declaration.

    As an example of a tagged union in Zig, take the Registry type exposed below. This type comes from the grammar.zig module2 from the Zig repository. This union type lists different types of registries. But notice this time, the use of (enum) after the union keyword. This is what makes this union type a tagged union. By being a tagged union, an object of this Registry type can be used as input in a switch statement. This is all you have to do. Just add (enum) to your union declaration, and you can use it in switch statements.

    -
    pub const Registry = union(enum) {
    -    core: CoreRegistry,
    -    extension: ExtensionRegistry,
    -};
    +
    pub const Registry = union(enum) {
    +    core: CoreRegistry,
    +    extension: ExtensionRegistry,
    +};
    diff --git a/docs/Chapters/10-stack-project.html b/docs/Chapters/10-stack-project.html index 5aa73bba..b19573e2 100644 --- a/docs/Chapters/10-stack-project.html +++ b/docs/Chapters/10-stack-project.html @@ -369,31 +369,35 @@

    test "test comptime" { _ = twice(5678); }

    +
    +
    1/1 file1054863994c6f.test.test comptime...OKAll 1
    +  1 tests passed.
    +

    But what if we provide a number that is not compile-time known to this function? For example, we might provide a different input value to this function depending on the target OS of our compilation process. The code example below demonstrates such case.

    Because the value of the object n is determined at runtime, we cannot provide this object as input to the twice() function. The zig compiler will not allow it, because we marked the num argument as a “comptime argument”. That is why the zig compiler raises the compile-time error exposed below:

    -
    const builtin = @import("builtin");
    -fn twice(comptime num: u32) u32 {
    -    return num * 2;
    -}
    -test "test comptime" {
    -    var n: u32 = undefined;
    -    if (builtin.target.os.tag == .windows) {
    -        n = 1234;
    -    } else {
    -        n = 5678;
    -    }
    -    _ = twice(n);
    -}
    +
    const builtin = @import("builtin");
    +fn twice(comptime num: u32) u32 {
    +    return num * 2;
    +}
    +test "test comptime" {
    +    var n: u32 = undefined;
    +    if (builtin.target.os.tag == .windows) {
    +        n = 1234;
    +    } else {
    +        n = 5678;
    +    }
    +    _ = twice(n);
    +}
    t.zig:12:16: error: runtime-known argument passed to comptime parameter 

    Comptime arguments are frequently used on functions that return some sort of generic structure. In fact, comptime is the essence (or the basis) to make generics in Zig. We are going to talk more about generics at Section 12.2.

    For now, let’s take a look at this code example from Seguin (2024). You can see that this IntArray() function have one argument named length. This argument is marked as comptime, and receives a value of type usize as input. So the value given to this argument must be compile-time known. We can also see that this function returns an array of i64 values as output.

    -
    fn IntArray(comptime length: usize) type {
    -    return [length]i64;
    -}
    +
    fn IntArray(comptime length: usize) type {
    +    return [length]i64;
    +}

    Now, the key component of this function is the length argument. This argument is used to determine the size of the array that is produced by the function. Let’s think about the consequences of that. If the size of the array is dependent on the value assigned to the length argument, this means that the data type of the output of the function depends on the value of this length argument.

    Let this statement sink for a bit in your mind. As I described at Section 1.2.2, Zig is a strongly-typed language, especially on function declarations. So every time we write a function in Zig, we have to annotate the data type of the value returned by the function. But how can we do that, if this data type depends on the value given to the argument of the function?

    @@ -409,18 +413,22 @@

    (Zig Software Foundation 2024). We are executing the same fibonacci() function both at runtime, and, at compile-time. The function is by default executed at runtime, but because we use the comptime keyword at the second “try expression”, this expression is executed at compile-time.

    This might be a bit confusing for some people. Yes! When I say that this expression is executed at compile-time, I mean that this expression is compiled and executed while the zig compiler is compiling your Zig source code.

    -
    const expect = @import("std").testing.expect;
    -fn fibonacci(index: u32) u32 {
    -    if (index < 2) return index;
    -    return fibonacci(index - 1) + fibonacci(index - 2);
    -}
    -
    -test "fibonacci" {
    -    // test fibonacci at run-time
    -    try expect(fibonacci(7) == 13);
    -    // test fibonacci at compile-time
    -    try comptime expect(fibonacci(7) == 13);
    -}
    +
    const expect = @import("std").testing.expect;
    +fn fibonacci(index: u32) u32 {
    +    if (index < 2) return index;
    +    return fibonacci(index - 1) + fibonacci(index - 2);
    +}
    +
    +test "fibonacci" {
    +    // test fibonacci at run-time
    +    try expect(fibonacci(7) == 13);
    +    // test fibonacci at compile-time
    +    try comptime expect(fibonacci(7) == 13);
    +}
    +
    +
    1/1 file10548bb87337.test.fibonacci...OKAll 1 test
    +  ts passed.
    +

    A lot of your Zig source code might be potentially executed at compile-time, because the zig compiler can figure it out the output of some expressions. Especially if these expressions depends only at compile-time known values. We have talked about this at Section 3.1.1.

    But when you use the comptime keyword on an expression, there is no “it might be executed at compile-time” anymore. With the comptime keyword you are ordering the zig compiler to execute this expression at compile-time. You are imposing this rule, it is guaranteed that the compiler will always execute it at compile-time. Or, at least, the compiler will try to execute it. If the compiler cannot execute the expression for whatever reason, the compiler will raise a compilation error.

    @@ -430,22 +438,26 @@

    Blocks were described at Section 1.7. When you apply the comptime keyword over a block of expressions, you get essentially the same effect when you apply this keyword to a single expression. That is, the entire block of expressions is executed at compile-time by the zig compiler.

    In the example below, we mark the block labeled of blk as a comptime block, and, therefore, the expressions inside this block are executed at compile-time.

    -
    const expect = @import("std").testing.expect;
    -fn fibonacci(index: u32) u32 {
    -    if (index < 2) return index;
    -    return fibonacci(index - 1) + fibonacci(index - 2);
    -}
    -
    -test "fibonacci in a block" {
    -    const x = comptime blk: {
    -        const n1 = 5;
    -        const n2 = 2;
    -        const n3 = n1 + n2;
    -        try expect(fibonacci(n3) == 13);
    -        break :blk n3;
    -    };
    -    _ = x;
    -}
    +
    const expect = @import("std").testing.expect;
    +fn fibonacci(index: u32) u32 {
    +    if (index < 2) return index;
    +    return fibonacci(index - 1) + fibonacci(index - 2);
    +}
    +
    +test "fibonacci in a block" {
    +    const x = comptime blk: {
    +        const n1 = 5;
    +        const n2 = 2;
    +        const n3 = n1 + n2;
    +        try expect(fibonacci(n3) == 13);
    +        break :blk n3;
    +    };
    +    _ = x;
    +}
    +
    +
    1/1 file105482dc0b880.test.fibonacci in a block...
    +  .OKAll 1 tests passed.
    +

    @@ -460,23 +472,30 @@

    Because we have used this type keyword in the T argument, we are telling the zig compiler that this T argument will receive some data type as input. Also notice the use of the comptime keyword in this argument. As I described at Section 12.1, every time you use this keyword in a function argument, this means that the value of this argument must be known at compile-time. This makes sense, right? Because there is no data type that is not known at compile-time.

    Think about this. Every data type that you will ever write is always known at compile-time. Especially because data types are an essential information for the compiler to actually compile your source code. Having this in mind, makes sense to mark this argument as a comptime argument.

    -
    fn max(comptime T: type, a: T, b: T) T {
    -    return if (a > b) a else b;
    -}
    +
    fn max(comptime T: type, a: T, b: T) T {
    +    return if (a > b) a else b;
    +}
    +
    +
    All 0 tests passed.
    +

    Also notice that the value of the T argument is actually used to define the data type of the other arguments in the function, a and b, and also at the return type annotation of the function. That is, the data type of these arguments (a and b), and, the return data type of the function itself, are determined by the input value given to the T argument.

    As a result, we have a generic function that works with different data types. For example, I can provide u8 values to this max() function, and it will work as expected. But if I provide f64 values instead, it will also work as expected. Without a generic function, I would have to write a different max() function for each one of the data types that I wanted to use. This generic function provides a very useful shortcut for us.

    -
    const std = @import("std");
    -fn max(comptime T: type, a: T, b: T) T {
    -    return if (a > b) a else b;
    -}
    -test "test max" {
    -    const n1 = max(u8, 4, 10);
    -    std.debug.print("Max n1: {d}\n", .{n1});
    -    const n2 = max(f64, 89.24, 64.001);
    -    std.debug.print("Max n2: {d}\n", .{n2});
    -}
    +
    const std = @import("std");
    +fn max(comptime T: type, a: T, b: T) T {
    +    return if (a > b) a else b;
    +}
    +test "test max" {
    +    const n1 = max(u8, 4, 10);
    +    std.debug.print("Max n1: {d}\n", .{n1});
    +    const n2 = max(f64, 89.24, 64.001);
    +    std.debug.print("Max n2: {d}\n", .{n2});
    +}
    +
    +
    1/1 file105482071daf3.test.test max...Max n1: 10Ma
    +  ax n2: 89.24OKAll 1 tests passed.
    +
    Max n1: 10
     Max n2: 89.24
    @@ -514,24 +533,24 @@

    -
    const std = @import("std");
    -const Allocator = std.mem.Allocator;
    -const Stack = struct {
    -    items: []u32,
    -    capacity: usize,
    -    length: usize,
    -    allocator: Allocator,
    -
    -    pub fn init(allocator: Allocator, capacity: usize) !Stack {
    -        var buf = try allocator.alloc(u32, capacity);
    -        return .{
    -            .items = buf[0..],
    -            .capacity = capacity,
    -            .length = 0,
    -            .allocator = allocator,
    -        };
    -    }
    -};
    +
    const std = @import("std");
    +const Allocator = std.mem.Allocator;
    +const Stack = struct {
    +    items: []u32,
    +    capacity: usize,
    +    length: usize,
    +    allocator: Allocator,
    +
    +    pub fn init(allocator: Allocator, capacity: usize) !Stack {
    +        var buf = try allocator.alloc(u32, capacity);
    +        return .{
    +            .items = buf[0..],
    +            .capacity = capacity,
    +            .length = 0,
    +            .allocator = allocator,
    +        };
    +    }
    +};

    12.4.1 Implementing the push operation

    @@ -543,22 +562,22 @@

    -
    pub fn push(self: *Stack, val: u32) !void {
    -    if ((self.length + 1) > self.capacity) {
    -        var new_buf = try self.allocator.alloc(
    -            u32, self.capacity * 2
    -        );
    -        @memcpy(
    -            new_buf[0..self.capacity], self.items
    -        );
    -        self.allocator.free(self.items);
    -        self.items = new_buf;
    -        self.capacity = self.capacity * 2;
    -    }
    -
    -    self.items[self.length] = val;
    -    self.length += 1;
    -}
    +
    pub fn push(self: *Stack, val: u32) !void {
    +    if ((self.length + 1) > self.capacity) {
    +        var new_buf = try self.allocator.alloc(
    +            u32, self.capacity * 2
    +        );
    +        @memcpy(
    +            new_buf[0..self.capacity], self.items
    +        );
    +        self.allocator.free(self.items);
    +        self.items = new_buf;
    +        self.capacity = self.capacity * 2;
    +    }
    +
    +    self.items[self.length] = val;
    +    self.length += 1;
    +}

    After we make sure that we have enough room to store this new value that we are adding to the stack, all we have to do is to assign this value to the top element in this stack, and, increase the value of the length attribute by one. We find the top element in the stack by using the length attribute.

    @@ -568,12 +587,12 @@

    -
    pub fn pop(self: *Stack) void {
    -    if (self.length == 0) return;
    -
    -    self.items[self.length - 1] = undefined;
    -    self.length -= 1;
    -}
    +
    pub fn pop(self: *Stack) void {
    +    if (self.length == 0) return;
    +
    +    self.items[self.length - 1] = undefined;
    +    self.length -= 1;
    +}
    @@ -582,9 +601,9 @@

    -
    pub fn deinit(self: *Stack) void {
    -    self.allocator.free(self.items);
    -}
    +
    pub fn deinit(self: *Stack) void {
    +    self.allocator.free(self.items);
    +}

    @@ -596,56 +615,56 @@

    We do that by using a generic function. Because a generic function can receive a data type as input, and we can pass this data type to the struct definition of our Stack object. Therefore, we can use the generic function to create a Stack object that can store the data type we want. If we want to create a stack structure that stores User values, we pass the User data type to this generic function, and it will create for us the struct definition that describes a Stack object that can store User values in it.

    Look at the code example below. I have omitted some parts of the Stack struct definition for brevity reasons. However, if a specific part of our Stack struct is not exposed here in this example, then it is because this part did not change from the previous example. It remains the same.

    -
    fn Stack(comptime T: type) type {
    -    return struct {
    -        items: []T,
    -        capacity: usize,
    -        length: usize,
    -        allocator: Allocator,
    -        const Self = @This();
    -
    -        pub fn init(allocator: Allocator,
    -                    capacity: usize) !Stack(T) {
    -            var buf = try allocator.alloc(T, capacity);
    -            return .{
    -                .items = buf[0..],
    -                .capacity = capacity,
    -                .length = 0,
    -                .allocator = allocator,
    -            };
    -        }
    -
    -        pub fn push(self: *Self, val: T) !void {
    -        // Truncate the rest of the struct
    -    };
    -}
    +
    fn Stack(comptime T: type) type {
    +    return struct {
    +        items: []T,
    +        capacity: usize,
    +        length: usize,
    +        allocator: Allocator,
    +        const Self = @This();
    +
    +        pub fn init(allocator: Allocator,
    +                    capacity: usize) !Stack(T) {
    +            var buf = try allocator.alloc(T, capacity);
    +            return .{
    +                .items = buf[0..],
    +                .capacity = capacity,
    +                .length = 0,
    +                .allocator = allocator,
    +            };
    +        }
    +
    +        pub fn push(self: *Self, val: T) !void {
    +        // Truncate the rest of the struct
    +    };
    +}

    Notice that we have created a function in this example named Stack(). This function takes a type as input, and passes this type to the struct definition of our Stack object. The data member items is now, an array of type T, which is the data type that we have provided as input to the function. The function argument val in the push() function is now a value of type T too.

    We can just provide a data type to this function, and it will create a definition of a Stack object that can store values of the data type that we have provided. In the example below, we are creating the definition of a Stack object that can store u8 values in it. This definition is stored at the Stacku8 object. This Stacku8 object becomes our new struct, it is the struct that we are going to use to create our Stack object.

    -
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    -const allocator = gpa.allocator();
    -const Stacku8 = Stack(u8);
    -var stack = try Stacku8.init(allocator, 10);
    -defer stack.deinit();
    -try stack.push(1);
    -try stack.push(2);
    -try stack.push(3);
    -try stack.push(4);
    -try stack.push(5);
    -try stack.push(6);
    -
    -std.debug.print("Stack len: {d}\n", .{stack.length});
    -std.debug.print("Stack capacity: {d}\n", .{stack.capacity});
    -
    -stack.pop();
    -std.debug.print("Stack len: {d}\n", .{stack.length});
    -stack.pop();
    -std.debug.print("Stack len: {d}\n", .{stack.length});
    -std.debug.print(
    -    "Stack state: {any}\n",
    -    .{stack.items[0..stack.length]}
    -);
    +
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    +const allocator = gpa.allocator();
    +const Stacku8 = Stack(u8);
    +var stack = try Stacku8.init(allocator, 10);
    +defer stack.deinit();
    +try stack.push(1);
    +try stack.push(2);
    +try stack.push(3);
    +try stack.push(4);
    +try stack.push(5);
    +try stack.push(6);
    +
    +std.debug.print("Stack len: {d}\n", .{stack.length});
    +std.debug.print("Stack capacity: {d}\n", .{stack.capacity});
    +
    +stack.pop();
    +std.debug.print("Stack len: {d}\n", .{stack.length});
    +stack.pop();
    +std.debug.print("Stack len: {d}\n", .{stack.length});
    +std.debug.print(
    +    "Stack state: {any}\n",
    +    .{stack.items[0..stack.length]}
    +);
    Stack len: 6
     Stack capacity: 10
    diff --git a/docs/Chapters/13-image-filter.html b/docs/Chapters/13-image-filter.html
    index 609d19f9..af1fa84c 100644
    --- a/docs/Chapters/13-image-filter.html
    +++ b/docs/Chapters/13-image-filter.html
    @@ -606,7 +606,7 @@ 

    const green_factor: f16 = 0.7152; const blue_factor: f16 = 0.0722; var index: u64 = 0; - while (index < (len - 4)) : (index += 4) { + while (index <= (len - 4)) : (index += 4) { const rf: f16 = @floatFromInt(buffer[index]); const gf: f16 = @floatFromInt(buffer[index + 1]); const bf: f16 = @floatFromInt(buffer[index + 2]); diff --git a/docs/ZigExamples/image_filter/pedro_pascal_filter.png b/docs/ZigExamples/image_filter/pedro_pascal_filter.png index bdce0380b5c0f138546e189851262424517f1c54..45bf4ed35f67ccb92ca00e2d7aedbf290dc9d82e 100644 GIT binary patch delta 45 zcmaE|gX`fAu7(!IEleVfj27EP8<|X{#kv3UJ4AX5bUJP3U;qM7S3j3^P6 - + Introduction to Zig \n\n\n\n \n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria have a bachelor degree in Economics from Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\nan Associate Developer for Apache Spark 3.0 certified by Databricks.\n\n[^blip]: \n\n\nThe author have more than 4 years of experience in the data industry. Developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nbrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer that loves to\nlearn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-49-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.2371+c013f45ad.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang)\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy an eBook or a physical copy\nof the book on Amazon:\n\n\n\n\n\n\n \n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.2371+c013f45ad.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang)\n", + "supporting": [ + "index_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/docs/Chapters/01-zig-weird.html b/docs/Chapters/01-zig-weird.html index ac94c65e..b091a3de 100644 --- a/docs/Chapters/01-zig-weird.html +++ b/docs/Chapters/01-zig-weird.html @@ -405,11 +405,14 @@

    Examples of build systems are CMake, GNU Make, GNU Autoconf and Ninja, which are used to build complex C and C++ projects. With these systems, you can write scripts, which are called “build scripts”. They simply are scripts that describes the necessary steps to compile/build your project.

    However, these are separate tools, that do not belong to C/C++ compilers, like gcc or clang. As a result, in C/C++ projects, you have not only to install and manage your C/C++ compilers, but you also have to install and manage these build systems separately.

    In Zig, we don’t need to use a separate set of tools to build our projects, because a build system is embedded inside the language itself. Therefore, Zig contains a native build system in it, and we can use this build system to write small scripts in Zig, which describes the necessary steps to build/compile our Zig project1. So, everything you need to build a complex Zig project is the zig compiler, and nothing more.

    -

    The second generated file (build.zig.zon) is the Zig package manager configuration file, where you can list and manage the dependencies of your project. Yes, Zig has a package manager (like pip in Python, cargo in Rust, or npm in Javascript) called Zon, and this build.zig.zon file is similar to the package.json file in Javascript projects, or, the Pipfile file in Python projects, or the Cargo.toml file in Rust projects.

    +

    The second generated file (build.zig.zon) is a JSON-like file, in which you can describe your project, and also, declare a set of dependencies of your project that you want to fetch from the internet. In other words, you can use this build.zig.zon file to include a list of external libraries in your project.

    +

    One possible way to include an external Zig library in your project, is to manually build and install the library in your system, and just link your source code with the library at the build step of your project.

    +

    However, if this external Zig library is available on GitHub for example, and it has a valid build.zig.zon file in root folder of the project, which describes the project, you can easily include this library in your project by simply listing this external library in your build.zig.zon file.

    +

    In other words, this build.zig.zon file works similarly to the package.json file in Javascript projects, or the Pipfile file in Python projects, or the Cargo.toml file in Rust projects. You can read more about this specific file in a couple of articles on the internet23, and you can also see the expected schema for this build.zig.zon file in a documentation file inside the official repository of Zig4.

    1.2.2 The file root.zig

    -

    Let’s take a look into the root.zig file. You might have noticed that every line of code with an expression ends with a semicolon (;). This follows the syntax of a C-family programming language2.

    +

    Let’s take a look into the root.zig file. You might have noticed that every line of code with an expression ends with a semicolon (;). This follows the syntax of a C-family programming language5.

    Also, notice the @import() call at the first line. We use this built-in function to import functionality from other Zig modules into our current module. This @import() function works similarly to the #include pre-processor in C or C++, or, to the import statement in Python or Javascript code. In this example, we are importing the std module, which gives you access to the Zig Standard Library.

    In this root.zig file, we can also see how assignments (i.e. creating new objects) are made in Zig. You can create a new object in Zig by using the following syntax (const|var) name = value;. In the example below, we are creating two constant objects (std and testing). At Section 1.4 we talk more about objects in general.

    @@ -430,14 +433,15 @@

    1.2.3 The main.zig file

    Now that we have learned a lot about Zig’s syntax from the root.zig file, let’s take a look at the main.zig file. A lot of the elements we saw in root.zig are also present in main.zig. But there are some other elements that we haven’t seen yet, so let’s dive in.

    First, look at the return type of the main() function in this file. We can see a small change. The return type of the function (void) is accompanied by an exclamation mark (!). This exclamation mark tells us that this main() function might return an error.

    -

    In this example, the main() function can either return void or return an error. This is an interesting feature of Zig. If you write a function and something inside of the body of this function might return an error then you are forced to:

    +

    Is worth noting that, a main() function in Zig is allowed to return nothing (void), or an unsigned 8-bit integer (u8) value, or an error. In other words, you can write your main() function in Zig to return essentially nothing (void), or, if you prefer, you can also write a more C-like main() function, which returns an integer value that usually serves as a “status code” for the process.

    +

    In this example, the return type annotation of main() indicates that this function can either return nothing (void), or return an error. This exclamation mark in the return type annotation is an interesting and powerful feature of Zig. In summary, if you write a function and something inside the body of this function might return an error, then, you are forced to:

      -
    • either add the exclamation mark to the return type of the function and make it clear that this function might return an error
    • -
    • explicitly handle this error inside the function
    • +
    • either add the exclamation mark to the return type of the function and make it clear that this function might return an error.
    • +
    • explicitly handle this error inside the function.

    In most programming languages, we normally handle (or deal with) an error through a try catch pattern. Zig does have both try and catch keywords. But they work a little differently than what you’re probably used to in other languages.

    If we look at the main() function below, you can see that we do have a try keyword on the 5th line. But we do not have a catch keyword in this code. In Zig, we use the try keyword to execute an expression that might return an error, which, in this example, is the stdout.print() expression.

    -

    In essence, the try keyword executes the expression stdout.print(). If this expression returns a valid value, then, the try keyword does nothing. It only passes the value forward. But if the expression does return an error, then, the try keyword just unwrap the error value, and return this error from the function and also prints the current stack trace to stderr.

    +

    In essence, the try keyword executes the expression stdout.print(). If this expression returns a valid value, then, the try keyword does absolutely nothing. It only passes the value forward. It is like if this try keyword was never there. However, if the expression does return an error, then, the try keyword will unwrap the error value, then, it returns this error from the function and also prints the current stack trace to stderr.

    This might sound weird to you if you come from a high-level language. Because in high-level languages, such as Python, if an error occurs somewhere, this error is automatically returned and the execution of your program will automatically stop even if you don’t want to stop the execution. You are obligated to face the error.

    const std = @import("std");
    @@ -447,9 +451,8 @@ 

    try stdout.print("Hello, {s}!\n", .{"world"}); }

    -

    Another thing that you might have noticed in this code example, is that the main() function is marked with the pub keyword. It marks the main() function as a public function from this module.

    -

    Every function in your Zig module is by default private to this Zig module and can only be called from within the module. Unless, you explicitly mark this function as a public function with the pub keyword. This means that the pub keyword in Zig does essentially the opposite of what the static keyword do in C/C++.

    -

    By making a function “public” you allow other Zig modules to access and call it. A calling Zig module imports the module with the @import() built-in. That makes all public functions from the imported module visible.

    +

    Another thing that you might have noticed in this code example, is that the main() function is marked with the pub keyword. It marks the main() function as a public function from this module. Every function in your Zig module is by default private to this Zig module and can only be called from within the module. Unless, you explicitly mark this function as a public function with the pub keyword.

    +

    If you think about it, this pub keyword in Zig does essentially the opposite of what the static keyword do in C/C++. By making a function “public” you allow other Zig modules to access and call this function. A calling Zig module imports another module by using the @import() built-in function, which makes all public functions from the imported module visible to the calling Zig module.

    1.2.4 Compiling your source code

    @@ -473,7 +476,7 @@

    <

    1.2.6 Important note for Windows users

    -

    First of all, this is a Windows-specific thing, and, therefore, does not apply to other operational systems, such as Linux and MacOs. In summary, if you have a piece of Zig code that includes some global variables whose initialization rely on runtime resources, then, you might have some troubles while trying to compile this Zig code on Windows.

    +

    First of all, this is a Windows-specific thing, and, therefore, does not apply to other operating systems, such as Linux and macOs. In summary, if you have a piece of Zig code that includes some global variables whose initialization rely on runtime resources, then, you might have some troubles while trying to compile this Zig code on Windows.

    An example of that is accessing the stdout (i.e. the standard output of your system), which is usually done in Zig by using the expression std.io.getStdOut(). Thus, if you use this expression to instantiate a global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows, with a “unable to evaluate comptime expression” error message.

    This failure in the compilation process happens because all global variables in Zig are initialized at compile-time. However, operations like accessing the stdout (or opening a file) on Windows depends on resources that are available only at runtime (you will learn more about compile-time versus runtime at Section 3.1.1).

    For example, if you try to compile this code example on Windows, you will likely get the error message exposed below:

    @@ -501,7 +504,7 @@

    }

    Hello
    -

    You can read more details about this Windows-specific limitation at a couple of GitHub issues opened at the official Zig repository. More specifically, the issues 17186 3 and 19864 4.

    +

    You can read more details about this Windows-specific limitation at a couple of GitHub issues opened at the official Zig repository. More specifically, the issues 17186 6 and 19864 7.

    1.2.7 Compiling the entire project

    @@ -526,17 +529,17 @@

    Discord, Slack, Telegram, and others: https://github.com/ziglang/zig/wiki/Community;

Now, one of the best ways to learn Zig is to simply read Zig code. Try to read Zig code often, and things will become more clear. A C/C++ programmer would also probably give you this same tip. Because this strategy really works!

-

Now, where can you find Zig code to read? I personally think that, the best way of reading Zig code is to read the source code of the Zig Standard Library. The Zig Standard Library is available at the lib/std folder5 on the official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.

+

Now, where can you find Zig code to read? I personally think that, the best way of reading Zig code is to read the source code of the Zig Standard Library. The Zig Standard Library is available at the lib/std folder8 on the official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.

Also, a great alternative is to read code from other large Zig codebases, such as:

    -
  1. the Javascript runtime Bun6.
  2. -
  3. the game engine Mach7.
  4. -
  5. a LLama 2 LLM model implementation in Zig8.
  6. -
  7. the financial transactions database tigerbeetle9.
  8. -
  9. the command-line arguments parser zig-clap10.
  10. -
  11. the UI framework capy11.
  12. -
  13. the Language Protocol implementation for Zig, zls12.
  14. -
  15. the event-loop library libxev13.
  16. +
  17. the Javascript runtime Bun9.
  18. +
  19. the game engine Mach10.
  20. +
  21. a LLama 2 LLM model implementation in Zig11.
  22. +
  23. the financial transactions database tigerbeetle12.
  24. +
  25. the command-line arguments parser zig-clap13.
  26. +
  27. the UI framework capy14.
  28. +
  29. the Language Protocol implementation for Zig, zls15.
  30. +
  31. the event-loop library libxev16.

All these assets are available on GitHub, and this is great, because we can use the GitHub search bar in our advantage, to find Zig code that fits our description. For example, you can always include lang:Zig in the GitHub search bar when you are searching for a particular pattern. This will limit the search to only Zig modules.

Also, a great alternative is to consult online resources and documentations. Here is a quick list of resources that I personally use from time to time to learn more about the language each day:

@@ -549,9 +552,9 @@

Read the code written by one of the Zig core team members: https://github.com/kubkon;
  • Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: https://www.youtube.com/@ZigSHOWTIME/videos;
  • -

    Another great strategy to learn Zig, or honestly, to learn any language you want, is to practice it by solving exercises. For example, there is a famous repository in the Zig community called Ziglings14 , which contains more than 100 small exercises that you can solve. It is a repository of tiny programs written in Zig that are currently broken, and your responsibility is to fix these programs, and make them work again.

    -

    A famous tech YouTuber known as The Primeagen also posted some videos (at YouTube) where he solves these exercises from Ziglings. The first video is named “Trying Zig Part 1”15.

    -

    Another great alternative, is to solve the Advent of Code exercises16. There are people that already took the time to learn and solve the exercises, and they posted their solutions on GitHub as well, so, in case you need some resource to compare while solving the exercises, you can look at these two repositories:

    +

    Another great strategy to learn Zig, or honestly, to learn any language you want, is to practice it by solving exercises. For example, there is a famous repository in the Zig community called Ziglings17 , which contains more than 100 small exercises that you can solve. It is a repository of tiny programs written in Zig that are currently broken, and your responsibility is to fix these programs, and make them work again.

    +

    A famous tech YouTuber known as The Primeagen also posted some videos (at YouTube) where he solves these exercises from Ziglings. The first video is named “Trying Zig Part 1”18.

    +

    Another great alternative, is to solve the Advent of Code exercises19. There are people that already took the time to learn and solve the exercises, and they posted their solutions on GitHub as well, so, in case you need some resource to compare while solving the exercises, you can look at these two repositories:

    • https://github.com/SpexGuy/Zig-AoC-Template;
    • https://github.com/fjebaker/advent-of-code-2022;
    • @@ -644,7 +647,7 @@

      1.5 Primitive Data Types

      -

      Zig have many different primitive data types available for you to use. You can see the full list of available data types at the official Language Reference page17.

      +

      Zig have many different primitive data types available for you to use. You can see the full list of available data types at the official Language Reference page20.

      But here is a quick list:

      • Unsigned integers: u8, 8-bit integer; u16, 16-bit integer; u32, 32-bit integer; u64, 64-bit integer; u128, 128-bit integer.
      • @@ -817,7 +820,7 @@

        // This is a string object: const object: []const u8 = "A string object";

    -

    Zig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every sequence of bytes you’re working with, but is not really Zig’s job to fix the encoding of your strings (you can use iconv18 for that). Today, most of the text in our modern world, especially on the web, should be UTF-8 encoded. So if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.

    +

    Zig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every sequence of bytes you’re working with, but is not really Zig’s job to fix the encoding of your strings (you can use iconv21 for that). Today, most of the text in our modern world, especially on the web, should be UTF-8 encoded. So if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.

    Let’s take for example the word “Hello”. In UTF-8, this sequence of characters (H, e, l, l, o) is represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this sequence is 0x48, 0x65, 0x6C, 0x6C, 0x6F. So if I take this sequence of hexadecimal values, and ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then, the text “Hello” will be printed into the terminal:

    const std = @import("std");
    @@ -831,7 +834,7 @@ 

    Hello

    -

    If you want to see the actual bytes that represents a string in Zig, you can use a for loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal value to the terminal. You do that by using a print() statement with the X formatting specifier, like you would normally do with the printf() function19 in C.

    +

    If you want to see the actual bytes that represents a string in Zig, you can use a for loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal value to the terminal. You do that by using a print() statement with the X formatting specifier, like you would normally do with the printf() function22 in C.

    const std = @import("std");
     const stdout = std.io.getStdOut().writer();
    @@ -1027,9 +1030,9 @@ 

    1.9 Safety in Zig

    A general trend in modern low-level programming languages is safety. As our modern world becomes more interconnected with technology and computers, the data produced by all of this technology becomes one of the most important (and also, one of the most dangerous) assets that we have.

    This is probably the main reason why modern low-level programming languages have been giving great attention to safety, especially memory safety, because memory corruption is still the main target for hackers to exploit. The reality is that we don’t have an easy solution for this problem. For now, we only have techniques and strategies that mitigates these problems.

    -

    As Richard Feldman explains on his most recent GOTO conference talk20 , we haven’t figured it out yet a way to achieve true safety in technology. In other words, we haven’t found a way to build software that won’t be exploited with 100% certainty. We can greatly reduce the risks of our software being exploited, by ensuring memory safety for example. But this is not enough to achieve “true safety” territory.

    -

    Because even if you write your program in a “safe language”, hackers can still exploit failures in the operational system where your program is running (e.g. maybe the system where your code is running has a “backdoor exploit” that can still affect your code in unexpected ways), or also, they can exploit the features from the architecture of your computer. A recently found exploit that involves memory invalidation through a feature of “memory tags” present in ARM chips is an example of that (Kim et al. 2024).

    -

    The question is: what have Zig and other languages been doing to mitigate this problem? If we take Rust as an example, Rust is, for the most part21, a memory safe language by enforcing specific rules to the developer. In other words, the key feature of Rust, the borrow checker, forces you to follow a specific logic when you are writing your Rust code, and the Rust compiler will always complain everytime you try to go out of this pattern.

    +

    As Richard Feldman explains on his most recent GOTO conference talk23 , we haven’t figured it out yet a way to achieve true safety in technology. In other words, we haven’t found a way to build software that won’t be exploited with 100% certainty. We can greatly reduce the risks of our software being exploited, by ensuring memory safety for example. But this is not enough to achieve “true safety” territory.

    +

    Because even if you write your program in a “safe language”, hackers can still exploit failures in the operating system where your program is running (e.g. maybe the system where your code is running has a “backdoor exploit” that can still affect your code in unexpected ways), or also, they can exploit the features from the architecture of your computer. A recently found exploit that involves memory invalidation through a feature of “memory tags” present in ARM chips is an example of that (Kim et al. 2024).

    +

    The question is: what have Zig and other languages been doing to mitigate this problem? If we take Rust as an example, Rust is, for the most part24, a memory safe language by enforcing specific rules to the developer. In other words, the key feature of Rust, the borrow checker, forces you to follow a specific logic when you are writing your Rust code, and the Rust compiler will always complain everytime you try to go out of this pattern.

    In contrast, the Zig language is not a memory safe language by default. There are some memory safety features that you get for free in Zig, especially in arrays and pointer objects. But there are other tools offered by the language, that are not used by default. In other words, the zig compiler does not obligates you to use such tools.

    The tools listed below are related to memory safety. That is, they help you to achieve memory safety in your Zig code:

    The name option specify the name that you want to give to the binary file defined by this target object. So, in this example, we are building an executable file named hello. Is common to set this name option to the name of your project.

    -

    Furthermore, the target option specify the target computer architecture (or the target operational system) of this binary file. For example, if you want this target object to run on a Windows machine that uses a x86_64 architecture, you can set this target option to x86_64-windows-gnu for example. This will make the zig compiler to compile the project to run on a x86_64 Windows machine. You can see the full list of architectures and OS’s that the zig compiler supports by running the zig targets command in the terminal.

    +

    Furthermore, the target option specify the target computer architecture (or the target operating system) of this binary file. For example, if you want this target object to run on a Windows machine that uses a x86_64 architecture, you can set this target option to x86_64-windows-gnu for example. This will make the zig compiler to compile the project to run on a x86_64 Windows machine. You can see the full list of architectures and OS’s that the zig compiler supports by running the zig targets command in the terminal.

    Now, if you are building the project to run on the current machine that you are using to run this build script, you can set this target option to the host method of the Build object, like we did in the example above. This host method identifies the current machine where you are currently running the zig compiler.

    At last, the root_source_file option specifies the root Zig module of your project. That is the Zig module that contains the entrypoint to your application (i.e. the main() function), or, the main API of your library. This also means that, all the Zig modules that compose your project are automatically discovered from the import statements you have inside this “root source file”. The zig compiler can detect when a Zig module depends on the other through the import statements, and, as a result, it can discover the entire map of Zig modules used in your project.

    -

    This is handy, and it is different from what happens in other build systems. In CMake for example, you have to explicitly list the paths to all source files that you want to include in your build process. This is probably a symptom of the “lack of conditional compilation” in the C and C++ compilers. Since they lack this feature, you have to explicitly choose which source files should be sent to the C/C++ compiler, because not every C/C++ code is portable or supported in every operational system, and, therefore, would cause a compilation error in the C/C++ compiler.

    +

    This is handy, and it is different from what happens in other build systems. In CMake for example, you have to explicitly list the paths to all source files that you want to include in your build process. This is probably a symptom of the “lack of conditional compilation” in the C and C++ compilers. Since they lack this feature, you have to explicitly choose which source files should be sent to the C/C++ compiler, because not every C/C++ code is portable or supported in every operating system, and, therefore, would cause a compilation error in the C/C++ compiler.

    Now, one important detail about the build process is that, you have to explicitly install the target objects that you create in your build script, by using the installArtifact() method of the Build struct.

    Everytime you invoke the build process of your project, by calling the build command of the zig compiler, a new directory named zig-out is created in the root directory of your project. This new directory contains the outputs of the build process, that is, the binary files built from your source code.

    What the installArtifact() method do is to install (or copy) the built target objects that you defined to this zig-out directory. This means that, if you do not install the target objects you define in your build script, these target objects are essentially discarded at the end of the build process.

    diff --git a/docs/Chapters/12-file-op.html b/docs/Chapters/12-file-op.html index 07269fb0..e00c2578 100644 --- a/docs/Chapters/12-file-op.html +++ b/docs/Chapters/12-file-op.html @@ -399,7 +399,7 @@

    This means that we receive an input, or send some output, through the operating system. It is the OS that makes the bridge between the user and your program. Your program does not have a direct access to the user. It is the OS that intermediates every message exchanged between your program and the user.

    The standard output and standard input channels of your OS are commonly known as the stdout and stdin channels of your OS, respectively. In some contexts, they are also called the standard output device and the standard input device. As the name suggests, the standard output is the channel through which output flows, while the standard input is the channel in which input flows.

    Furthermore, OS’s also normally create a dedicated channel for exchanging error messages, which is known as the standard error channel, or, the stderr channel. This is the channel to which error and warning messages are usually sent to. These are the messages that are normally displayed in red-like or orange-like colors into your terminal.

    -

    Normally, every OS (e.g. Windows, MacOS, Linux, etc.) creates a dedicated and separate set of standard output, standard error and standard input channels for every single program (or process) that runs in your computer. This means that every program you write have a dedicated stdin, stderr and stdout that are separate from the stdin, stderr and stdout of other programs and processes that are currently running.

    +

    Normally, every OS (e.g. Windows, macOS, Linux, etc.) creates a dedicated and separate set of standard output, standard error and standard input channels for every single program (or process) that runs in your computer. This means that every program you write have a dedicated stdin, stderr and stdout that are separate from the stdin, stderr and stdout of other programs and processes that are currently running.

    This is a behaviour from your OS. This does not come from the programming language that you are using. Because as I sad earlier, input and output in programming languages, especially in high-level ones, are just a simple abstraction over the stdin, stderr and stdout from your current OS. That is, your OS is the intermediary between every input/output operation made in your program, regardless of the programming language that you are using.

    13.1.1 The writer and reader pattern

    @@ -589,7 +589,7 @@

    13.3.2 The concept of paths

    A path is essentially a location. It points to a location in your filesystem. We use paths to describe the location of files and folders in our computer. One important aspect about paths is that they are always written inside strings, i.e. they are always provided as text values.

    There are two types of paths that you can provide to any program in any OS: a relative path, or an absolute path. Absolute paths are paths that start at the root of your filesystem, and go all the way to the file name or the specific folder that you are referring to. This type of path is called absolute, because it points to an unique and absolute location on your computer. That is, there is no other existing location on your computer that corresponds to this path. It is an unique identifier.

    -

    In Windows, an absolute path is a path that starts with a hard disk identifier (e.g. C:/Users/pedro). On the other hand, absolute paths in Linux and MacOS, are paths that start with a forward slash character (e.g. /usr/local/bin). Notice that a path is composed by “segments”. Each segment is connected to each other by a slash character (\ or /). On Windows, the backward slash (\) is normally used to connect the path segments. While on Linux and MacOS, the forward slash (/) is the character used to connect path segments.

    +

    In Windows, an absolute path is a path that starts with a hard disk identifier (e.g. C:/Users/pedro). On the other hand, absolute paths in Linux and macOS, are paths that start with a forward slash character (e.g. /usr/local/bin). Notice that a path is composed by “segments”. Each segment is connected to each other by a slash character (\ or /). On Windows, the backward slash (\) is normally used to connect the path segments. While on Linux and macOS, the forward slash (/) is the character used to connect path segments.

    A relative path is a path that start at the CWD. In other words, a relative path is “relative to the CWD”. The path used to access the hello.zig file at Figure 13.3 is an example of a relative path. This path is reproduced below. This path begins at the CWD, which in the context of Figure 13.3, is the zig-book folder, then, it goes to the ZigExamples folder, then, into zig-basics, then, to the hello.zig file.

    ZigExamples/zig-basics/hello_world.zig
    diff --git a/docs/index.html b/docs/index.html index 2857af7e..ac188123 100644 --- a/docs/index.html +++ b/docs/index.html @@ -7,7 +7,7 @@ - + Introduction to Zig \n\n\n\n \n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.2371+c013f45ad.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang)\n", - "supporting": [ - "index_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy an eBook or a physical copy\nof the book on Amazon:\n\n\n\n\n\n\n \n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.2371+c013f45ad.\n- Quarto version: 1.5.57.\n\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur)\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/contributors.txt b/contributors.txt index 18cad9e2..6bcf75bc 100644 --- a/contributors.txt +++ b/contributors.txt @@ -12,3 +12,8 @@ Bruno,@PoorlyDefinedBehaviour Ilia Choly,@icholy Korri Katti,@KorryKatti Vedang Manerikar,@vedang +Tommaso Ricci,@Zorgatone +Primo Sabatini,@primos63 +Santiago Fernandez,@santif +Hamza Wahed,@HamzaWahed +mwilbur,@mwilbur diff --git a/docs/index.html b/docs/index.html index ac188123..bb4d7134 100644 --- a/docs/index.html +++ b/docs/index.html @@ -439,7 +439,7 @@

    Acknowledgments

    This book is also a product of many conversations and exchanges that we had with different people from the Zig community. I (Pedro Duarte Faria) am incredibly grateful for these conversations, and also, for some direct contributions that we had. Below we have a list of the people involved (name of the person with their usename in GitHub):

    -

    Calin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang)

    +

    Calin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur)

    diff --git a/docs/search.json b/docs/search.json index 7c847548..82133e70 100644 --- a/docs/search.json +++ b/docs/search.json @@ -84,7 +84,7 @@ "href": "index.html#acknowledgments", "title": "Introduction to Zig", "section": "Acknowledgments", - "text": "Acknowledgments\nThis book is also a product of many conversations and exchanges that we had with different people from the Zig community. I (Pedro Duarte Faria) am incredibly grateful for these conversations, and also, for some direct contributions that we had. Below we have a list of the people involved (name of the person with their usename in GitHub):\nCalin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang)", + "text": "Acknowledgments\nThis book is also a product of many conversations and exchanges that we had with different people from the Zig community. I (Pedro Duarte Faria) am incredibly grateful for these conversations, and also, for some direct contributions that we had. Below we have a list of the people involved (name of the person with their usename in GitHub):\nCalin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur)", "crumbs": [ "Welcome" ] From afc69bd483d8fe72af8d2626655c4354226bdc52 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Thu, 30 Jan 2025 23:43:51 -0300 Subject: [PATCH 033/151] Recompile book with changes --- .../01-zig-weird/execute-results/html.json | 8 +++++--- .../03-structs/execute-results/html.json | 4 ++-- docs/Chapters/01-zig-weird.html | 8 ++++---- docs/Chapters/03-structs.html | 16 ++++++++-------- docs/search.json | 12 ++++++------ 5 files changed, 25 insertions(+), 23 deletions(-) diff --git a/_freeze/Chapters/01-zig-weird/execute-results/html.json b/_freeze/Chapters/01-zig-weird/execute-results/html.json index 11a7f613..28800571 100644 --- a/_freeze/Chapters/01-zig-weird/execute-results/html.json +++ b/_freeze/Chapters/01-zig-weird/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "3e66c278de9f34fb70ff9abb53f3d4ce", + "hash": "507166385ff85ccf512b153b7c107291", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it is still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. They really make it sometimes hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscures the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that get's compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e. it is where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\n```\n\nThe `ìnit` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contain Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nTherefore, Zig contains a native build system in it, and\nwe can use this build system to write small scripts in Zig,\nwhich describes the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e. creating new objects)\nare made in Zig. You can create a new object in Zig by using the following syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). At @sec-assignments we talk more about objects in general.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n```\n:::\n\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that at @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIs worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt is like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portale C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig build.zig.zon main src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nOn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOs. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e. the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. Thus, if you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith a \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, operations like accessing the `stdout` (or opening a file) on Windows\ndepends on resources that are available only at *runtime* (you will learn more about compile-time\nversus runtime at @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword at @sec-comptime.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation at a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues \n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described at @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig latter in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig? \nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar in our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentations.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It is a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (at YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e. identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compiles successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n age = 25;\n ~~^~~\n```\n\nIn contrast, if you use `var`, then, the object created is a variable object.\nWith `var` you can declare this object in your source code, and then,\nchange the value of this object how many times you want over future points\nin your source code.\n\nSo, using the same code example exposed above, if I change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it is an \"variable object\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIs important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code use this object while it is uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object. \n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e. if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n const age = 15;\n ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to an special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It is discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also get's discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig have many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e. the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\n\nIs worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it have the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array. \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it is a slice that\naccess all elements in the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhave 2 elements in it.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" at @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth at @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially at @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned at @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e. the start and the end of this range)\nis known at compile-time, the slice object that get's created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nat @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that get's created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e. a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can \ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n 1, 2, 3, 4, 5,\n 6, 7, 8, 9, 10\n};\n// This slice have a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n```\n:::\n\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat get's created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, the `slice` object have a runtime known range, because the end index of the range\nis not known at compile time. In other words, the size of the array at `buffer` is not known\nat compile time. When we execute this program, the size of the array might be 10, or, it might be 12\ndepending on where we execute it. Therefore, we don't know at compile time if\nthe slice object have a range of size 10, or, a range of size 12.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var n: usize = 0;\n if (builtin.target.os.tag == .windows) {\n n = 10;\n } else {\n n = 12;\n }\n const buffer = try allocator.alloc(u64, n);\n const slice = buffer[0..];\n _ = slice;\n}\n```\n:::\n\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code have its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e. a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n y += 1;\n break :add_one y;\n};\nif (x == 124 and y == 124) {\n try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nIn summary, there are two types of string values that you care about in Zig, which are:\n\n- String literal values.\n- String objects.\n\nA string literal value is just a pointer to a null-terminated array of bytes (i.e. similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string into the data type of the value itself.\nTherefore, a string literal value have a data type in the format `*const [n:0]u8`. The `n` in the data type\nindicates the size of the string.\n\nOn the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes,\nor, in other words, a slice of `u8` values (slices were presented at @sec-arrays). Thus,\na string object have a data type of `[]u8` or `[]const u8`, depending if the string object is\nmarked as constant with `const`, or as variable with `var`.\n\nBecause a string object is essentially a slice, it means that a string object always contains two things:\na pointer to an array of bytes (i.e. `u8` values) that represents the string value; and also, a length value,\nwhich specifies the size of the slice, or, how many elements there is in the slice.\nIs worth to emphasize that the array of bytes in a string object is not null-terminated, like in a\nstring literal value.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n\"A literal value\";\n// This is a string object:\nconst object: []const u8 = \"A string object\";\n```\n:::\n\n\n\n\n\nZig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example\";\n try stdout.print(\"Bytes that represents the string object: \", .{});\n for (string_object) |byte| {\n try stdout.print(\"{X} \", .{byte});\n }\n try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n 73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Strings in C\n\nAt first glance, a string literal value in Zig looks very similar to how C treats strings as well.\nIn more details, string values in C are treated internally as an array of arbitrary bytes,\nand this array is also null-terminated.\n\nBut one key difference between a Zig string literal and a C string, is that Zig also stores the length of\nthe string inside the object itself. In the case of a string literal value, this length is stored in the\ndata type of the value (i.e. the `n` variable in `[n:0]u8`). While, in a string object, the length is stored\nin the `len` attribute of the slice that represents the string object. This small detail makes your code safer,\nbecause is much easier for the Zig compiler to check if you are trying to access an element that is\n\"out of bounds\", i.e. if your trying to access memory that does not belong to you.\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n char* array = \"An example of string in C\";\n int index = 0;\n while (1) {\n if (array[index] == '\\0') {\n break;\n }\n index++;\n }\n printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible. In a string object for example, you can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example of string literal in Zig\";\n try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it is a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const simple_array = [_]i32{1, 2, 3, 4};\n const string_obj: []const u8 = \"A string object\";\n std.debug.print(\n \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n );\n std.debug.print(\n \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n );\n std.debug.print(\n \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n );\n std.debug.print(\n \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nType 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons\n st [4]i32Type 4: []const u8\n```\n\n\n:::\n:::\n\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIs important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"Ⱥ\";\n _ = try stdout.write(\n \"Bytes that represents the string object: \"\n );\n for (string_object) |char| {\n try stdout.print(\"{X} \", .{char});\n }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n var iterator = utf8.iterator();\n while (iterator.nextCodepointSlice()) |codepoint| {\n try stdout.print(\n \"got codepoint {}\\n\",\n .{std.fmt.fmtSliceHexUpper(codepoint)},\n );\n }\n}\n\n```\n:::\n\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligates you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig at @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers at @sec-root-file and especially at @sec-assignments.\n- How strings work in Zig at @sec-zig-strings.\n- How to use arrays and slices at @sec-arrays.\n- How to import functionality from other Zig modules at @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* at @sec-structs-and-oop.\n- Basic control flow syntax at @sec-zig-control-flow.\n- Enums at @sec-enum;\n- Pointers and Optionals at @sec-pointer;\n- Error handling with `try` and `catch` at @sec-error-handling;\n- Unit tests at @sec-unittests;\n- Vectors at @sec-vectors-simd;\n- Build System at @sec-build-system;\n\n\n\n\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it is still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. They really make it sometimes hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscures the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that get's compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e. it is where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contain Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nTherefore, Zig contains a native build system in it, and\nwe can use this build system to write small scripts in Zig,\nwhich describes the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e. creating new objects)\nare made in Zig. You can create a new object in Zig by using the following syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). At @sec-assignments we talk more about objects in general.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n```\n:::\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that at @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIs worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt is like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portale C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig build.zig.zon main src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nOn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOs. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e. the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. Thus, if you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith a \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, operations like accessing the `stdout` (or opening a file) on Windows\ndepends on resources that are available only at *runtime* (you will learn more about compile-time\nversus runtime at @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword at @sec-comptime.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation at a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues \n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described at @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig latter in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig? \nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar in our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentations.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It is a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (at YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e. identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n age = 25;\n ~~^~~\n```\n\nIn contrast, if you use `var`, then, the object created is a variable object.\nWith `var` you can declare this object in your source code, and then,\nchange the value of this object how many times you want over future points\nin your source code.\n\nSo, using the same code example exposed above, if I change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it is an \"variable object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIs important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code use this object while it is uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object. \n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e. if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n const age = 15;\n ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to an special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It is discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also get's discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig have many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e. the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\nIs worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it have the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array. \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it is a slice that\naccess all elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhave 2 elements in it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" at @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth at @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially at @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned at @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e. the start and the end of this range)\nis known at compile-time, the slice object that get's created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nat @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that get's created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e. a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can \ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n 1, 2, 3, 4, 5,\n 6, 7, 8, 9, 10\n};\n// This slice have a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n```\n:::\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat get's created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, the `slice` object have a runtime known range, because the end index of the range\nis not known at compile time. In other words, the size of the array at `buffer` is not known\nat compile time. When we execute this program, the size of the array might be 10, or, it might be 12\ndepending on where we execute it. Therefore, we don't know at compile time if\nthe slice object have a range of size 10, or, a range of size 12.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var n: usize = 0;\n if (builtin.target.os.tag == .windows) {\n n = 10;\n } else {\n n = 12;\n }\n const buffer = try allocator.alloc(u64, n);\n const slice = buffer[0..];\n _ = slice;\n}\n```\n:::\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code have its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e. a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n y += 1;\n break :add_one y;\n};\nif (x == 124 and y == 124) {\n try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nIn summary, there are two types of string values that you care about in Zig, which are:\n\n- String literal values.\n- String objects.\n\nA string literal value is just a pointer to a null-terminated array of bytes (i.e. similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string into the data type of the value itself.\nTherefore, a string literal value have a data type in the format `*const [n:0]u8`. The `n` in the data type\nindicates the size of the string.\n\nOn the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes,\nor, in other words, a slice of `u8` values (slices were presented at @sec-arrays). Thus,\na string object have a data type of `[]u8` or `[]const u8`, depending if the string object is\nmarked as constant with `const`, or as variable with `var`.\n\nBecause a string object is essentially a slice, it means that a string object always contains two things:\na pointer to an array of bytes (i.e. `u8` values) that represents the string value; and also, a length value,\nwhich specifies the size of the slice, or, how many elements there is in the slice.\nIs worth to emphasize that the array of bytes in a string object is not null-terminated, like in a\nstring literal value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n\"A literal value\";\n// This is a string object:\nconst object: []const u8 = \"A string object\";\n```\n:::\n\n\n\n\nZig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example\";\n try stdout.print(\"Bytes that represents the string object: \", .{});\n for (string_object) |byte| {\n try stdout.print(\"{X} \", .{byte});\n }\n try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n 73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n### Strings in C\n\nAt first glance, a string literal value in Zig looks very similar to how C treats strings as well.\nIn more details, string values in C are treated internally as an array of arbitrary bytes,\nand this array is also null-terminated.\n\nBut one key difference between a Zig string literal and a C string, is that Zig also stores the length of\nthe string inside the object itself. In the case of a string literal value, this length is stored in the\ndata type of the value (i.e. the `n` variable in `[n:0]u8`). While, in a string object, the length is stored\nin the `len` attribute of the slice that represents the string object. This small detail makes your code safer,\nbecause it is much easier for the Zig compiler to check if you are trying to access an element that is\n\"out of bounds\", i.e. if your trying to access memory that does not belong to you.\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n char* array = \"An example of string in C\";\n int index = 0;\n while (1) {\n if (array[index] == '\\0') {\n break;\n }\n index++;\n }\n printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible. In a string object for example, you can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example of string literal in Zig\";\n try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it is a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const simple_array = [_]i32{1, 2, 3, 4};\n const string_obj: []const u8 = \"A string object\";\n std.debug.print(\n \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n );\n std.debug.print(\n \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n );\n std.debug.print(\n \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n );\n std.debug.print(\n \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nType 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons\n st [4]i32Type 4: []const u8\n```\n\n\n:::\n:::\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIs important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"Ⱥ\";\n _ = try stdout.write(\n \"Bytes that represents the string object: \"\n );\n for (string_object) |char| {\n try stdout.print(\"{X} \", .{char});\n }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n var iterator = utf8.iterator();\n while (iterator.nextCodepointSlice()) |codepoint| {\n try stdout.print(\n \"got codepoint {}\\n\",\n .{std.fmt.fmtSliceHexUpper(codepoint)},\n );\n }\n}\n\n```\n:::\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig at @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers at @sec-root-file and especially at @sec-assignments.\n- How strings work in Zig at @sec-zig-strings.\n- How to use arrays and slices at @sec-arrays.\n- How to import functionality from other Zig modules at @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* at @sec-structs-and-oop.\n- Basic control flow syntax at @sec-zig-control-flow.\n- Enums at @sec-enum;\n- Pointers and Optionals at @sec-pointer;\n- Error handling with `try` and `catch` at @sec-error-handling;\n- Unit tests at @sec-unittests;\n- Vectors at @sec-vectors-simd;\n- Build System at @sec-build-system;\n\n\n\n\n", + "supporting": [ + "01-zig-weird_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/03-structs/execute-results/html.json b/_freeze/Chapters/03-structs/execute-results/html.json index 04f37e1b..fb55828f 100644 --- a/_freeze/Chapters/03-structs/execute-results/html.json +++ b/_freeze/Chapters/03-structs/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "cedb7b341aa333220e9f4f2918e4ea74", + "hash": "75a34188e80fdc2dce5441514f1bc59a", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `order`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object have type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e. four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n```\n:::\n\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It is important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n else => {\n try stdout.print(\n \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n );\n },\n}\n```\n:::\n\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n```\n:::\n\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function get's executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, is worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression get's executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that get's printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n // code to execute\n}\n```\n:::\n\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It is the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e. the logical test is equal to false), the function raises an assertion error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e. constant) object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n x = x + 2;\n return x;\n}\n\npub fn main() !void {\n const y = add2(4);\n std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n x = x + 2;\n ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e. `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n const d: u32 = 2;\n x.* = x.* + d;\n}\n\npub fn main() !void {\n var x: u32 = 4;\n add2(&x);\n std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n pub fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n pub fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nEvery method that you declare in your struct that is marked with the keyword `pub`,\nbecomes a public method of this particular struct.\n\nSo every method that you create inside your struct, is, at first, a private method\nof that struct. Meaning that, this method can only be called from within this\nstruct. But, if you mark this method as public, with the keyword `pub`, then,\nyou can call the method directly from an instance of the `User` struct.\n\nIn other words, the functions marked by the keyword `pub`\nare members of the public API of that struct.\nFor example, if I did not mark the `print_name()` method as public,\nthen, I could not execute the line `u.print_name()`. Because I would\nnot be authorized to call this method directly in my code.\n\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n```\n:::\n\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt is not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n```\n:::\n\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods is affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e. change the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n```\n:::\n\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it is not about the input object, it is about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special party in this place. More specifically, it is\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and it is\ntrying to infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n```\n:::\n\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e. we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it is explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file10b91234368fa.test_0...OKAll 1 tests passe\n ed.\n```\n\n\n:::\n:::\n\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe, and there are situations where these assumptions do not hold. For example,\nwhen casting an integer value into a float value, or vice-versa, it is not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file10b9130ae9221.test_0...OKAll 1 tests passe\n ed.\n```\n\n\n:::\n:::\n\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e. they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file10b914c434861.test_0...OKAll 1 tests passe\n ed.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e. a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" get's executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object get's saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n .{ .max_threads = num_threads }\n);\n```\n:::\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `role`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object has type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e. four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n```\n:::\n\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It is important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n else => {\n try stdout.print(\n \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n );\n },\n}\n```\n:::\n\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n```\n:::\n\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function get's executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, is worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression get's executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that get's printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n // code to execute\n}\n```\n:::\n\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It is the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e. the logical test is equal to false), the function raises an assertion error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e. constant) object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n x = x + 2;\n return x;\n}\n\npub fn main() !void {\n const y = add2(4);\n std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n x = x + 2;\n ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e. `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n const d: u32 = 2;\n x.* = x.* + d;\n}\n\npub fn main() !void {\n var x: u32 = 4;\n add2(&x);\n std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n pub fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n pub fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nEvery method that you declare in your struct that is marked with the keyword `pub`,\nbecomes a public method of this particular struct.\n\nSo every method that you create inside your struct, is, at first, a private method\nof that struct. Meaning that, this method can only be called from within this\nstruct. But, if you mark this method as public, with the keyword `pub`, then,\nyou can call the method directly from an instance of the `User` struct.\n\nIn other words, the functions marked by the keyword `pub`\nare members of the public API of that struct.\nFor example, if I did not mark the `print_name()` method as public,\nthen, I could not execute the line `u.print_name()`. Because I would\nnot be authorized to call this method directly in my code.\n\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n```\n:::\n\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt is not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n```\n:::\n\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods is affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e. change the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n```\n:::\n\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it is not about the input object, it is about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special party in this place. More specifically, it is\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and it is\ntrying to infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n```\n:::\n\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e. we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it is explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filecdc41797a754.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe, and there are situations where these assumptions do not hold. For example,\nwhen casting an integer value into a float value, or vice-versa, it is not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filecdc428638149.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e. they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filecdc46f71cc03.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e. a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" get's executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object get's saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n .{ .max_threads = num_threads }\n);\n```\n:::\n", "supporting": [ "03-structs_files" ], diff --git a/docs/Chapters/01-zig-weird.html b/docs/Chapters/01-zig-weird.html index 2f44cd2d..f7360c5b 100644 --- a/docs/Chapters/01-zig-weird.html +++ b/docs/Chapters/01-zig-weird.html @@ -400,7 +400,7 @@

    -

    The ìnit command also creates two additional files in our working directory: build.zig and build.zig.zon. The first file (build.zig) represents a build script written in Zig. This script is executed when you call the build command from the zig compiler. In other words, this file contain Zig code that executes the necessary steps to build the entire project.

    +

    The init command also creates two additional files in our working directory: build.zig and build.zig.zon. The first file (build.zig) represents a build script written in Zig. This script is executed when you call the build command from the zig compiler. In other words, this file contain Zig code that executes the necessary steps to build the entire project.

    Low-level languages normally use a compiler to build your source code into binary executables or binary libraries. Nevertheless, this process of compiling your source code and building binary executables or binary libraries from it, became a real challenge in the programming world, once the projects became bigger and bigger. As a result, programmers created “build systems”, which are a second set of tools designed to make this process of compiling and building complex projects, easier.

    Examples of build systems are CMake, GNU Make, GNU Autoconf and Ninja, which are used to build complex C and C++ projects. With these systems, you can write scripts, which are called “build scripts”. They simply are scripts that describes the necessary steps to compile/build your project.

    However, these are separate tools, that do not belong to C/C++ compilers, like gcc or clang. As a result, in C/C++ projects, you have not only to install and manage your C/C++ compilers, but you also have to install and manage these build systems separately.

    @@ -567,7 +567,7 @@

    On the other side, if you use var, then, you are creating a variable (or mutable) object. You can change the value of this object as many times you want. Using the keyword var in Zig is similar to using the keywords let mut in Rust.

    1.4.1 Constant objects vs variable objects

    -

    In the code example below, we are creating a new constant object called age. This object stores a number representing the age of someone. However, this code example does not compiles successfully. Because on the next line of code, we are trying to change the value of the object age to 25.

    +

    In the code example below, we are creating a new constant object called age. This object stores a number representing the age of someone. However, this code example does not compile successfully. Because on the next line of code, we are trying to change the value of the object age to 25.

    The zig compiler detects that we are trying to change the value of an object/identifier that is constant, and because of that, the compiler will raise a compilation error, warning us about the mistake.

    const age = 24;
    @@ -854,7 +854,7 @@ 

    1.8.1 Strings in C

    At first glance, a string literal value in Zig looks very similar to how C treats strings as well. In more details, string values in C are treated internally as an array of arbitrary bytes, and this array is also null-terminated.

    -

    But one key difference between a Zig string literal and a C string, is that Zig also stores the length of the string inside the object itself. In the case of a string literal value, this length is stored in the data type of the value (i.e. the n variable in [n:0]u8). While, in a string object, the length is stored in the len attribute of the slice that represents the string object. This small detail makes your code safer, because is much easier for the Zig compiler to check if you are trying to access an element that is “out of bounds”, i.e. if your trying to access memory that does not belong to you.

    +

    But one key difference between a Zig string literal and a C string, is that Zig also stores the length of the string inside the object itself. In the case of a string literal value, this length is stored in the data type of the value (i.e. the n variable in [n:0]u8). While, in a string object, the length is stored in the len attribute of the slice that represents the string object. This small detail makes your code safer, because it is much easier for the Zig compiler to check if you are trying to access an element that is “out of bounds”, i.e. if your trying to access memory that does not belong to you.

    To achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless. So getting this kind of safety is not automatic and much harder to do in C. For example, if you want to track the length of your string throughout your program in C, then, you first need to loop through the array of bytes that represents this string, and find the null element ('\0') position to discover where exactly the array ends, or, in other words, to find how much elements the array of bytes contain.

    To do that, you would need something like this in C. In this example, the C string stored in the object array is 25 bytes long:

    @@ -1033,7 +1033,7 @@

    As Richard Feldman explains on his most recent GOTO conference talk24 , we haven’t figured it out yet a way to achieve true safety in technology. In other words, we haven’t found a way to build software that won’t be exploited with 100% certainty. We can greatly reduce the risks of our software being exploited, by ensuring memory safety for example. But this is not enough to achieve “true safety” territory.

    Because even if you write your program in a “safe language”, hackers can still exploit failures in the operating system where your program is running (e.g. maybe the system where your code is running has a “backdoor exploit” that can still affect your code in unexpected ways), or also, they can exploit the features from the architecture of your computer. A recently found exploit that involves memory invalidation through a feature of “memory tags” present in ARM chips is an example of that (Kim et al. 2024).

    The question is: what have Zig and other languages been doing to mitigate this problem? If we take Rust as an example, Rust is, for the most part25, a memory safe language by enforcing specific rules to the developer. In other words, the key feature of Rust, the borrow checker, forces you to follow a specific logic when you are writing your Rust code, and the Rust compiler will always complain everytime you try to go out of this pattern.

    -

    In contrast, the Zig language is not a memory safe language by default. There are some memory safety features that you get for free in Zig, especially in arrays and pointer objects. But there are other tools offered by the language, that are not used by default. In other words, the zig compiler does not obligates you to use such tools.

    +

    In contrast, the Zig language is not a memory safe language by default. There are some memory safety features that you get for free in Zig, especially in arrays and pointer objects. But there are other tools offered by the language, that are not used by default. In other words, the zig compiler does not obligate you to use such tools.

    The tools listed below are related to memory safety. That is, they help you to achieve memory safety in your Zig code:

    • defer allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, “use after free”, and also “double-free” problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.
    • diff --git a/docs/Chapters/03-structs.html b/docs/Chapters/03-structs.html index 19bc03c5..bcf6dd8f 100644 --- a/docs/Chapters/03-structs.html +++ b/docs/Chapters/03-structs.html @@ -392,8 +392,8 @@

      2.1.2.1 Switch statements must exhaust all possibilities

      -

      One very important aspect about switch statements in Zig is that they must exhaust all existing possibilities. In other words, all possible values that could be found inside the order object must be explicitly handled in this switch statement.

      -

      Since the role object have type Role, the only possible values to be found inside this object are PM, SE, DPE, PO, DE, DA and KS. There are no other possible values to be stored in this role object. Thus, the switch statements must have a combination (branch) for each one of these values. This is what “exhaust all existing possibilities” means. The switch statement covers every possible case.

      +

      One very important aspect about switch statements in Zig is that they must exhaust all existing possibilities. In other words, all possible values that could be found inside the role object must be explicitly handled in this switch statement.

      +

      Since the role object has type Role, the only possible values to be found inside this object are PM, SE, DPE, PO, DE, DA and KS. There are no other possible values to be stored in this role object. Thus, the switch statements must have a combination (branch) for each one of these values. This is what “exhaust all existing possibilities” means. The switch statement covers every possible case.

      Therefore, you cannot write a switch statement in Zig, and leave an edge case with no explicit action to be taken. This is a similar behaviour to switch statements in Rust, which also have to handle all possible cases.

      @@ -927,8 +927,8 @@

      try expect(@TypeOf(y) == u32); }

    -
    1/1 file10b91234368fa.test_0...OKAll 1 tests passe
    -  ed.
    +
    1/1 filecdc41797a754.test_0...OKAll 1 tests passed
    +  d.

    This is the general way to perform type casting in Zig. But remember, @as() works only when casting is unambiguous and safe, and there are situations where these assumptions do not hold. For example, when casting an integer value into a float value, or vice-versa, it is not clear to the compiler how to perform this conversion safely.

    @@ -943,8 +943,8 @@

    try expect(@TypeOf(y) == f32); }

    -
    1/1 file10b9130ae9221.test_0...OKAll 1 tests passe
    -  ed.
    +
    1/1 filecdc428638149.test_0...OKAll 1 tests passed
    +  d.

    Another built-in function that is very useful when performing type casting operations is @ptrCast(). In essence, we use the @as() built-in function when we want to explicit convert (or cast) a Zig value/object from a type “x” to a type “y”, etc. However, pointers (we are going to discuss pointers in more depth in Chapter 6) are a special type of object in Zig, i.e. they are treated differently from “normal objects”.

    @@ -960,8 +960,8 @@

    try expect(@TypeOf(u32_ptr) == *const u32); }
    -
    1/1 file10b914c434861.test_0...OKAll 1 tests passe
    -  ed.
    +
    1/1 filecdc46f71cc03.test_0...OKAll 1 tests passed
    +  d.
    diff --git a/docs/search.json b/docs/search.json index 82133e70..9d8728f7 100644 --- a/docs/search.json +++ b/docs/search.json @@ -124,7 +124,7 @@ "href": "Chapters/01-zig-weird.html#hello-world-in-zig", "title": "1  Introducing Zig", "section": "1.2 Hello world in Zig", - "text": "1.2 Hello world in Zig\nWe begin our journey in Zig by creating a small “Hello World” program. To start a new Zig project in your computer, you simply call the init command from the zig compiler. Just create a new directory in your computer, then, init a new Zig project inside this directory, like this:\nmkdir hello_world\ncd hello_world\nzig init\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n\n1.2.1 Understanding the project files\nAfter you run the init command from the zig compiler, some new files are created inside of your current directory. First, a “source” (src) directory is created, containing two files, main.zig and root.zig. Each .zig file is a separate Zig module, which is simply a text file that contains some Zig code.\nBy convention, the main.zig module is where your main function lives. Thus, if you are building an executable program in Zig, you need to declare a main() function, which represents the entrypoint of your program, i.e. it is where the execution of your program begins.\nHowever, if you are building a library (instead of an executable program), then, the normal procedure is to delete this main.zig file and start with the root.zig module. By convention, the root.zig module is the root source file of your library.\ntree .\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\nThe ìnit command also creates two additional files in our working directory: build.zig and build.zig.zon. The first file (build.zig) represents a build script written in Zig. This script is executed when you call the build command from the zig compiler. In other words, this file contain Zig code that executes the necessary steps to build the entire project.\nLow-level languages normally use a compiler to build your source code into binary executables or binary libraries. Nevertheless, this process of compiling your source code and building binary executables or binary libraries from it, became a real challenge in the programming world, once the projects became bigger and bigger. As a result, programmers created “build systems”, which are a second set of tools designed to make this process of compiling and building complex projects, easier.\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja, which are used to build complex C and C++ projects. With these systems, you can write scripts, which are called “build scripts”. They simply are scripts that describes the necessary steps to compile/build your project.\nHowever, these are separate tools, that do not belong to C/C++ compilers, like gcc or clang. As a result, in C/C++ projects, you have not only to install and manage your C/C++ compilers, but you also have to install and manage these build systems separately.\nIn Zig, we don’t need to use a separate set of tools to build our projects, because a build system is embedded inside the language itself. Therefore, Zig contains a native build system in it, and we can use this build system to write small scripts in Zig, which describes the necessary steps to build/compile our Zig project1. So, everything you need to build a complex Zig project is the zig compiler, and nothing more.\nThe second generated file (build.zig.zon) is a JSON-like file, in which you can describe your project, and also, declare a set of dependencies of your project that you want to fetch from the internet. In other words, you can use this build.zig.zon file to include a list of external libraries in your project.\nOne possible way to include an external Zig library in your project, is to manually build and install the library in your system, and just link your source code with the library at the build step of your project.\nHowever, if this external Zig library is available on GitHub for example, and it has a valid build.zig.zon file in root folder of the project, which describes the project, you can easily include this library in your project by simply listing this external library in your build.zig.zon file.\nIn other words, this build.zig.zon file works similarly to the package.json file in Javascript projects, or the Pipfile file in Python projects, or the Cargo.toml file in Rust projects. You can read more about this specific file in a couple of articles on the internet23, and you can also see the expected schema for this build.zig.zon file in a documentation file inside the official repository of Zig4.\n\n\n1.2.2 The file root.zig\nLet’s take a look into the root.zig file. You might have noticed that every line of code with an expression ends with a semicolon (;). This follows the syntax of a C-family programming language5.\nAlso, notice the @import() call at the first line. We use this built-in function to import functionality from other Zig modules into our current module. This @import() function works similarly to the #include pre-processor in C or C++, or, to the import statement in Python or Javascript code. In this example, we are importing the std module, which gives you access to the Zig Standard Library.\nIn this root.zig file, we can also see how assignments (i.e. creating new objects) are made in Zig. You can create a new object in Zig by using the following syntax (const|var) name = value;. In the example below, we are creating two constant objects (std and testing). At Section 1.4 we talk more about objects in general.\n\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n\nFunctions in Zig are declared using the fn keyword. In this root.zig module, we are declaring a function called add(), which has two arguments named a and b. The function returns an integer of the type i32 as result.\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit the type of an object in your code, if this type can be inferred by the zig compiler (we talk more about that at Section 2.4). But there are other situations where you do need to be explicit. For example, you do have to explicitly specify the type of each function argument, and also, the return type of every function that you create in Zig.\nWe specify the type of an object or a function argument in Zig by using a colon character (:) followed by the type after the name of this object/function argument. With the expressions a: i32 and b: i32, we know that both a and b arguments have type i32, which is a signed 32 bit integer. In this part, the syntax in Zig is identical to the syntax in Rust, which also specifies types by using the colon character.\nLastly, we have the return type of the function at the end of the line, before we open the curly braces to start writing the function’s body. In the example above, this type is also a signed 32 bit integer (i32) value.\nNotice that we also have an export keyword before the function declaration. This keyword is similar to the extern keyword in C. It exposes the function to make it available in the library API. Therefore, if you are writing a library for other people to use, you have to expose the functions you write in the public API of this library by using this export keyword. If we removed the export keyword from the add() function declaration, then, this function would be no longer exposed in the library object built by the zig compiler.\n\n\n1.2.3 The main.zig file\nNow that we have learned a lot about Zig’s syntax from the root.zig file, let’s take a look at the main.zig file. A lot of the elements we saw in root.zig are also present in main.zig. But there are some other elements that we haven’t seen yet, so let’s dive in.\nFirst, look at the return type of the main() function in this file. We can see a small change. The return type of the function (void) is accompanied by an exclamation mark (!). This exclamation mark tells us that this main() function might return an error.\nIs worth noting that, a main() function in Zig is allowed to return nothing (void), or an unsigned 8-bit integer (u8) value6, or an error. In other words, you can write your main() function in Zig to return essentially nothing (void), or, if you prefer, you can also write a more C-like main() function, which returns an integer value that usually serves as a “status code” for the process.\nIn this example, the return type annotation of main() indicates that this function can either return nothing (void), or return an error. This exclamation mark in the return type annotation is an interesting and powerful feature of Zig. In summary, if you write a function and something inside the body of this function might return an error, then, you are forced to:\n\neither add the exclamation mark to the return type of the function and make it clear that this function might return an error.\nexplicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through a try catch pattern. Zig does have both try and catch keywords. But they work a little differently than what you’re probably used to in other languages.\nIf we look at the main() function below, you can see that we do have a try keyword on the 5th line. But we do not have a catch keyword in this code. In Zig, we use the try keyword to execute an expression that might return an error, which, in this example, is the stdout.print() expression.\nIn essence, the try keyword executes the expression stdout.print(). If this expression returns a valid value, then, the try keyword does absolutely nothing. It only passes the value forward. It is like if this try keyword was never there. However, if the expression does return an error, then, the try keyword will unwrap the error value, then, it returns this error from the function and also prints the current stack trace to stderr.\nThis might sound weird to you if you come from a high-level language. Because in high-level languages, such as Python, if an error occurs somewhere, this error is automatically returned and the execution of your program will automatically stop even if you don’t want to stop the execution. You are obligated to face the error.\n\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n\nAnother thing that you might have noticed in this code example, is that the main() function is marked with the pub keyword. It marks the main() function as a public function from this module. Every function in your Zig module is by default private to this Zig module and can only be called from within the module. Unless, you explicitly mark this function as a public function with the pub keyword.\nIf you think about it, this pub keyword in Zig does essentially the opposite of what the static keyword do in C/C++. By making a function “public” you allow other Zig modules to access and call this function. A calling Zig module imports another module by using the @import() built-in function, which makes all public functions from the imported module visible to the calling Zig module.\n\n\n1.2.4 Compiling your source code\nYou can compile your Zig modules into a binary executable by running the build-exe command from the zig compiler. You simply list all the Zig modules that you want to build after the build-exe command, separated by spaces. In the example below, we are compiling the module main.zig.\nzig build-exe src/main.zig\nSince we are building an executable, the zig compiler will look for a main() function declared in any of the files that you list after the build-exe command. If the compiler does not find a main() function declared somewhere, a compilation error will be raised, warning about this mistake.\nThe zig compiler also offers a build-lib and build-obj commands, which work the exact same way as the build-exe command. The only difference is that, they compile your Zig modules into a portale C ABI library, or, into object files, respectively.\nIn the case of the build-exe command, a binary executable file is created by the zig compiler in the root directory of your project. If we take a look now at the contents of our current directory, with a simple ls command, we can see the binary file called main that was created by the compiler.\nls\nbuild.zig build.zig.zon main src\nIf I execute this binary executable, I get the “Hello World” message in the terminal , as we expected.\n./main\nHello, world!\n\n\n1.2.5 Compile and execute at the same time\nOn the previous section, I presented the zig build-exe command, which compiles Zig modules into an executable file. However, this means that, in order to execute the executable file, we have to run two different commands. First, the zig build-exe command, and then, we call the executable file created by the compiler.\nBut what if we wanted to perform these two steps, all at once, in a single command? We can do that by using the zig run command.\nzig run src/main.zig\nHello, world!\n\n\n1.2.6 Important note for Windows users\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other operating systems, such as Linux and macOs. In summary, if you have a piece of Zig code that includes some global variables whose initialization rely on runtime resources, then, you might have some troubles while trying to compile this Zig code on Windows.\nAn example of that is accessing the stdout (i.e. the standard output of your system), which is usually done in Zig by using the expression std.io.getStdOut(). Thus, if you use this expression to instantiate a global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows, with a “unable to evaluate comptime expression” error message.\nThis failure in the compilation process happens because all global variables in Zig are initialized at compile-time. However, operations like accessing the stdout (or opening a file) on Windows depends on resources that are available only at runtime (you will learn more about compile-time versus runtime at Section 3.1.1).\nFor example, if you try to compile this code example on Windows, you will likely get the error message exposed below:\n\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\nTo avoid this problem on Windows, we need to force the zig compiler to instantiate this stdout object only at runtime, instead of instantiating it at compile-time. We can achieve that by simply moving the expression to a function body.\nThis solves the problem because all expressions that are inside a function body in Zig are evaluated only at runtime, unless you use the comptime keyword explicitly to change this behaviour. You will learn more about this comptime keyword at Section 12.1.\n\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n\nHello\nYou can read more details about this Windows-specific limitation at a couple of GitHub issues opened at the official Zig repository. More specifically, the issues 17186 7 and 19864 8.\n\n\n1.2.7 Compiling the entire project\nJust as I described at Section 1.2.1, as our project grows in size and complexity, we usually prefer to organize the compilation and build process of the project into a build script, using some sort of “build system”.\nIn other words, as our project grows in size and complexity, the build-exe, build-lib and build-obj commands become harder to use directly. Because then, we start to list multiple and multiple modules at the same time. We also start to add built-in compilation flags to customize the build process for our needs, etc. It becomes a lot of work to write the necessary commands by hand.\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, Makefile or configure scripts to organize this process. However, in Zig, we have a native build system in the language itself. So, we can write build scripts in Zig to compile and build Zig projects. Then, all we need to do, is to call the zig build command to build our project.\nSo, when you execute the zig build command, the zig compiler will search for a Zig module named build.zig inside your current directory, which should be your build script, containing the necessary code to compile and build your project. If the compiler does find this build.zig file in your directory, then, the compiler will essentially execute a zig run command over this build.zig file, to compile and execute this build script, which in turn, will compile and build your entire project.\nzig build\nAfter you execute this “build project” command, a zig-out directory is created in the root of your project directory, where you can find the binary executables and libraries created from your Zig modules accordingly to the build commands that you specified at build.zig. We will talk more about the build system in Zig latter in this book.\nIn the example below, I’m executing the binary executable named hello_world that was generated by the compiler after the zig build command.\n./zig-out/bin/hello_world\nHello, world!", + "text": "1.2 Hello world in Zig\nWe begin our journey in Zig by creating a small “Hello World” program. To start a new Zig project in your computer, you simply call the init command from the zig compiler. Just create a new directory in your computer, then, init a new Zig project inside this directory, like this:\nmkdir hello_world\ncd hello_world\nzig init\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n\n1.2.1 Understanding the project files\nAfter you run the init command from the zig compiler, some new files are created inside of your current directory. First, a “source” (src) directory is created, containing two files, main.zig and root.zig. Each .zig file is a separate Zig module, which is simply a text file that contains some Zig code.\nBy convention, the main.zig module is where your main function lives. Thus, if you are building an executable program in Zig, you need to declare a main() function, which represents the entrypoint of your program, i.e. it is where the execution of your program begins.\nHowever, if you are building a library (instead of an executable program), then, the normal procedure is to delete this main.zig file and start with the root.zig module. By convention, the root.zig module is the root source file of your library.\ntree .\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\nThe init command also creates two additional files in our working directory: build.zig and build.zig.zon. The first file (build.zig) represents a build script written in Zig. This script is executed when you call the build command from the zig compiler. In other words, this file contain Zig code that executes the necessary steps to build the entire project.\nLow-level languages normally use a compiler to build your source code into binary executables or binary libraries. Nevertheless, this process of compiling your source code and building binary executables or binary libraries from it, became a real challenge in the programming world, once the projects became bigger and bigger. As a result, programmers created “build systems”, which are a second set of tools designed to make this process of compiling and building complex projects, easier.\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja, which are used to build complex C and C++ projects. With these systems, you can write scripts, which are called “build scripts”. They simply are scripts that describes the necessary steps to compile/build your project.\nHowever, these are separate tools, that do not belong to C/C++ compilers, like gcc or clang. As a result, in C/C++ projects, you have not only to install and manage your C/C++ compilers, but you also have to install and manage these build systems separately.\nIn Zig, we don’t need to use a separate set of tools to build our projects, because a build system is embedded inside the language itself. Therefore, Zig contains a native build system in it, and we can use this build system to write small scripts in Zig, which describes the necessary steps to build/compile our Zig project1. So, everything you need to build a complex Zig project is the zig compiler, and nothing more.\nThe second generated file (build.zig.zon) is a JSON-like file, in which you can describe your project, and also, declare a set of dependencies of your project that you want to fetch from the internet. In other words, you can use this build.zig.zon file to include a list of external libraries in your project.\nOne possible way to include an external Zig library in your project, is to manually build and install the library in your system, and just link your source code with the library at the build step of your project.\nHowever, if this external Zig library is available on GitHub for example, and it has a valid build.zig.zon file in root folder of the project, which describes the project, you can easily include this library in your project by simply listing this external library in your build.zig.zon file.\nIn other words, this build.zig.zon file works similarly to the package.json file in Javascript projects, or the Pipfile file in Python projects, or the Cargo.toml file in Rust projects. You can read more about this specific file in a couple of articles on the internet23, and you can also see the expected schema for this build.zig.zon file in a documentation file inside the official repository of Zig4.\n\n\n1.2.2 The file root.zig\nLet’s take a look into the root.zig file. You might have noticed that every line of code with an expression ends with a semicolon (;). This follows the syntax of a C-family programming language5.\nAlso, notice the @import() call at the first line. We use this built-in function to import functionality from other Zig modules into our current module. This @import() function works similarly to the #include pre-processor in C or C++, or, to the import statement in Python or Javascript code. In this example, we are importing the std module, which gives you access to the Zig Standard Library.\nIn this root.zig file, we can also see how assignments (i.e. creating new objects) are made in Zig. You can create a new object in Zig by using the following syntax (const|var) name = value;. In the example below, we are creating two constant objects (std and testing). At Section 1.4 we talk more about objects in general.\n\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n\nFunctions in Zig are declared using the fn keyword. In this root.zig module, we are declaring a function called add(), which has two arguments named a and b. The function returns an integer of the type i32 as result.\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit the type of an object in your code, if this type can be inferred by the zig compiler (we talk more about that at Section 2.4). But there are other situations where you do need to be explicit. For example, you do have to explicitly specify the type of each function argument, and also, the return type of every function that you create in Zig.\nWe specify the type of an object or a function argument in Zig by using a colon character (:) followed by the type after the name of this object/function argument. With the expressions a: i32 and b: i32, we know that both a and b arguments have type i32, which is a signed 32 bit integer. In this part, the syntax in Zig is identical to the syntax in Rust, which also specifies types by using the colon character.\nLastly, we have the return type of the function at the end of the line, before we open the curly braces to start writing the function’s body. In the example above, this type is also a signed 32 bit integer (i32) value.\nNotice that we also have an export keyword before the function declaration. This keyword is similar to the extern keyword in C. It exposes the function to make it available in the library API. Therefore, if you are writing a library for other people to use, you have to expose the functions you write in the public API of this library by using this export keyword. If we removed the export keyword from the add() function declaration, then, this function would be no longer exposed in the library object built by the zig compiler.\n\n\n1.2.3 The main.zig file\nNow that we have learned a lot about Zig’s syntax from the root.zig file, let’s take a look at the main.zig file. A lot of the elements we saw in root.zig are also present in main.zig. But there are some other elements that we haven’t seen yet, so let’s dive in.\nFirst, look at the return type of the main() function in this file. We can see a small change. The return type of the function (void) is accompanied by an exclamation mark (!). This exclamation mark tells us that this main() function might return an error.\nIs worth noting that, a main() function in Zig is allowed to return nothing (void), or an unsigned 8-bit integer (u8) value6, or an error. In other words, you can write your main() function in Zig to return essentially nothing (void), or, if you prefer, you can also write a more C-like main() function, which returns an integer value that usually serves as a “status code” for the process.\nIn this example, the return type annotation of main() indicates that this function can either return nothing (void), or return an error. This exclamation mark in the return type annotation is an interesting and powerful feature of Zig. In summary, if you write a function and something inside the body of this function might return an error, then, you are forced to:\n\neither add the exclamation mark to the return type of the function and make it clear that this function might return an error.\nexplicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through a try catch pattern. Zig does have both try and catch keywords. But they work a little differently than what you’re probably used to in other languages.\nIf we look at the main() function below, you can see that we do have a try keyword on the 5th line. But we do not have a catch keyword in this code. In Zig, we use the try keyword to execute an expression that might return an error, which, in this example, is the stdout.print() expression.\nIn essence, the try keyword executes the expression stdout.print(). If this expression returns a valid value, then, the try keyword does absolutely nothing. It only passes the value forward. It is like if this try keyword was never there. However, if the expression does return an error, then, the try keyword will unwrap the error value, then, it returns this error from the function and also prints the current stack trace to stderr.\nThis might sound weird to you if you come from a high-level language. Because in high-level languages, such as Python, if an error occurs somewhere, this error is automatically returned and the execution of your program will automatically stop even if you don’t want to stop the execution. You are obligated to face the error.\n\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n\nAnother thing that you might have noticed in this code example, is that the main() function is marked with the pub keyword. It marks the main() function as a public function from this module. Every function in your Zig module is by default private to this Zig module and can only be called from within the module. Unless, you explicitly mark this function as a public function with the pub keyword.\nIf you think about it, this pub keyword in Zig does essentially the opposite of what the static keyword do in C/C++. By making a function “public” you allow other Zig modules to access and call this function. A calling Zig module imports another module by using the @import() built-in function, which makes all public functions from the imported module visible to the calling Zig module.\n\n\n1.2.4 Compiling your source code\nYou can compile your Zig modules into a binary executable by running the build-exe command from the zig compiler. You simply list all the Zig modules that you want to build after the build-exe command, separated by spaces. In the example below, we are compiling the module main.zig.\nzig build-exe src/main.zig\nSince we are building an executable, the zig compiler will look for a main() function declared in any of the files that you list after the build-exe command. If the compiler does not find a main() function declared somewhere, a compilation error will be raised, warning about this mistake.\nThe zig compiler also offers a build-lib and build-obj commands, which work the exact same way as the build-exe command. The only difference is that, they compile your Zig modules into a portale C ABI library, or, into object files, respectively.\nIn the case of the build-exe command, a binary executable file is created by the zig compiler in the root directory of your project. If we take a look now at the contents of our current directory, with a simple ls command, we can see the binary file called main that was created by the compiler.\nls\nbuild.zig build.zig.zon main src\nIf I execute this binary executable, I get the “Hello World” message in the terminal , as we expected.\n./main\nHello, world!\n\n\n1.2.5 Compile and execute at the same time\nOn the previous section, I presented the zig build-exe command, which compiles Zig modules into an executable file. However, this means that, in order to execute the executable file, we have to run two different commands. First, the zig build-exe command, and then, we call the executable file created by the compiler.\nBut what if we wanted to perform these two steps, all at once, in a single command? We can do that by using the zig run command.\nzig run src/main.zig\nHello, world!\n\n\n1.2.6 Important note for Windows users\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other operating systems, such as Linux and macOs. In summary, if you have a piece of Zig code that includes some global variables whose initialization rely on runtime resources, then, you might have some troubles while trying to compile this Zig code on Windows.\nAn example of that is accessing the stdout (i.e. the standard output of your system), which is usually done in Zig by using the expression std.io.getStdOut(). Thus, if you use this expression to instantiate a global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows, with a “unable to evaluate comptime expression” error message.\nThis failure in the compilation process happens because all global variables in Zig are initialized at compile-time. However, operations like accessing the stdout (or opening a file) on Windows depends on resources that are available only at runtime (you will learn more about compile-time versus runtime at Section 3.1.1).\nFor example, if you try to compile this code example on Windows, you will likely get the error message exposed below:\n\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\nTo avoid this problem on Windows, we need to force the zig compiler to instantiate this stdout object only at runtime, instead of instantiating it at compile-time. We can achieve that by simply moving the expression to a function body.\nThis solves the problem because all expressions that are inside a function body in Zig are evaluated only at runtime, unless you use the comptime keyword explicitly to change this behaviour. You will learn more about this comptime keyword at Section 12.1.\n\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n\nHello\nYou can read more details about this Windows-specific limitation at a couple of GitHub issues opened at the official Zig repository. More specifically, the issues 17186 7 and 19864 8.\n\n\n1.2.7 Compiling the entire project\nJust as I described at Section 1.2.1, as our project grows in size and complexity, we usually prefer to organize the compilation and build process of the project into a build script, using some sort of “build system”.\nIn other words, as our project grows in size and complexity, the build-exe, build-lib and build-obj commands become harder to use directly. Because then, we start to list multiple and multiple modules at the same time. We also start to add built-in compilation flags to customize the build process for our needs, etc. It becomes a lot of work to write the necessary commands by hand.\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, Makefile or configure scripts to organize this process. However, in Zig, we have a native build system in the language itself. So, we can write build scripts in Zig to compile and build Zig projects. Then, all we need to do, is to call the zig build command to build our project.\nSo, when you execute the zig build command, the zig compiler will search for a Zig module named build.zig inside your current directory, which should be your build script, containing the necessary code to compile and build your project. If the compiler does find this build.zig file in your directory, then, the compiler will essentially execute a zig run command over this build.zig file, to compile and execute this build script, which in turn, will compile and build your entire project.\nzig build\nAfter you execute this “build project” command, a zig-out directory is created in the root of your project directory, where you can find the binary executables and libraries created from your Zig modules accordingly to the build commands that you specified at build.zig. We will talk more about the build system in Zig latter in this book.\nIn the example below, I’m executing the binary executable named hello_world that was generated by the compiler after the zig build command.\n./zig-out/bin/hello_world\nHello, world!", "crumbs": [ "1  Introducing Zig" ] @@ -144,7 +144,7 @@ "href": "Chapters/01-zig-weird.html#sec-assignments", "title": "1  Introducing Zig", "section": "1.4 Creating new objects in Zig (i.e. identifiers)", - "text": "1.4 Creating new objects in Zig (i.e. identifiers)\nLet’s talk more about objects in Zig. Readers that have past experience with other programming languages might know this concept through a different name, such as: “variable” or “identifier”. In this book, I choose to use the term “object” to refer to this concept.\nTo create a new object (or a new “identifier”) in Zig, we use the keywords const or var. These keywords specify if the object that you are creating is mutable or not. If you use const, then the object you are creating is a constant (or immutable) object, which means that once you declare this object, you can no longer change the value stored inside this object.\nOn the other side, if you use var, then, you are creating a variable (or mutable) object. You can change the value of this object as many times you want. Using the keyword var in Zig is similar to using the keywords let mut in Rust.\n\n1.4.1 Constant objects vs variable objects\nIn the code example below, we are creating a new constant object called age. This object stores a number representing the age of someone. However, this code example does not compiles successfully. Because on the next line of code, we are trying to change the value of the object age to 25.\nThe zig compiler detects that we are trying to change the value of an object/identifier that is constant, and because of that, the compiler will raise a compilation error, warning us about the mistake.\n\nconst age = 24;\n// The line below is not valid!\nage = 25;\n\nt.zig:10:5: error: cannot assign to constant\n age = 25;\n ~~^~~\nIn contrast, if you use var, then, the object created is a variable object. With var you can declare this object in your source code, and then, change the value of this object how many times you want over future points in your source code.\nSo, using the same code example exposed above, if I change the declaration of the age object to use the var keyword, then, the program gets compiled successfully. Because now, the zig compiler detects that we are changing the value of an object that allows this behaviour, because it is an “variable object”.\n\nvar age: u8 = 24;\nage = 25;\n\n\n\n1.4.2 Declaring without an initial value\nBy default, when you declare a new object in Zig, you must give it an initial value. In other words, this means that we have to declare, and, at the same time, initialize every object we create in our source code.\nOn the other hand, you can, in fact, declare a new object in your source code, and not give it an explicit value. But we need to use a special keyword for that, which is the undefined keyword.\nIs important to emphasize that, you should avoid using undefined as much as possible. Because when you use this keyword, you leave your object uninitialized, and, as a consequence, if for some reason, your code use this object while it is uninitialized, then, you will definitely have undefined behaviour and major bugs in your program.\nIn the example below, I’m declaring the age object again. But this time, I do not give it an initial value. The variable is only initialized at the second line of code, where I store the number 25 in this object.\n\nvar age: u8 = undefined;\nage = 25;\n\nHaving these points in mind, just remember that you should avoid as much as possible to use undefined in your code. Always declare and initialize your objects. Because this gives you much more safety in your program. But in case you really need to declare an object without initializing it… the undefined keyword is the way to do it in Zig.\n\n\n1.4.3 There is no such thing as unused objects\nEvery object (being constant or variable) that you declare in Zig must be used in some way. You can give this object to a function call, as a function argument, or, you can use it in another expression to calculate the value of another object, or, you can call a method that belongs to this particular object.\nIt doesn’t matter in which way you use it. As long as you use it. If you try to break this rule, i.e. if your try to declare a object, but not use it, the zig compiler will not compile your Zig source code, and it will issue a error message warning that you have unused objects in your code.\nLet’s demonstrate this with an example. In the source code below, we declare a constant object called age. If you try to compile a simple Zig program with this line of code below, the compiler will return an error as demonstrated below:\n\nconst age = 15;\n\nt.zig:4:11: error: unused local constant\n const age = 15;\n ^~~\nEverytime you declare a new object in Zig, you have two choices:\n\nyou either use the value of this object;\nor you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign this object to an special character in Zig, which is the underscore (_). When you assign an object to a underscore, like in the example below, the zig compiler will automatically discard the value of this particular object.\nYou can see in the example below that, this time, the compiler did not complain about any “unused constant”, and successfully compiled our source code.\n\n// It compiles!\nconst age = 15;\n_ = age;\n\nNow, remember, everytime you assign a particular object to the underscore, this object is essentially destroyed. It is discarded by the compiler. This means that you can no longer use this object further in your code. It doesn’t exist anymore.\nSo if you try to use the constant age in the example below, after we discarded it, you will get a loud error message from the compiler (talking about a “pointless discard”) warning you about this mistake.\n\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n\nt.zig:7:5: error: pointless discard\n of local constant\nThis same rule applies to variable objects. Every variable object must also be used in some way. And if you assign a variable object to the underscore, this object also get’s discarded, and you can no longer use this object.\n\n\n1.4.4 You must mutate every variable objects\nEvery variable object that you create in your source code must be mutated at some point. In other words, if you declare an object as a variable object, with the keyword var, and you do not change the value of this object at some point in the future, the zig compiler will detect this, and it will raise an error warning you about this mistake.\nThe concept behind this is that every object you create in Zig should be preferably a constant object, unless you really need an object whose value will change during the execution of your program.\nSo, if I try to declare a variable object such as where_i_live below, and I do not change the value of this object in some way, the zig compiler raises an error message with the phrase “variable is never mutated”.\n\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'", + "text": "1.4 Creating new objects in Zig (i.e. identifiers)\nLet’s talk more about objects in Zig. Readers that have past experience with other programming languages might know this concept through a different name, such as: “variable” or “identifier”. In this book, I choose to use the term “object” to refer to this concept.\nTo create a new object (or a new “identifier”) in Zig, we use the keywords const or var. These keywords specify if the object that you are creating is mutable or not. If you use const, then the object you are creating is a constant (or immutable) object, which means that once you declare this object, you can no longer change the value stored inside this object.\nOn the other side, if you use var, then, you are creating a variable (or mutable) object. You can change the value of this object as many times you want. Using the keyword var in Zig is similar to using the keywords let mut in Rust.\n\n1.4.1 Constant objects vs variable objects\nIn the code example below, we are creating a new constant object called age. This object stores a number representing the age of someone. However, this code example does not compile successfully. Because on the next line of code, we are trying to change the value of the object age to 25.\nThe zig compiler detects that we are trying to change the value of an object/identifier that is constant, and because of that, the compiler will raise a compilation error, warning us about the mistake.\n\nconst age = 24;\n// The line below is not valid!\nage = 25;\n\nt.zig:10:5: error: cannot assign to constant\n age = 25;\n ~~^~~\nIn contrast, if you use var, then, the object created is a variable object. With var you can declare this object in your source code, and then, change the value of this object how many times you want over future points in your source code.\nSo, using the same code example exposed above, if I change the declaration of the age object to use the var keyword, then, the program gets compiled successfully. Because now, the zig compiler detects that we are changing the value of an object that allows this behaviour, because it is an “variable object”.\n\nvar age: u8 = 24;\nage = 25;\n\n\n\n1.4.2 Declaring without an initial value\nBy default, when you declare a new object in Zig, you must give it an initial value. In other words, this means that we have to declare, and, at the same time, initialize every object we create in our source code.\nOn the other hand, you can, in fact, declare a new object in your source code, and not give it an explicit value. But we need to use a special keyword for that, which is the undefined keyword.\nIs important to emphasize that, you should avoid using undefined as much as possible. Because when you use this keyword, you leave your object uninitialized, and, as a consequence, if for some reason, your code use this object while it is uninitialized, then, you will definitely have undefined behaviour and major bugs in your program.\nIn the example below, I’m declaring the age object again. But this time, I do not give it an initial value. The variable is only initialized at the second line of code, where I store the number 25 in this object.\n\nvar age: u8 = undefined;\nage = 25;\n\nHaving these points in mind, just remember that you should avoid as much as possible to use undefined in your code. Always declare and initialize your objects. Because this gives you much more safety in your program. But in case you really need to declare an object without initializing it… the undefined keyword is the way to do it in Zig.\n\n\n1.4.3 There is no such thing as unused objects\nEvery object (being constant or variable) that you declare in Zig must be used in some way. You can give this object to a function call, as a function argument, or, you can use it in another expression to calculate the value of another object, or, you can call a method that belongs to this particular object.\nIt doesn’t matter in which way you use it. As long as you use it. If you try to break this rule, i.e. if your try to declare a object, but not use it, the zig compiler will not compile your Zig source code, and it will issue a error message warning that you have unused objects in your code.\nLet’s demonstrate this with an example. In the source code below, we declare a constant object called age. If you try to compile a simple Zig program with this line of code below, the compiler will return an error as demonstrated below:\n\nconst age = 15;\n\nt.zig:4:11: error: unused local constant\n const age = 15;\n ^~~\nEverytime you declare a new object in Zig, you have two choices:\n\nyou either use the value of this object;\nor you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign this object to an special character in Zig, which is the underscore (_). When you assign an object to a underscore, like in the example below, the zig compiler will automatically discard the value of this particular object.\nYou can see in the example below that, this time, the compiler did not complain about any “unused constant”, and successfully compiled our source code.\n\n// It compiles!\nconst age = 15;\n_ = age;\n\nNow, remember, everytime you assign a particular object to the underscore, this object is essentially destroyed. It is discarded by the compiler. This means that you can no longer use this object further in your code. It doesn’t exist anymore.\nSo if you try to use the constant age in the example below, after we discarded it, you will get a loud error message from the compiler (talking about a “pointless discard”) warning you about this mistake.\n\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n\nt.zig:7:5: error: pointless discard\n of local constant\nThis same rule applies to variable objects. Every variable object must also be used in some way. And if you assign a variable object to the underscore, this object also get’s discarded, and you can no longer use this object.\n\n\n1.4.4 You must mutate every variable objects\nEvery variable object that you create in your source code must be mutated at some point. In other words, if you declare an object as a variable object, with the keyword var, and you do not change the value of this object at some point in the future, the zig compiler will detect this, and it will raise an error warning you about this mistake.\nThe concept behind this is that every object you create in Zig should be preferably a constant object, unless you really need an object whose value will change during the execution of your program.\nSo, if I try to declare a variable object such as where_i_live below, and I do not change the value of this object in some way, the zig compiler raises an error message with the phrase “variable is never mutated”.\n\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'", "crumbs": [ "1  Introducing Zig" ] @@ -184,7 +184,7 @@ "href": "Chapters/01-zig-weird.html#sec-zig-strings", "title": "1  Introducing Zig", "section": "1.8 How strings work in Zig?", - "text": "1.8 How strings work in Zig?\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (Chapter 4). But in order for us to build such a thing, we need to get a better understanding on how strings work in Zig. So let’s discuss this specific aspect of Zig.\nIn summary, there are two types of string values that you care about in Zig, which are:\n\nString literal values.\nString objects.\n\nA string literal value is just a pointer to a null-terminated array of bytes (i.e. similar to a C string). But in Zig, a string literal value also embeds the length of the string into the data type of the value itself. Therefore, a string literal value have a data type in the format *const [n:0]u8. The n in the data type indicates the size of the string.\nOn the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes, or, in other words, a slice of u8 values (slices were presented at Section 1.6). Thus, a string object have a data type of []u8 or []const u8, depending if the string object is marked as constant with const, or as variable with var.\nBecause a string object is essentially a slice, it means that a string object always contains two things: a pointer to an array of bytes (i.e. u8 values) that represents the string value; and also, a length value, which specifies the size of the slice, or, how many elements there is in the slice. Is worth to emphasize that the array of bytes in a string object is not null-terminated, like in a string literal value.\n\n// This is a string literal value:\n\"A literal value\";\n// This is a string object:\nconst object: []const u8 = \"A string object\";\n\nZig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every sequence of bytes you’re working with, but is not really Zig’s job to fix the encoding of your strings (you can use iconv22 for that). Today, most of the text in our modern world, especially on the web, should be UTF-8 encoded. So if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\nLet’s take for example the word “Hello”. In UTF-8, this sequence of characters (H, e, l, l, o) is represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this sequence is 0x48, 0x65, 0x6C, 0x6C, 0x6F. So if I take this sequence of hexadecimal values, and ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then, the text “Hello” will be printed into the terminal:\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n try stdout.print(\"{s}\\n\", .{bytes});\n}\n\nHello\n\n\nIf you want to see the actual bytes that represents a string in Zig, you can use a for loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal value to the terminal. You do that by using a print() statement with the X formatting specifier, like you would normally do with the printf() function23 in C.\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example\";\n try stdout.print(\"Bytes that represents the string object: \", .{});\n for (string_object) |byte| {\n try stdout.print(\"{X} \", .{byte});\n }\n try stdout.print(\"\\n\", .{});\n}\n\nBytes that represents the string object: 54 68 69 \n 73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n\n\n\n1.8.1 Strings in C\nAt first glance, a string literal value in Zig looks very similar to how C treats strings as well. In more details, string values in C are treated internally as an array of arbitrary bytes, and this array is also null-terminated.\nBut one key difference between a Zig string literal and a C string, is that Zig also stores the length of the string inside the object itself. In the case of a string literal value, this length is stored in the data type of the value (i.e. the n variable in [n:0]u8). While, in a string object, the length is stored in the len attribute of the slice that represents the string object. This small detail makes your code safer, because is much easier for the Zig compiler to check if you are trying to access an element that is “out of bounds”, i.e. if your trying to access memory that does not belong to you.\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless. So getting this kind of safety is not automatic and much harder to do in C. For example, if you want to track the length of your string throughout your program in C, then, you first need to loop through the array of bytes that represents this string, and find the null element ('\\0') position to discover where exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\nTo do that, you would need something like this in C. In this example, the C string stored in the object array is 25 bytes long:\n\n#include <stdio.h>\nint main() {\n char* array = \"An example of string in C\";\n int index = 0;\n while (1) {\n if (array[index] == '\\0') {\n break;\n }\n index++;\n }\n printf(\"Number of elements in the array: %d\\n\", index);\n}\n\nNumber of elements in the array: 25\nYou don’t have this kind of work in Zig. Because the length of the string is always present and accessible. In a string object for example, you can easily access the length of the string through the len attribute. As an example, the string_object object below is 43 bytes long:\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example of string literal in Zig\";\n try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n\n43\n\n\n\n\n1.8.2 A better look at the object type\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the @TypeOf() function. If we look at the type of the simple_array object below, you will find that this object is an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type i32 in Zig. That is what an object of type [4]i32 is.\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a constant pointer (hence the *const annotation) to an array of 16 elements (or 16 bytes). Each element is a single byte (more precisely, an unsigned 8 bit integer - u8), that is why we have the [16:0]u8 portion of the type below. In other words, the string literal value exposed below is 16 bytes long.\nNow, if we create an pointer to the simple_array object, then, we get a constant pointer to an array of 4 elements (*const [4]i32), which is very similar to the type of the string literal value. This demonstrates that a string literal value in Zig is already a pointer to a null-terminated array of bytes.\nFurthermore, if we take a look at the type of the string_obj object, you will see that it is a slice object (hence the [] portion of the type) to a sequence of constant u8 values (hence the const u8 portion of the type).\n\nconst std = @import(\"std\");\npub fn main() !void {\n const simple_array = [_]i32{1, 2, 3, 4};\n const string_obj: []const u8 = \"A string object\";\n std.debug.print(\n \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n );\n std.debug.print(\n \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n );\n std.debug.print(\n \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n );\n std.debug.print(\n \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n );\n}\n\nType 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons\n st [4]i32Type 4: []const u8\n\n\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n\n\n1.8.3 Byte vs unicode points\nIs important to point out that each byte in the array is not necessarily a single character. This fact arises from the difference between a single byte and a single unicode point.\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in the string. For example, the character “H” is stored in UTF-8 as the decimal number 72. This means that the number 72 is the unicode point for the character “H”. Each possible character that can appear in a UTF-8 encoded string have its own unicode point.\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point) 570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which is 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why, the unicode point 570 is actually stored inside the computer’s memory as the bytes C8 BA.\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"Ⱥ\";\n _ = try stdout.write(\n \"Bytes that represents the string object: \"\n );\n for (string_object) |char| {\n try stdout.print(\"{X} \", .{char});\n }\n}\n\nBytes that represents the string object: C8 BA \n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together to represent the number 570. That is why the relationship between bytes and unicode points is not always 1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds to a single unicode point.\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the bytes that represents that string, and not through the characters of that string. In the Ⱥ example above, the for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a consequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because the number of bytes will be equal to the number of characters in that string. In other words, in this specific situation, the relationship between bytes and unicode points is 1 to 1.\nBut on the other side, if your string contains other types of letters… for example, you might be working with text data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent your UTF-8 string will likely be much higher than the number of characters in that string.\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the std.unicode.Utf8View struct to create an iterator that iterates through the unicode points of your string.\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in this string is represented by three bytes. But the for loop iterates four times, one iteration for each character/unicode point in this string:\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n var iterator = utf8.iterator();\n while (iterator.nextCodepointSlice()) |codepoint| {\n try stdout.print(\n \"got codepoint {}\\n\",\n .{std.fmt.fmtSliceHexUpper(codepoint)},\n );\n }\n}\n\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n\n\n1.8.4 Some useful functions for strings\nIn this section, I just want to quickly describe some functions from the Zig Standard Library that are very useful to use when working with strings. Most notably:\n\nstd.mem.eql(): to compare if two strings are equal.\nstd.mem.splitScalar(): to split a string into an array of substrings given a delimiter value.\nstd.mem.splitSequence(): to split a string into an array of substrings given a substring delimiter.\nstd.mem.startsWith(): to check if string starts with substring.\nstd.mem.endsWith(): to check if string ends with substring.\nstd.mem.trim(): to remove specific values from both start and end of the string.\nstd.mem.concat(): to concatenate strings together.\nstd.mem.count(): to count the occurrences of substring in the string.\nstd.mem.replace(): to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the mem module of the Zig Standard Library. This module contains multiple functions and methods that are useful to work with memory and sequences of bytes in general.\nThe eql() function is used to check if two arrays of data are equal or not. Since strings are just arbitrary arrays of bytes, we can use this function to compare two strings together. This function returns a boolean value indicating if the two strings are equal or not. The first argument of this function is the data type of the elements of the arrays that are being compared.\n\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n\ntrue\n\n\nThe splitScalar() and splitSequence() functions are useful to split a string into multiple fragments, like the split() method from Python strings. The difference between these two methods is that the splitScalar() uses a single character as the separator to split the string, while splitSequence() uses a sequence of characters (a.k.a. a substring) as the separator. There is a practical example of these functions later in the book.\nThe startsWith() and endsWith() functions are pretty straightforward. They return a boolean value indicating if the string (or, more precisely, if the array of data) begins (startsWith) or ends (endsWith) with the sequence provided.\n\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n\ntrue\n\n\nThe concat() function, as the name suggests, concatenate two or more strings together. Because the process of concatenating the strings involves allocating enough space to accomodate all the strings together, this concat() function receives an allocator object as input.\n\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n\nAs you can imagine, the replace() function is used to replace substrings in a string by another substring. This function works very similarly to the replace() method from Python strings. Therefore, you provide a substring to search, and every time that the replace() function finds this substring within the input string, it replaces this substring with the “replacement substring” that you provided as input.\nIn the example below, we are taking the input string “Hello”, and replacing all occurrences of the substring “el” inside this input string with “34”, and saving the results inside the buffer object. As result, the replace() function returns an usize value that indicates how many replacements were performed.\n\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n\nNew string: H34lo\nN of replacements: 1", + "text": "1.8 How strings work in Zig?\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (Chapter 4). But in order for us to build such a thing, we need to get a better understanding on how strings work in Zig. So let’s discuss this specific aspect of Zig.\nIn summary, there are two types of string values that you care about in Zig, which are:\n\nString literal values.\nString objects.\n\nA string literal value is just a pointer to a null-terminated array of bytes (i.e. similar to a C string). But in Zig, a string literal value also embeds the length of the string into the data type of the value itself. Therefore, a string literal value have a data type in the format *const [n:0]u8. The n in the data type indicates the size of the string.\nOn the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes, or, in other words, a slice of u8 values (slices were presented at Section 1.6). Thus, a string object have a data type of []u8 or []const u8, depending if the string object is marked as constant with const, or as variable with var.\nBecause a string object is essentially a slice, it means that a string object always contains two things: a pointer to an array of bytes (i.e. u8 values) that represents the string value; and also, a length value, which specifies the size of the slice, or, how many elements there is in the slice. Is worth to emphasize that the array of bytes in a string object is not null-terminated, like in a string literal value.\n\n// This is a string literal value:\n\"A literal value\";\n// This is a string object:\nconst object: []const u8 = \"A string object\";\n\nZig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every sequence of bytes you’re working with, but is not really Zig’s job to fix the encoding of your strings (you can use iconv22 for that). Today, most of the text in our modern world, especially on the web, should be UTF-8 encoded. So if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\nLet’s take for example the word “Hello”. In UTF-8, this sequence of characters (H, e, l, l, o) is represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this sequence is 0x48, 0x65, 0x6C, 0x6C, 0x6F. So if I take this sequence of hexadecimal values, and ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then, the text “Hello” will be printed into the terminal:\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n try stdout.print(\"{s}\\n\", .{bytes});\n}\n\nHello\n\n\nIf you want to see the actual bytes that represents a string in Zig, you can use a for loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal value to the terminal. You do that by using a print() statement with the X formatting specifier, like you would normally do with the printf() function23 in C.\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example\";\n try stdout.print(\"Bytes that represents the string object: \", .{});\n for (string_object) |byte| {\n try stdout.print(\"{X} \", .{byte});\n }\n try stdout.print(\"\\n\", .{});\n}\n\nBytes that represents the string object: 54 68 69 \n 73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n\n\n\n1.8.1 Strings in C\nAt first glance, a string literal value in Zig looks very similar to how C treats strings as well. In more details, string values in C are treated internally as an array of arbitrary bytes, and this array is also null-terminated.\nBut one key difference between a Zig string literal and a C string, is that Zig also stores the length of the string inside the object itself. In the case of a string literal value, this length is stored in the data type of the value (i.e. the n variable in [n:0]u8). While, in a string object, the length is stored in the len attribute of the slice that represents the string object. This small detail makes your code safer, because it is much easier for the Zig compiler to check if you are trying to access an element that is “out of bounds”, i.e. if your trying to access memory that does not belong to you.\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless. So getting this kind of safety is not automatic and much harder to do in C. For example, if you want to track the length of your string throughout your program in C, then, you first need to loop through the array of bytes that represents this string, and find the null element ('\\0') position to discover where exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\nTo do that, you would need something like this in C. In this example, the C string stored in the object array is 25 bytes long:\n\n#include <stdio.h>\nint main() {\n char* array = \"An example of string in C\";\n int index = 0;\n while (1) {\n if (array[index] == '\\0') {\n break;\n }\n index++;\n }\n printf(\"Number of elements in the array: %d\\n\", index);\n}\n\nNumber of elements in the array: 25\nYou don’t have this kind of work in Zig. Because the length of the string is always present and accessible. In a string object for example, you can easily access the length of the string through the len attribute. As an example, the string_object object below is 43 bytes long:\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example of string literal in Zig\";\n try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n\n43\n\n\n\n\n1.8.2 A better look at the object type\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the @TypeOf() function. If we look at the type of the simple_array object below, you will find that this object is an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type i32 in Zig. That is what an object of type [4]i32 is.\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a constant pointer (hence the *const annotation) to an array of 16 elements (or 16 bytes). Each element is a single byte (more precisely, an unsigned 8 bit integer - u8), that is why we have the [16:0]u8 portion of the type below. In other words, the string literal value exposed below is 16 bytes long.\nNow, if we create an pointer to the simple_array object, then, we get a constant pointer to an array of 4 elements (*const [4]i32), which is very similar to the type of the string literal value. This demonstrates that a string literal value in Zig is already a pointer to a null-terminated array of bytes.\nFurthermore, if we take a look at the type of the string_obj object, you will see that it is a slice object (hence the [] portion of the type) to a sequence of constant u8 values (hence the const u8 portion of the type).\n\nconst std = @import(\"std\");\npub fn main() !void {\n const simple_array = [_]i32{1, 2, 3, 4};\n const string_obj: []const u8 = \"A string object\";\n std.debug.print(\n \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n );\n std.debug.print(\n \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n );\n std.debug.print(\n \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n );\n std.debug.print(\n \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n );\n}\n\nType 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons\n st [4]i32Type 4: []const u8\n\n\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n\n\n1.8.3 Byte vs unicode points\nIs important to point out that each byte in the array is not necessarily a single character. This fact arises from the difference between a single byte and a single unicode point.\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in the string. For example, the character “H” is stored in UTF-8 as the decimal number 72. This means that the number 72 is the unicode point for the character “H”. Each possible character that can appear in a UTF-8 encoded string have its own unicode point.\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point) 570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which is 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why, the unicode point 570 is actually stored inside the computer’s memory as the bytes C8 BA.\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"Ⱥ\";\n _ = try stdout.write(\n \"Bytes that represents the string object: \"\n );\n for (string_object) |char| {\n try stdout.print(\"{X} \", .{char});\n }\n}\n\nBytes that represents the string object: C8 BA \n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together to represent the number 570. That is why the relationship between bytes and unicode points is not always 1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds to a single unicode point.\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the bytes that represents that string, and not through the characters of that string. In the Ⱥ example above, the for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a consequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because the number of bytes will be equal to the number of characters in that string. In other words, in this specific situation, the relationship between bytes and unicode points is 1 to 1.\nBut on the other side, if your string contains other types of letters… for example, you might be working with text data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent your UTF-8 string will likely be much higher than the number of characters in that string.\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the std.unicode.Utf8View struct to create an iterator that iterates through the unicode points of your string.\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in this string is represented by three bytes. But the for loop iterates four times, one iteration for each character/unicode point in this string:\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n var iterator = utf8.iterator();\n while (iterator.nextCodepointSlice()) |codepoint| {\n try stdout.print(\n \"got codepoint {}\\n\",\n .{std.fmt.fmtSliceHexUpper(codepoint)},\n );\n }\n}\n\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n\n\n1.8.4 Some useful functions for strings\nIn this section, I just want to quickly describe some functions from the Zig Standard Library that are very useful to use when working with strings. Most notably:\n\nstd.mem.eql(): to compare if two strings are equal.\nstd.mem.splitScalar(): to split a string into an array of substrings given a delimiter value.\nstd.mem.splitSequence(): to split a string into an array of substrings given a substring delimiter.\nstd.mem.startsWith(): to check if string starts with substring.\nstd.mem.endsWith(): to check if string ends with substring.\nstd.mem.trim(): to remove specific values from both start and end of the string.\nstd.mem.concat(): to concatenate strings together.\nstd.mem.count(): to count the occurrences of substring in the string.\nstd.mem.replace(): to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the mem module of the Zig Standard Library. This module contains multiple functions and methods that are useful to work with memory and sequences of bytes in general.\nThe eql() function is used to check if two arrays of data are equal or not. Since strings are just arbitrary arrays of bytes, we can use this function to compare two strings together. This function returns a boolean value indicating if the two strings are equal or not. The first argument of this function is the data type of the elements of the arrays that are being compared.\n\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n\ntrue\n\n\nThe splitScalar() and splitSequence() functions are useful to split a string into multiple fragments, like the split() method from Python strings. The difference between these two methods is that the splitScalar() uses a single character as the separator to split the string, while splitSequence() uses a sequence of characters (a.k.a. a substring) as the separator. There is a practical example of these functions later in the book.\nThe startsWith() and endsWith() functions are pretty straightforward. They return a boolean value indicating if the string (or, more precisely, if the array of data) begins (startsWith) or ends (endsWith) with the sequence provided.\n\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n\ntrue\n\n\nThe concat() function, as the name suggests, concatenate two or more strings together. Because the process of concatenating the strings involves allocating enough space to accomodate all the strings together, this concat() function receives an allocator object as input.\n\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n\nAs you can imagine, the replace() function is used to replace substrings in a string by another substring. This function works very similarly to the replace() method from Python strings. Therefore, you provide a substring to search, and every time that the replace() function finds this substring within the input string, it replaces this substring with the “replacement substring” that you provided as input.\nIn the example below, we are taking the input string “Hello”, and replacing all occurrences of the substring “el” inside this input string with “34”, and saving the results inside the buffer object. As result, the replace() function returns an usize value that indicates how many replacements were performed.\n\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n\nNew string: H34lo\nN of replacements: 1", "crumbs": [ "1  Introducing Zig" ] @@ -194,7 +194,7 @@ "href": "Chapters/01-zig-weird.html#safety-in-zig", "title": "1  Introducing Zig", "section": "1.9 Safety in Zig", - "text": "1.9 Safety in Zig\nA general trend in modern low-level programming languages is safety. As our modern world becomes more interconnected with technology and computers, the data produced by all of this technology becomes one of the most important (and also, one of the most dangerous) assets that we have.\nThis is probably the main reason why modern low-level programming languages have been giving great attention to safety, especially memory safety, because memory corruption is still the main target for hackers to exploit. The reality is that we don’t have an easy solution for this problem. For now, we only have techniques and strategies that mitigates these problems.\nAs Richard Feldman explains on his most recent GOTO conference talk24 , we haven’t figured it out yet a way to achieve true safety in technology. In other words, we haven’t found a way to build software that won’t be exploited with 100% certainty. We can greatly reduce the risks of our software being exploited, by ensuring memory safety for example. But this is not enough to achieve “true safety” territory.\nBecause even if you write your program in a “safe language”, hackers can still exploit failures in the operating system where your program is running (e.g. maybe the system where your code is running has a “backdoor exploit” that can still affect your code in unexpected ways), or also, they can exploit the features from the architecture of your computer. A recently found exploit that involves memory invalidation through a feature of “memory tags” present in ARM chips is an example of that (Kim et al. 2024).\nThe question is: what have Zig and other languages been doing to mitigate this problem? If we take Rust as an example, Rust is, for the most part25, a memory safe language by enforcing specific rules to the developer. In other words, the key feature of Rust, the borrow checker, forces you to follow a specific logic when you are writing your Rust code, and the Rust compiler will always complain everytime you try to go out of this pattern.\nIn contrast, the Zig language is not a memory safe language by default. There are some memory safety features that you get for free in Zig, especially in arrays and pointer objects. But there are other tools offered by the language, that are not used by default. In other words, the zig compiler does not obligates you to use such tools.\nThe tools listed below are related to memory safety. That is, they help you to achieve memory safety in your Zig code:\n\ndefer allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, “use after free”, and also “double-free” problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\nerrdefer helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\npointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\nZig offers some native types of allocators (called “testing allocators”) that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\narrays and slices in Zig have their lengths embedded in the object itself, which makes the zig compiler very effective on detecting “index out-of-range” type of errors, and avoiding buffer overflows.\n\nDespite these features that Zig offers that are related to memory safety issues, the language also has some rules that help you to achieve another type of safety, which is more related to program logic safety. These rules are:\n\npointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\nswitch statements must exaust all possible options.\nthe zig compiler forces you to handle every possible error in your program.", + "text": "1.9 Safety in Zig\nA general trend in modern low-level programming languages is safety. As our modern world becomes more interconnected with technology and computers, the data produced by all of this technology becomes one of the most important (and also, one of the most dangerous) assets that we have.\nThis is probably the main reason why modern low-level programming languages have been giving great attention to safety, especially memory safety, because memory corruption is still the main target for hackers to exploit. The reality is that we don’t have an easy solution for this problem. For now, we only have techniques and strategies that mitigates these problems.\nAs Richard Feldman explains on his most recent GOTO conference talk24 , we haven’t figured it out yet a way to achieve true safety in technology. In other words, we haven’t found a way to build software that won’t be exploited with 100% certainty. We can greatly reduce the risks of our software being exploited, by ensuring memory safety for example. But this is not enough to achieve “true safety” territory.\nBecause even if you write your program in a “safe language”, hackers can still exploit failures in the operating system where your program is running (e.g. maybe the system where your code is running has a “backdoor exploit” that can still affect your code in unexpected ways), or also, they can exploit the features from the architecture of your computer. A recently found exploit that involves memory invalidation through a feature of “memory tags” present in ARM chips is an example of that (Kim et al. 2024).\nThe question is: what have Zig and other languages been doing to mitigate this problem? If we take Rust as an example, Rust is, for the most part25, a memory safe language by enforcing specific rules to the developer. In other words, the key feature of Rust, the borrow checker, forces you to follow a specific logic when you are writing your Rust code, and the Rust compiler will always complain everytime you try to go out of this pattern.\nIn contrast, the Zig language is not a memory safe language by default. There are some memory safety features that you get for free in Zig, especially in arrays and pointer objects. But there are other tools offered by the language, that are not used by default. In other words, the zig compiler does not obligate you to use such tools.\nThe tools listed below are related to memory safety. That is, they help you to achieve memory safety in your Zig code:\n\ndefer allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, “use after free”, and also “double-free” problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\nerrdefer helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\npointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\nZig offers some native types of allocators (called “testing allocators”) that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\narrays and slices in Zig have their lengths embedded in the object itself, which makes the zig compiler very effective on detecting “index out-of-range” type of errors, and avoiding buffer overflows.\n\nDespite these features that Zig offers that are related to memory safety issues, the language also has some rules that help you to achieve another type of safety, which is more related to program logic safety. These rules are:\n\npointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\nswitch statements must exaust all possible options.\nthe zig compiler forces you to handle every possible error in your program.", "crumbs": [ "1  Introducing Zig" ] @@ -234,7 +234,7 @@ "href": "Chapters/03-structs.html#sec-zig-control-flow", "title": "2  Control flow, structs, modules and types", "section": "", - "text": "2.1.1 If/else statements\nAn if/else statement performs a “conditional flow operation”. A conditional flow control (or choice control) allows you to execute or ignore a certain block of commands based on a logical condition. Many programmers and computer science professionals also use the term “branching” in this case. In essence, an if/else statement allow us to use the result of a logical test to decide whether or not to execute a given block of commands.\nIn Zig, we write if/else statements by using the keywords if and else. We start with the if keyword followed by a logical test inside a pair of parentheses, followed by a pair of curly braces which contains the lines of code to be executed in case the logical test returns the value true.\nAfter that, you can optionally add an else statement. To do that, just add the else keyword followed by a pair of curly braces, with the lines of code to executed in case the logical test defined at if returns false.\nIn the example below, we are testing if the object x contains a number that is greater than 10. Judging by the output printed to the console, we know that this logical test returned false. Because the output in the console is compatible with the line of code present in the else branch of the if/else statement.\n\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n\nx <= 10!\n\n\n\n\n2.1.2 Switch statements\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust. As you would expect, to write a switch statement in Zig we use the switch keyword. We provide the value that we want to “switch over” inside a pair of parentheses. Then, we list the possible combinations (or “branches”) inside a pair of curly braces.\nLet’s take a look at the code example below. You can see that I’m creating an enum type called Role. We talk more about enums in Section 7.6. But in summary, this Role type is listing different types of roles in a fictitious company, like SE for Software Engineer, DE for Data Engineer, PM for Product Manager, etc.\nNotice that we are using the value from the role object in the switch statement, to discover which exact area we need to store in the area variable object. Also notice that we are using type inference inside the switch statement, with the dot character, as we are going to describe in Section 2.4. This makes the zig compiler infer the correct data type of the values (PM, SE, etc.) for us.\nAlso notice that, we are grouping multiple values in the same branch of the switch statement. We just separate each possible value with a comma. For example, if role contains either DE or DA, the area variable would contain the value \"Data & Analytics\", instead of \"Platform\" or \"Sales\".\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n\nPlatform\n\n\n\n2.1.2.1 Switch statements must exhaust all possibilities\nOne very important aspect about switch statements in Zig is that they must exhaust all existing possibilities. In other words, all possible values that could be found inside the order object must be explicitly handled in this switch statement.\nSince the role object have type Role, the only possible values to be found inside this object are PM, SE, DPE, PO, DE, DA and KS. There are no other possible values to be stored in this role object. Thus, the switch statements must have a combination (branch) for each one of these values. This is what “exhaust all existing possibilities” means. The switch statement covers every possible case.\nTherefore, you cannot write a switch statement in Zig, and leave an edge case with no explicit action to be taken. This is a similar behaviour to switch statements in Rust, which also have to handle all possible cases.\n\n\n2.1.2.2 The else branch\nTake a look at the dump_hex_fallible() function below as an example. This function comes from the Zig Standard Library. More precisely, from the debug.zig module1. There are multiple lines in this function, but I omitted them to focus solely on the switch statement found in this function. Notice that this switch statement has four possible cases (i.e. four explicit branches). Also, notice that we used an else branch in this case.\nAn else branch in a switch statement works as the “default branch”. Whenever you have multiple cases in your switch statement where you want to apply the exact same action, you can use an else branch to do that.\n\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n\nMany programmers would also use an else branch to handle a “not supported” case. That is, a case that cannot be properly handled by your code, or, just a case that should not be “fixed”. Therefore, you can use an else branch to panic (or raise an error) in your program to stop the current execution.\nTake the code example below. We can see that, we are handling the cases for the level object being either 1, 2, or 3. All other possible cases are not supported by default, and, as consequence, we raise a runtime error in such cases through the @panic() built-in function.\nAlso notice that, we are assigning the result of the switch statement to a new object called category. This is another thing that you can do with switch statements in Zig. If a branch outputs a value as result, you can store the result value of the switch statement into a new object.\n\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n\n\n2.1.2.3 Using ranges in switch\nFurthermore, you can also use ranges of values in switch statements. That is, you can create a branch in your switch statement that is used whenever the input value is within the specified range. These “range expressions” are created with the operator .... It is important to emphasize that the ranges created by this operator are inclusive on both ends.\nFor example, I could easily change the previous code example to support all levels between 0 and 100. Like this:\n\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n\nbeginner\n\n\nThis is neat, and it works with character ranges too. That is, I could simply write 'a'...'z', to match any character value that is a lowercase letter, and it would work fine.\n\n\n2.1.2.4 Labeled switch statements\nIn Section 1.7 we have talked about labeling blocks, and also, about using these labels to return a value from the block. Well, from version 0.14.0 and onwards of the zig compiler, you can also apply labels over switch statements, which makes it possible to almost implement a “C goto” like pattern.\nFor example, if you give the label xsw to a switch statement, you can use this label in conjunction with the continue keyword to go back to the beginning of the switch statement. In the example below, the execution goes back to the beginning of the switch statement two times, before ending at the 3 branch.\n\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n else => {\n try stdout.print(\n \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n );\n },\n}\n\n\n\n\n2.1.3 The defer keyword\nWith the defer keyword you can register an expression to be executed when you exit the current scope. Therefore, this keyword has a similar functionality as the on.exit() function from R. Take the foo() function below as an example. When we execute this foo() function, the expression that prints the message “Exiting function …” is getting executed only when the function exits its scope.\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n\nAdding some numbers ...\nMultiplying ...\nExiting function ...\nTherefore, we can use defer to declare an expression that is going to be executed when your code exits the current scope. Some programmers like to interpret the phrase “exit of the current scope” as “the end of the current scope”. But this interpretation might not be entirely correct, depending on what you consider as “the end of the current scope”.\nI mean, what do you consider as the end of the current scope? Is it the closing curly bracket (}) of the scope? Is it when the last expression in the function get’s executed? Is it when the function returns to the previous scope? Etc. For example, it would not be correct to interpret the “exit of the current scope” as the closing curly bracket of the scope. Because the function might exit from an earlier position than this closing curly bracket (e.g. an error value was generated at a previous line inside the function; the function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\nNow, if you remember of what we have discussed in Section 1.7, there are multiple structures in the language that create their own separate scopes. For/while loops, if/else statements, functions, normal blocks, etc. This also affects the interpretation of defer. For example, if you use defer inside a for loop, then, the given expression will be executed everytime this specific for loop exits its own scope.\nBefore we continue, is worth emphasizing that the defer keyword is an “unconditional defer”. Which means that the given expression will be executed no matter how the code exits the current scope. For example, your code might exit the current scope because of an error value being generated, or, because of a return statement, or, a break statement, etc.\n\n\n2.1.4 The errdefer keyword\nOn the previous section, we have discussed the defer keyword, which you can use to register an expression to be executed at the exit of the current scope. But this keyword has a brother, which is the errdefer keyword. While defer is an “unconditional defer”, the errdefer keyword is a “conditional defer”. Which means that the given expression is executed only when you exit the current scope on a very specific circumstance.\nIn more details, the expression given to errdefer is executed only when an error occurs in the current scope. Therefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope in a normal situation, without errors, the expression given to errdefer is not executed.\nThis makes the errdefer keyword one of the many tools available in Zig for error handling. In this section, we are more concerned with the control flow aspects around errdefer. But we are going to discuss errdefer later as a error handling tool in Section 10.2.4.\nThe code example below demonstrates three things:\n\nthat defer is an “unconditional defer”, because the given expression get’s executed regardless of how the function foo() exits its own scope.\nthat errdefer is executed because the function foo() returned an error value.\nthat defer and errdefer expressions are executed in a LIFO (last in, first out) order.\n\n\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\nWhen I say that “defer expressions” are executed in a LIFO order, what I want to say is that the last defer or errdefer expressions in the code are the first ones to be executed. You could also interpret this as: “defer expressions” are executed from bottom to top, or, from last to first.\nTherefore, if I change the order of the defer and errdefer expressions, you will notice that the value of i that get’s printed to the console changes to 1. This doesn’t mean that the defer expression was not executed in this case. This actually means that the defer expression was executed only after the errdefer expression. The code example below demonstrates this:\n\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n\n\n2.1.5 For loops\nA loop allows you to execute the same lines of code multiple times, thus, creating a “repetition space” in the execution flow of your program. Loops are particularly useful when we want to replicate the same function (or the same set of commands) over different inputs.\nThere are different types of loops available in Zig. But the most essential of them all is probably the for loop. A for loop is used to apply the same piece of code over the elements of a slice, or, an array.\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from other languages. You start with the for keyword, then, you list the items that you want to iterate over inside a pair of parentheses. Then, inside of a pair of pipes (|) you should declare an identifier that will serve as your iterator, or, the “repetition index of the loop”.\n\nfor (items) |value| {\n // code to execute\n}\n\nTherefore, instead of using a (value in items) syntax, in Zig, for loops use the syntax (items) |value|. In the example below, you can see that we are looping through the items of the array stored at the object name, and printing to the console the decimal representation of each character in this array.\nIf we wanted, we could also iterate through a slice (or a portion) of the array, instead of iterating through the entire array stored in the name object. Just use a range selector to select the section you want. For example, I could provide the expression name[0..3] to the for loop, to iterate just through the first 3 elements in the array.\n\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n\n80 | 101 | 100 | 114 | 111 | \n\n\nIn the above example we are using the value itself of each element in the array as our iterator. But there are many situations where we need to use an index instead of the actual values of the items.\nYou can do that by providing a second set of items to iterate over. More precisely, you provide the range selector 0.. to the for loop. So, yes, you can use two different iterators at the same time in a for loop in Zig.\nBut remember from Section 1.4 that, every object you create in Zig must be used in some way. So if you declare two iterators in your for loop, you must use both iterators inside the for loop body. But if you want to use just the index iterator, and not use the “value iterator”, then, you can discard the value iterator by maching the value items to the underscore character, like in the example below:\n\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n\n0 | 1 | 2 | 3 | 4 |\n\n\n2.1.6 While loops\nA while loop is created from the while keyword. A for loop iterates through the items of an array, but a while loop will loop continuously, and infinitely, until a logical test (specified by you) becomes false.\nYou start with the while keyword, then, you define a logical expression inside a pair of parentheses, and the body of the loop is provided inside a pair of curly braces, like in the example below:\n\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n\n1 | 2 | 3 | 4 | \n\n\nYou can also specify the increment expression to be used at the beginning of a while loop. To do that, we write the increment expression inside a pair of parentheses after a colon character (:). The code example below demonstrates this other pattern.\n\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n\n1 | 2 | 3 | 4 | \n\n\n\n\n2.1.7 Using break and continue\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using the keywords break and continue, respectively. The while loop presented in the next code example is, at first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to true. But what makes this while loop stop when the i object reaches the count 10? It is the break keyword!\nInside the while loop, we have an if statement that is constantly checking if the i variable is equal to 10. Since we are incrementing the value of i at each iteration of the while loop, this i object will eventually be equal to 10, and when it is, the if statement will execute the break expression, and, as a result, the execution of the while loop is stopped.\nNotice the use of the expect() function from the Zig Standard Library after the while loop. This expect() function is an “assert” type of function. This function checks if the logical test provided is equal to true. If so, the function do nothing. Otherwise (i.e. the logical test is equal to false), the function raises an assertion error.\n\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n\nEverything worked!\n\n\nSince this code example was executed successfully by the zig compiler, without raising any errors, we known that, after the execution of the while loop, the i object is equal to 10. Because if it wasn’t equal to 10, an error would have been raised by expect().\nNow, in the next example, we have a use case for the continue keyword. The if statement is constantly checking if the current index is a multiple of 2. If it is, we jump to the next iteration of the loop. Otherwise, the loop just prints the current index to the console.\n\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n\n1 | 3 | 5 |", + "text": "2.1.1 If/else statements\nAn if/else statement performs a “conditional flow operation”. A conditional flow control (or choice control) allows you to execute or ignore a certain block of commands based on a logical condition. Many programmers and computer science professionals also use the term “branching” in this case. In essence, an if/else statement allow us to use the result of a logical test to decide whether or not to execute a given block of commands.\nIn Zig, we write if/else statements by using the keywords if and else. We start with the if keyword followed by a logical test inside a pair of parentheses, followed by a pair of curly braces which contains the lines of code to be executed in case the logical test returns the value true.\nAfter that, you can optionally add an else statement. To do that, just add the else keyword followed by a pair of curly braces, with the lines of code to executed in case the logical test defined at if returns false.\nIn the example below, we are testing if the object x contains a number that is greater than 10. Judging by the output printed to the console, we know that this logical test returned false. Because the output in the console is compatible with the line of code present in the else branch of the if/else statement.\n\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n\nx <= 10!\n\n\n\n\n2.1.2 Switch statements\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust. As you would expect, to write a switch statement in Zig we use the switch keyword. We provide the value that we want to “switch over” inside a pair of parentheses. Then, we list the possible combinations (or “branches”) inside a pair of curly braces.\nLet’s take a look at the code example below. You can see that I’m creating an enum type called Role. We talk more about enums in Section 7.6. But in summary, this Role type is listing different types of roles in a fictitious company, like SE for Software Engineer, DE for Data Engineer, PM for Product Manager, etc.\nNotice that we are using the value from the role object in the switch statement, to discover which exact area we need to store in the area variable object. Also notice that we are using type inference inside the switch statement, with the dot character, as we are going to describe in Section 2.4. This makes the zig compiler infer the correct data type of the values (PM, SE, etc.) for us.\nAlso notice that, we are grouping multiple values in the same branch of the switch statement. We just separate each possible value with a comma. For example, if role contains either DE or DA, the area variable would contain the value \"Data & Analytics\", instead of \"Platform\" or \"Sales\".\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n\nPlatform\n\n\n\n2.1.2.1 Switch statements must exhaust all possibilities\nOne very important aspect about switch statements in Zig is that they must exhaust all existing possibilities. In other words, all possible values that could be found inside the role object must be explicitly handled in this switch statement.\nSince the role object has type Role, the only possible values to be found inside this object are PM, SE, DPE, PO, DE, DA and KS. There are no other possible values to be stored in this role object. Thus, the switch statements must have a combination (branch) for each one of these values. This is what “exhaust all existing possibilities” means. The switch statement covers every possible case.\nTherefore, you cannot write a switch statement in Zig, and leave an edge case with no explicit action to be taken. This is a similar behaviour to switch statements in Rust, which also have to handle all possible cases.\n\n\n2.1.2.2 The else branch\nTake a look at the dump_hex_fallible() function below as an example. This function comes from the Zig Standard Library. More precisely, from the debug.zig module1. There are multiple lines in this function, but I omitted them to focus solely on the switch statement found in this function. Notice that this switch statement has four possible cases (i.e. four explicit branches). Also, notice that we used an else branch in this case.\nAn else branch in a switch statement works as the “default branch”. Whenever you have multiple cases in your switch statement where you want to apply the exact same action, you can use an else branch to do that.\n\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n\nMany programmers would also use an else branch to handle a “not supported” case. That is, a case that cannot be properly handled by your code, or, just a case that should not be “fixed”. Therefore, you can use an else branch to panic (or raise an error) in your program to stop the current execution.\nTake the code example below. We can see that, we are handling the cases for the level object being either 1, 2, or 3. All other possible cases are not supported by default, and, as consequence, we raise a runtime error in such cases through the @panic() built-in function.\nAlso notice that, we are assigning the result of the switch statement to a new object called category. This is another thing that you can do with switch statements in Zig. If a branch outputs a value as result, you can store the result value of the switch statement into a new object.\n\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n\n\n2.1.2.3 Using ranges in switch\nFurthermore, you can also use ranges of values in switch statements. That is, you can create a branch in your switch statement that is used whenever the input value is within the specified range. These “range expressions” are created with the operator .... It is important to emphasize that the ranges created by this operator are inclusive on both ends.\nFor example, I could easily change the previous code example to support all levels between 0 and 100. Like this:\n\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n\nbeginner\n\n\nThis is neat, and it works with character ranges too. That is, I could simply write 'a'...'z', to match any character value that is a lowercase letter, and it would work fine.\n\n\n2.1.2.4 Labeled switch statements\nIn Section 1.7 we have talked about labeling blocks, and also, about using these labels to return a value from the block. Well, from version 0.14.0 and onwards of the zig compiler, you can also apply labels over switch statements, which makes it possible to almost implement a “C goto” like pattern.\nFor example, if you give the label xsw to a switch statement, you can use this label in conjunction with the continue keyword to go back to the beginning of the switch statement. In the example below, the execution goes back to the beginning of the switch statement two times, before ending at the 3 branch.\n\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n else => {\n try stdout.print(\n \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n );\n },\n}\n\n\n\n\n2.1.3 The defer keyword\nWith the defer keyword you can register an expression to be executed when you exit the current scope. Therefore, this keyword has a similar functionality as the on.exit() function from R. Take the foo() function below as an example. When we execute this foo() function, the expression that prints the message “Exiting function …” is getting executed only when the function exits its scope.\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n\nAdding some numbers ...\nMultiplying ...\nExiting function ...\nTherefore, we can use defer to declare an expression that is going to be executed when your code exits the current scope. Some programmers like to interpret the phrase “exit of the current scope” as “the end of the current scope”. But this interpretation might not be entirely correct, depending on what you consider as “the end of the current scope”.\nI mean, what do you consider as the end of the current scope? Is it the closing curly bracket (}) of the scope? Is it when the last expression in the function get’s executed? Is it when the function returns to the previous scope? Etc. For example, it would not be correct to interpret the “exit of the current scope” as the closing curly bracket of the scope. Because the function might exit from an earlier position than this closing curly bracket (e.g. an error value was generated at a previous line inside the function; the function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\nNow, if you remember of what we have discussed in Section 1.7, there are multiple structures in the language that create their own separate scopes. For/while loops, if/else statements, functions, normal blocks, etc. This also affects the interpretation of defer. For example, if you use defer inside a for loop, then, the given expression will be executed everytime this specific for loop exits its own scope.\nBefore we continue, is worth emphasizing that the defer keyword is an “unconditional defer”. Which means that the given expression will be executed no matter how the code exits the current scope. For example, your code might exit the current scope because of an error value being generated, or, because of a return statement, or, a break statement, etc.\n\n\n2.1.4 The errdefer keyword\nOn the previous section, we have discussed the defer keyword, which you can use to register an expression to be executed at the exit of the current scope. But this keyword has a brother, which is the errdefer keyword. While defer is an “unconditional defer”, the errdefer keyword is a “conditional defer”. Which means that the given expression is executed only when you exit the current scope on a very specific circumstance.\nIn more details, the expression given to errdefer is executed only when an error occurs in the current scope. Therefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope in a normal situation, without errors, the expression given to errdefer is not executed.\nThis makes the errdefer keyword one of the many tools available in Zig for error handling. In this section, we are more concerned with the control flow aspects around errdefer. But we are going to discuss errdefer later as a error handling tool in Section 10.2.4.\nThe code example below demonstrates three things:\n\nthat defer is an “unconditional defer”, because the given expression get’s executed regardless of how the function foo() exits its own scope.\nthat errdefer is executed because the function foo() returned an error value.\nthat defer and errdefer expressions are executed in a LIFO (last in, first out) order.\n\n\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\nWhen I say that “defer expressions” are executed in a LIFO order, what I want to say is that the last defer or errdefer expressions in the code are the first ones to be executed. You could also interpret this as: “defer expressions” are executed from bottom to top, or, from last to first.\nTherefore, if I change the order of the defer and errdefer expressions, you will notice that the value of i that get’s printed to the console changes to 1. This doesn’t mean that the defer expression was not executed in this case. This actually means that the defer expression was executed only after the errdefer expression. The code example below demonstrates this:\n\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n\n\n2.1.5 For loops\nA loop allows you to execute the same lines of code multiple times, thus, creating a “repetition space” in the execution flow of your program. Loops are particularly useful when we want to replicate the same function (or the same set of commands) over different inputs.\nThere are different types of loops available in Zig. But the most essential of them all is probably the for loop. A for loop is used to apply the same piece of code over the elements of a slice, or, an array.\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from other languages. You start with the for keyword, then, you list the items that you want to iterate over inside a pair of parentheses. Then, inside of a pair of pipes (|) you should declare an identifier that will serve as your iterator, or, the “repetition index of the loop”.\n\nfor (items) |value| {\n // code to execute\n}\n\nTherefore, instead of using a (value in items) syntax, in Zig, for loops use the syntax (items) |value|. In the example below, you can see that we are looping through the items of the array stored at the object name, and printing to the console the decimal representation of each character in this array.\nIf we wanted, we could also iterate through a slice (or a portion) of the array, instead of iterating through the entire array stored in the name object. Just use a range selector to select the section you want. For example, I could provide the expression name[0..3] to the for loop, to iterate just through the first 3 elements in the array.\n\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n\n80 | 101 | 100 | 114 | 111 | \n\n\nIn the above example we are using the value itself of each element in the array as our iterator. But there are many situations where we need to use an index instead of the actual values of the items.\nYou can do that by providing a second set of items to iterate over. More precisely, you provide the range selector 0.. to the for loop. So, yes, you can use two different iterators at the same time in a for loop in Zig.\nBut remember from Section 1.4 that, every object you create in Zig must be used in some way. So if you declare two iterators in your for loop, you must use both iterators inside the for loop body. But if you want to use just the index iterator, and not use the “value iterator”, then, you can discard the value iterator by maching the value items to the underscore character, like in the example below:\n\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n\n0 | 1 | 2 | 3 | 4 |\n\n\n2.1.6 While loops\nA while loop is created from the while keyword. A for loop iterates through the items of an array, but a while loop will loop continuously, and infinitely, until a logical test (specified by you) becomes false.\nYou start with the while keyword, then, you define a logical expression inside a pair of parentheses, and the body of the loop is provided inside a pair of curly braces, like in the example below:\n\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n\n1 | 2 | 3 | 4 | \n\n\nYou can also specify the increment expression to be used at the beginning of a while loop. To do that, we write the increment expression inside a pair of parentheses after a colon character (:). The code example below demonstrates this other pattern.\n\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n\n1 | 2 | 3 | 4 | \n\n\n\n\n2.1.7 Using break and continue\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using the keywords break and continue, respectively. The while loop presented in the next code example is, at first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to true. But what makes this while loop stop when the i object reaches the count 10? It is the break keyword!\nInside the while loop, we have an if statement that is constantly checking if the i variable is equal to 10. Since we are incrementing the value of i at each iteration of the while loop, this i object will eventually be equal to 10, and when it is, the if statement will execute the break expression, and, as a result, the execution of the while loop is stopped.\nNotice the use of the expect() function from the Zig Standard Library after the while loop. This expect() function is an “assert” type of function. This function checks if the logical test provided is equal to true. If so, the function do nothing. Otherwise (i.e. the logical test is equal to false), the function raises an assertion error.\n\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n\nEverything worked!\n\n\nSince this code example was executed successfully by the zig compiler, without raising any errors, we known that, after the execution of the while loop, the i object is equal to 10. Because if it wasn’t equal to 10, an error would have been raised by expect().\nNow, in the next example, we have a use case for the continue keyword. The if statement is constantly checking if the current index is a multiple of 2. If it is, we jump to the next iteration of the loop. Otherwise, the loop just prints the current index to the console.\n\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n\n1 | 3 | 5 |", "crumbs": [ "2  Control flow, structs, modules and types" ] @@ -274,7 +274,7 @@ "href": "Chapters/03-structs.html#sec-type-cast", "title": "2  Control flow, structs, modules and types", "section": "2.5 Type casting", - "text": "2.5 Type casting\nIn this section, I want to discuss type casting (or, type conversion) with you. We use type casting when we have an object of type “x”, and we want to convert it into an object of type “y”, i.e. we want to change the data type of the object.\nMost languages have a formal way to perform type casting. In Rust for example, we normally use the keyword as, and in C, we normally use the type casting syntax, e.g. (int) x. In Zig, we use the @as() built-in function to cast an object of type “x”, into an object of type “y”.\nThis @as() function is the preferred way to perform type conversion (or type casting) in Zig. Because it is explicit, and, it also performs the casting only if it is unambiguous and safe. To use this function, you just provide the target data type in the first argument, and, the object that you want cast as the second argument.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n\n1/1 file10b91234368fa.test_0...OKAll 1 tests passe\n ed.\n\n\nThis is the general way to perform type casting in Zig. But remember, @as() works only when casting is unambiguous and safe, and there are situations where these assumptions do not hold. For example, when casting an integer value into a float value, or vice-versa, it is not clear to the compiler how to perform this conversion safely.\nTherefore, we need to use specialized “casting functions” in such situations. For example, if you want to cast an integer value into a float value, then, you should use the @floatFromInt() function. In the inverse scenario, you should use the @intFromFloat() function.\nIn these functions, you just provide the object that you want to cast as input. Then, the target data type of the “type casting operation” is determined by the type annotation of the object where you are saving the results. In the example below, we are casting the object x into a value of type f32, because the object y, which is where we are saving the results, is annotated as an object of type f32.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n\n1/1 file10b9130ae9221.test_0...OKAll 1 tests passe\n ed.\n\n\nAnother built-in function that is very useful when performing type casting operations is @ptrCast(). In essence, we use the @as() built-in function when we want to explicit convert (or cast) a Zig value/object from a type “x” to a type “y”, etc. However, pointers (we are going to discuss pointers in more depth in Chapter 6) are a special type of object in Zig, i.e. they are treated differently from “normal objects”.\nEverytime a pointer is involved in some “type casting operation” in Zig, the @ptrCast() function is used. This function works similarly to @floatFromInt(). You just provide the pointer object that you want to cast as input to this function, and the target data type is, once again, determined by the type annotation of the object where the results are being stored.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n\n1/1 file10b914c434861.test_0...OKAll 1 tests passe\n ed.", + "text": "2.5 Type casting\nIn this section, I want to discuss type casting (or, type conversion) with you. We use type casting when we have an object of type “x”, and we want to convert it into an object of type “y”, i.e. we want to change the data type of the object.\nMost languages have a formal way to perform type casting. In Rust for example, we normally use the keyword as, and in C, we normally use the type casting syntax, e.g. (int) x. In Zig, we use the @as() built-in function to cast an object of type “x”, into an object of type “y”.\nThis @as() function is the preferred way to perform type conversion (or type casting) in Zig. Because it is explicit, and, it also performs the casting only if it is unambiguous and safe. To use this function, you just provide the target data type in the first argument, and, the object that you want cast as the second argument.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n\n1/1 filecdc41797a754.test_0...OKAll 1 tests passed\n d.\n\n\nThis is the general way to perform type casting in Zig. But remember, @as() works only when casting is unambiguous and safe, and there are situations where these assumptions do not hold. For example, when casting an integer value into a float value, or vice-versa, it is not clear to the compiler how to perform this conversion safely.\nTherefore, we need to use specialized “casting functions” in such situations. For example, if you want to cast an integer value into a float value, then, you should use the @floatFromInt() function. In the inverse scenario, you should use the @intFromFloat() function.\nIn these functions, you just provide the object that you want to cast as input. Then, the target data type of the “type casting operation” is determined by the type annotation of the object where you are saving the results. In the example below, we are casting the object x into a value of type f32, because the object y, which is where we are saving the results, is annotated as an object of type f32.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n\n1/1 filecdc428638149.test_0...OKAll 1 tests passed\n d.\n\n\nAnother built-in function that is very useful when performing type casting operations is @ptrCast(). In essence, we use the @as() built-in function when we want to explicit convert (or cast) a Zig value/object from a type “x” to a type “y”, etc. However, pointers (we are going to discuss pointers in more depth in Chapter 6) are a special type of object in Zig, i.e. they are treated differently from “normal objects”.\nEverytime a pointer is involved in some “type casting operation” in Zig, the @ptrCast() function is used. This function works similarly to @floatFromInt(). You just provide the pointer object that you want to cast as input to this function, and the target data type is, once again, determined by the type annotation of the object where the results are being stored.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n\n1/1 filecdc46f71cc03.test_0...OKAll 1 tests passed\n d.", "crumbs": [ "2  Control flow, structs, modules and types" ] From 91ebf325e129c8bc4666aab2b336cf3b6007b191 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Fri, 31 Jan 2025 08:37:05 -0400 Subject: [PATCH 034/151] fix: change his to its --- Chapters/01-memory.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index 0c4de856..c2d329a5 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -121,7 +121,7 @@ For example, the function `input_length()` contains an argument named `input`, w It is impossible to know the value of this particular argument at compile time. And it also is impossible to know the size/length of this particular argument. Because it is an array that do not have a fixed size specified explicitly in the argument type annotation. -So, we know that this `input` argument will be an array of `u8` integers. But we do not know at compile-time, its value, and neither his size. +So, we know that this `input` argument will be an array of `u8` integers. But we do not know at compile-time, its value, and neither its size. This information is known only at runtime, which is the period of time when you program is executed. As a consequence, the value of the expression `input.len` is also known only at runtime. This is an intrinsic characteristic of any function. Just remember that the value of function arguments is usually not "compile-time known". From c30ce1c4e62a6b498eae7ff62b7276f61063f758 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Fri, 31 Jan 2025 08:43:29 -0400 Subject: [PATCH 035/151] fix: remove apostrophe --- Chapters/01-memory.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index c2d329a5..8d3678f7 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -151,7 +151,7 @@ It simply exists in your program. ### Stack vs Heap -If you are familiar with system's programming, or just low-level programming in general, you +If you are familiar with systems programming, or just low-level programming in general, you probably have heard of the "duel" between Stack vs Heap. These are two different types of memory, or different memory spaces, which are both available in Zig. From a62e7a1ee12cac32f046cddfa7c8cde126eeff62 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Fri, 31 Jan 2025 08:49:19 -0400 Subject: [PATCH 036/151] fix: change have to has --- Chapters/01-memory.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index 8d3678f7..fd8870d0 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -242,7 +242,7 @@ freed/destroyed at the end of the function scope. ::: -This same logic applies to any other special structure in Zig that have its own scope by surrounding +This same logic applies to any other special structure in Zig that has its own scope by surrounding it with curly braces (`{}`). For loops, while loops, if else statements, etc. For example, if you declare any local object in the scope of a for loop, this local object is accessible only within the scope From f152e22ee31d23abdfe05f0d6627101203548669 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Fri, 31 Jan 2025 08:53:14 -0400 Subject: [PATCH 037/151] fix: change very to well --- Chapters/01-memory.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index fd8870d0..91c90b57 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -314,7 +314,7 @@ pub fn main() !void { } ``` -This "invalid pointer to stack variable" problem is very known across many programming language communities. +This "invalid pointer to stack variable" problem is well known across many programming language communities. If you try to do the same thing, for example, in a C or C++ program (i.e. returning an address to a local object stored in the stack), you would also get undefined behaviour in the program. From 4301b0d69a98b2819dabd6efcb824e52dddd5bde Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Fri, 31 Jan 2025 08:56:52 -0400 Subject: [PATCH 038/151] fix: refine wording --- Chapters/01-memory.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index 91c90b57..597b0073 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -327,7 +327,7 @@ is destroyed at the end of its scope. ::: But what if you really need to use this local object in some way after your function returns? -How can you do this? The answer is: "in the same you would do if this was a C or C++ program. By returning +How can you do this? The answer is: "in the same way you would do if this were a C or C++ program. By returning an address to an object stored in the heap". The heap memory has a much more flexible lifecycle, and allows you to get a valid pointer to a local object of a function that already returned from its scope. From 49bafcdf09be8e6ebef6a3a2759717decda4e028 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Fri, 31 Jan 2025 09:00:01 -0400 Subject: [PATCH 039/151] fix: change sentence to reduce 'or' usage --- Chapters/01-memory.qmd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index 597b0073..aff78342 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -346,8 +346,8 @@ In summary, a server is a type of application that runs for long periods of time and that serves (or "deals with") any incoming request that reaches this particular server. The heap is a good choice for this type of system, mainly because the server does not know upfront -how many requests it will receive from users, while it is active. It could be one single request, -or, 5 thousand requests, or, it could also be zero requests. +how many requests it will receive from users, while it is active. It could be a single request, +5 thousand requests, or even zero requests. The server needs to have the ability to allocate and manage its memory according to how many requests it receives. Another key difference between the stack and the heap, is that the heap is a type From d50c9da4afe091a91d09e9c59c4fa3b0b35030b7 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Fri, 31 Jan 2025 09:05:19 -0400 Subject: [PATCH 040/151] fix: change 'he' to 'it' --- Chapters/01-memory.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index aff78342..9fa7a376 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -386,7 +386,7 @@ object you declare is stored: 1. every constant object (`const`) whose value **is known at compile-time** is also stored in the global data section. 1. every object (constant or not) whose length/size **is known at compile time** is stored in the stack space for the current scope. 1. if an object is created with the method `alloc()` or `create()` of an allocator object, this object is stored in the memory space used by this particular allocator object. Most of allocators available in Zig use the heap memory, so, this object is likely stored in the heap (`FixedBufferAllocator()` is an exception to that). -1. the heap can only be accessed through allocators. If your object was not created through the `alloc()` or `create()` methods of an allocator object, then, he is most certainly not an object stored in the heap. +1. the heap can only be accessed through allocators. If your object was not created through the `alloc()` or `create()` methods of an allocator object, then, it is most certainly not an object stored in the heap. ## Stack overflows {#sec-stack-overflow} From d474f213d92cd92299568d02746edc39e9e76c91 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Fri, 31 Jan 2025 09:07:57 -0400 Subject: [PATCH 041/151] fix grammar in overflow explanation --- Chapters/01-memory.qmd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index 9fa7a376..97c8ac9d 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -405,8 +405,8 @@ a *stack overflow* happens, and your program just crashes as a result of that. I you attempt to use more space than is available on the stack. This type of problem is very similar to a *buffer overflow*, i.e. you are trying to use more space -than is available in the "buffer object". However, a stack overflow always cause your program to crash, -while a buffer overflow not always cause your program to crash (although it often does). +than is available in the "buffer object". However, a stack overflow always causes your program to crash, +while a buffer overflow does not always cause your program to crash (although it often does). You can see an example of a stack overflow in the example below. We are trying to allocate a very big array of `u64` values on the stack. You can see below that this program does not run succesfully, because it crashed From b941732945a3118bfae7286b8c527ce4b990c397 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Fri, 31 Jan 2025 09:09:27 -0400 Subject: [PATCH 042/151] fix: correct spelling of 'successfully' in error message explanation --- Chapters/01-memory.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index 97c8ac9d..f7cc8ca8 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -409,7 +409,7 @@ than is available in the "buffer object". However, a stack overflow always cause while a buffer overflow does not always cause your program to crash (although it often does). You can see an example of a stack overflow in the example below. We are trying to allocate a very big array of `u64` values -on the stack. You can see below that this program does not run succesfully, because it crashed +on the stack. You can see below that this program does not run successfully, because it crashed with a "segmentation fault" error message. ```{zig} From 7c9ad9545ef250f8228ef002877341ecf23139bd Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Fri, 31 Jan 2025 09:16:04 -0400 Subject: [PATCH 043/151] fix: add 'a' before 'new string' --- Chapters/01-memory.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index f7cc8ca8..852a1bdb 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -450,7 +450,7 @@ sure that this function/operator will allocate some memory during its execution. An example is the `allocPrint()` function from the Zig Standard Library. With this function, you can write a new string using format specifiers. So, this function is, for example, very similar to the function `sprintf()` in C. -In order to write such new string, the `allocPrint()` function needs to allocate some memory to store the +In order to write such a new string, the `allocPrint()` function needs to allocate some memory to store the output string. That is why, the first argument of this function is an allocator object that you, the user/programmer, gives From 4da4cbaca835d0cdc8e4c062ba99d01002382960 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Fri, 31 Jan 2025 09:21:41 -0400 Subject: [PATCH 044/151] fix: change 'have' to 'has' --- Chapters/01-memory.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index 852a1bdb..e4368ef1 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -497,7 +497,7 @@ but you don't need to change the function calls to the methods that do the memor As we described at @sec-stack, everytime you make a function call in Zig, a space in the stack is reserved for this function call. But the stack -has a key limitation which is: every object stored in the stack have a +has a key limitation which is: every object stored in the stack has a known fixed length. But in reality, there are two very common instances where this "fixed length limitation" of the stack is a deal braker: From c576540d86543de691866e52d948488ef7708251 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Fri, 31 Jan 2025 09:26:19 -0400 Subject: [PATCH 045/151] fix: grammar in sentence about stack suitability --- Chapters/01-memory.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index e4368ef1..464b4c5b 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -511,7 +511,7 @@ stack. However, if this object is stored in the heap, then, you can return a poi end of the function. Because you (the programmer) control the lifetime of any heap memory that you allocate. You decide when this memory gets destroyed/freed. -These are common situations where the stack is not good for. +These are common situations for which the stack is not good. That is why you need a different memory management strategy to store these objects inside your function. You need to use a memory type that can grow together with your objects, or that you From bca98a7f6006249adb93b6cdc2e56997440b552d Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Fri, 31 Jan 2025 10:23:46 -0400 Subject: [PATCH 046/151] fix: change 'an' to 'a' --- Chapters/01-memory.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index 464b4c5b..1cd29bd9 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -760,7 +760,7 @@ should use `alloc()` and `free()`. But if you need to store just a single item, then, the `create()` and `destroy()` methods are ideal for you. In the example below, I'm defining a struct to represent an user of some sort. -It could be an user for a game, or a software to manage resources, it doesn't mater. +It could be a user for a game, or software to manage resources, it doesn't mater. Notice that I use the `create()` method this time, to store a single `User` object in the program. Also notice that I use the `destroy()` method to free the memory used by this object at the end of the scope. From 3656ee4f9225338775946041c4ac9c1c09c2dd96 Mon Sep 17 00:00:00 2001 From: loveholly Date: Sun, 2 Feb 2025 11:24:33 +0800 Subject: [PATCH 047/151] Grammar issue --- docs/Chapters/01-zig-weird.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Chapters/01-zig-weird.html b/docs/Chapters/01-zig-weird.html index f7360c5b..f46d6fd0 100644 --- a/docs/Chapters/01-zig-weird.html +++ b/docs/Chapters/01-zig-weird.html @@ -612,7 +612,7 @@

    // It compiles!
    
    From c5ca497a8a3ba7fb13ea88e0dc1d6de551adfca8 Mon Sep 17 00:00:00 2001
    From: Dima Budaragin 
    Date: Sun, 2 Feb 2025 18:48:48 +0000
    Subject: [PATCH 048/151] fix typos
    
    ---
     Chapters/01-zig-weird.qmd | 16 ++++++++--------
     1 file changed, 8 insertions(+), 8 deletions(-)
    
    diff --git a/Chapters/01-zig-weird.qmd b/Chapters/01-zig-weird.qmd
    index f0983bf4..5af2822f 100644
    --- a/Chapters/01-zig-weird.qmd
    +++ b/Chapters/01-zig-weird.qmd
    @@ -335,7 +335,7 @@ compilation error will be raised, warning about this mistake.
     
     The `zig` compiler also offers a `build-lib` and `build-obj` commands, which work
     the exact same way as the `build-exe` command. The only difference is that, they compile your
    -Zig modules into a portale C ABI library, or, into object files, respectively.
    +Zig modules into a portable C ABI library, or, into object files, respectively.
     
     In the case of the `build-exe` command, a binary executable file is created by the `zig`
     compiler in the root directory of your project.
    @@ -364,7 +364,7 @@ Hello, world!
     
     ### Compile and execute at the same time {#sec-compile-run-code}
     
    -On the previous section, I presented the `zig build-exe` command, which
    +In the previous section, I presented the `zig build-exe` command, which
     compiles Zig modules into an executable file. However, this means that,
     in order to execute the executable file, we have to run two different commands.
     First, the `zig build-exe` command, and then, we call the executable file
    @@ -386,7 +386,7 @@ Hello, world!
     ### Important note for Windows users
     
     First of all, this is a Windows-specific thing, and, therefore, does not apply to other
    -operating systems, such as Linux and macOs. In summary, if you have a piece of Zig code that
    +operating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that
     includes some global variables whose initialization rely on runtime resources, then,
     you might have some troubles while trying to compile this Zig code on Windows.
     
    @@ -458,7 +458,7 @@ GitHub issues opened at the official Zig repository. More specifically, the issu
     
     ### Compiling the entire project {#sec-compile-project}
     
    -Just as I described at @sec-project-files, as our project grows in size and
    +Just as I described in @sec-project-files, as our project grows in size and
     complexity, we usually prefer to organize the compilation and build process
     of the project into a build script, using some sort of "build system".
     
    @@ -493,7 +493,7 @@ After you execute this "build project" command, a `zig-out` directory
     is created in the root of your project directory, where you can find
     the binary executables and libraries created from your Zig modules
     accordingly to the build commands that you specified at `build.zig`.
    -We will talk more about the build system in Zig latter in this book.
    +We will talk more about the build system in Zig later in this book.
     
     In the example below, I'm executing the binary executable
     named `hello_world` that was generated by the compiler after the
    @@ -554,14 +554,14 @@ codebases, such as:
     [^bunjs]: .
     
     All these assets are available on GitHub,
    -and this is great, because we can use the GitHub search bar in our advantage,
    +and this is great, because we can use the GitHub search bar to our advantage,
     to find Zig code that fits our description.
     For example, you can always include `lang:Zig` in the GitHub search bar when you
     are searching for a particular pattern. This will limit the search to only Zig modules.
     
     [^zig-lib-std]: 
     
    -Also, a great alternative is to consult online resources and documentations.
    +Also, a great alternative is to consult online resources and documentation.
     Here is a quick list of resources that I personally use from time to time to learn
     more about the language each day:
     
    @@ -583,7 +583,7 @@ fix these programs, and make them work again.
     
     [^ziglings]: .
     
    -A famous tech YouTuber known as *The Primeagen* also posted some videos (at YouTube)
    +A famous tech YouTuber known as *The Primeagen* also posted some videos (on YouTube)
     where he solves these exercises from Ziglings. The first video is named
     ["Trying Zig Part 1"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].
     
    
    From 254d9b1169bf4b1f643c457fcb0f5a005f4b63c7 Mon Sep 17 00:00:00 2001
    From: Alexander Alekhin 
    Date: Wed, 5 Feb 2025 20:22:08 +0300
    Subject: [PATCH 049/151] fix errors in code samples
    
    ---
     Chapters/01-base64.qmd    |  9 ++++-----
     Chapters/01-memory.qmd    |  6 +++---
     Chapters/02-debugging.qmd | 12 ++++++------
     3 files changed, 13 insertions(+), 14 deletions(-)
    
    diff --git a/Chapters/01-base64.qmd b/Chapters/01-base64.qmd
    index d883696c..fabfc797 100644
    --- a/Chapters/01-base64.qmd
    +++ b/Chapters/01-base64.qmd
    @@ -115,7 +115,7 @@ const Base64 = struct {
             };
         }
     
    -    pub fn _char_at(self: Base64, index: u8) u8 {
    +    pub fn _char_at(self: Base64, index: usize) u8 {
             return self._table[index];
         }
     };
    @@ -175,7 +175,7 @@ to fill the space that it needs. That is why at @fig-base64-algo1, on the third
     2 extra zeros were added to fill the gap in this group.
     
     When we have a 6-bit group that is not completely full, like the third group, extra zeros
    -are added to fill the gap. But what about when an entire 6-bit group is empty, or, it 
    +are added to fill the gap. But what about when an entire 6-bit group is empty, or, it
     simply doesn't exist? This is the case of the fourth 6-bit group exposed at
     @fig-base64-algo1.
     
    @@ -682,10 +682,9 @@ fn _char_index(self: Base64, char: u8) u8 {
             return 64;
         var index: u8 = 0;
         for (0..63) |i| {
    -        if (self._char_at(i) == char) {
    -            index = i;
    +        if (self._char_at(i) == char)
                 break;
    -        }
    +        index += 1;
         }
     
         return index;
    diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd
    index 0c4de856..94ce0ecb 100644
    --- a/Chapters/01-memory.qmd
    +++ b/Chapters/01-memory.qmd
    @@ -177,7 +177,7 @@ a dynamic memory space, which can grow or shrink to fit the size of your objects
     
     ### Stack {#sec-stack}
     
    -The stack is a type of memory that uses the power of the *stack data structure*, hence the name. 
    +The stack is a type of memory that uses the power of the *stack data structure*, hence the name.
     A "stack" is a type of *data structure* that uses a "last in, first out" (LIFO) mechanism to store the values
     you give it to. I imagine you are familiar with this data structure.
     But, if you are not, the [Wikipedia page](https://en.wikipedia.org/wiki/Stack_(abstract_data_type))[^wiki-stack]
    @@ -263,7 +263,7 @@ for (0..a.len) |i| {
     // Trying to use an object that was
     // declared in the for loop scope,
     // and that does not exist anymore.
    -std.debug.print("{d}\n", index);
    +std.debug.print("{d}\n", .{index});
     ```
     
     
    @@ -520,7 +520,7 @@ The heap fits this description.
     
     Allocating memory on the heap is commonly known as dynamic memory management. As the objects you create grow in size
     during the execution of your program, you grow the amount of memory
    -you have by allocating more memory in the heap to store these objects. 
    +you have by allocating more memory in the heap to store these objects.
     And you do that in Zig, by using an allocator object.
     
     
    diff --git a/Chapters/02-debugging.qmd b/Chapters/02-debugging.qmd
    index 7f3e147a..6329bdea 100644
    --- a/Chapters/02-debugging.qmd
    +++ b/Chapters/02-debugging.qmd
    @@ -94,7 +94,7 @@ fn add(x: u8, y: u8) u8 {
     
     pub fn main() !void {
         const result = add(34, 16);
    -    _ = try stdout.print("Result: {d}", .{result});
    +    try stdout.print("Result: {d}", .{result});
     }
     ```
     
    @@ -128,7 +128,7 @@ then, creating a *writer* object to `stderr`, then, using the `print()` method o
     const std = @import("std");
     const stderr = std.io.getStdErr().writer();
     // some more lines ...
    -_ = try stderr.print("Result: {d}", .{result});
    +try stderr.print("Result: {d}", .{result});
     ```
     
     
    @@ -184,7 +184,7 @@ fn add_and_increment(a: u8, b: u8) u8 {
     pub fn main() !void {
         var n = add_and_increment(2, 3);
         n = add_and_increment(n, n);
    -    _ = try stdout.print("Result: {d}!\n", .{n});
    +    try stdout.print("Result: {d}!\n", .{n});
     }
     ```
     
    @@ -227,7 +227,7 @@ Process 8654 stopped
         stop reason = breakpoint 1.1 frame #0: 0x10341a6
         add_program`debug1.main at add_program.zig:11:30
        8   	}
    -   9   	
    +   9
        10  	pub fn main() !void {
     -> 11  	    var n = add_and_increment(2, 3);
        12  	    n = add_and_increment(n, n);
    @@ -268,7 +268,7 @@ Process 4798 stopped
     * thread #1, name = 'debugging',
         stop reason = step over frame #0: 0x10341ae
         debugging`debug1.main at debug1.zig:12:26
    -   9   	
    +   9
        10  	pub fn main() !void {
        11  	    var n = add_and_increment(2, 3);
     -> 12  	    n = add_and_increment(n, n);
    @@ -327,7 +327,7 @@ But you also have alternatives embedded in the language itself to access the dat
     types of your objects.
     
     In Zig, you can retrieve the data type of an object, by using the built-in function
    -`@TypeOf()`. Just apply this function over the object, and you get access to 
    +`@TypeOf()`. Just apply this function over the object, and you get access to
     the data type of the object.
     
     ```{zig}
    
    From 85ced25486d2d882b9f5ff8255db8319cbdef685 Mon Sep 17 00:00:00 2001
    From: jorge-j1m <68088000+jorge-j1m@users.noreply.github.com>
    Date: Fri, 7 Feb 2025 23:58:53 -0500
    Subject: [PATCH 050/151] Fix typo in Chapter 1
    
    ---
     Chapters/01-zig-weird.qmd | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/Chapters/01-zig-weird.qmd b/Chapters/01-zig-weird.qmd
    index f0983bf4..298c6f45 100644
    --- a/Chapters/01-zig-weird.qmd
    +++ b/Chapters/01-zig-weird.qmd
    @@ -335,7 +335,7 @@ compilation error will be raised, warning about this mistake.
     
     The `zig` compiler also offers a `build-lib` and `build-obj` commands, which work
     the exact same way as the `build-exe` command. The only difference is that, they compile your
    -Zig modules into a portale C ABI library, or, into object files, respectively.
    +Zig modules into a portable C ABI library, or, into object files, respectively.
     
     In the case of the `build-exe` command, a binary executable file is created by the `zig`
     compiler in the root directory of your project.
    
    From 37048ebd85bef14d534c5fa7dbb4efb410386c0b Mon Sep 17 00:00:00 2001
    From: hamza wahed 
    Date: Sat, 8 Feb 2025 21:43:03 -0400
    Subject: [PATCH 051/151] fix: change your to you
    
    ---
     Chapters/02-debugging.qmd | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/Chapters/02-debugging.qmd b/Chapters/02-debugging.qmd
    index 7f3e147a..b4946bfc 100644
    --- a/Chapters/02-debugging.qmd
    +++ b/Chapters/02-debugging.qmd
    @@ -51,7 +51,7 @@ the Zig Standard Library Official Reference for the type `File`](https://ziglang
     [^zig-fiile-reference]: .
     
     For our purpose here, which is to write something to the `stdout`, especially to debug our
    -program, I recommend you to use the `writer()` method, which gives your a *writer* object.
    +program, I recommend you to use the `writer()` method, which gives you a *writer* object.
     This *writer* object offers some helper methods to write stuff into the file descriptor object
     that represents the `stdout` stream. In special, the `print()` method.
     
    
    From f27eb4791c87113095573337a9e8e9928afb9405 Mon Sep 17 00:00:00 2001
    From: hamza wahed 
    Date: Sat, 8 Feb 2025 22:02:58 -0400
    Subject: [PATCH 052/151] fix: change print to prints
    
    ---
     Chapters/02-debugging.qmd | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/Chapters/02-debugging.qmd b/Chapters/02-debugging.qmd
    index b4946bfc..cf8614ee 100644
    --- a/Chapters/02-debugging.qmd
    +++ b/Chapters/02-debugging.qmd
    @@ -99,7 +99,7 @@ pub fn main() !void {
     ```
     
     Is important to emphasize that, the `stdout.print()` method, as you would expect,
    -print your template string into the `stdout` stream of your system.
    +prints your template string into the `stdout` stream of your system.
     However, you can also print your template string into the `stderr` stream
     if your prefer. All you need to do, is to replace the `stdout.print()`
     call with the function `std.debug.print()`. Like this:
    
    From c6bdd042915772118a08e4edd9de9a26016db156 Mon Sep 17 00:00:00 2001
    From: hamza wahed 
    Date: Sat, 8 Feb 2025 22:04:41 -0400
    Subject: [PATCH 053/151] fix: Add a subject to the sentence
    
    ---
     Chapters/02-debugging.qmd | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/Chapters/02-debugging.qmd b/Chapters/02-debugging.qmd
    index cf8614ee..e5940da3 100644
    --- a/Chapters/02-debugging.qmd
    +++ b/Chapters/02-debugging.qmd
    @@ -98,7 +98,7 @@ pub fn main() !void {
     }
     ```
     
    -Is important to emphasize that, the `stdout.print()` method, as you would expect,
    +It is important to emphasize that, the `stdout.print()` method, as you would expect,
     prints your template string into the `stdout` stream of your system.
     However, you can also print your template string into the `stderr` stream
     if your prefer. All you need to do, is to replace the `stdout.print()`
    
    From f81cb7130288c1b390efcfd3a2a6efebb2ca13f5 Mon Sep 17 00:00:00 2001
    From: hamza wahed 
    Date: Sat, 8 Feb 2025 22:13:30 -0400
    Subject: [PATCH 054/151] fix: change being to is
    
    ---
     Chapters/02-debugging.qmd | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/Chapters/02-debugging.qmd b/Chapters/02-debugging.qmd
    index e5940da3..811d5fe3 100644
    --- a/Chapters/02-debugging.qmd
    +++ b/Chapters/02-debugging.qmd
    @@ -135,7 +135,7 @@ _ = try stderr.print("Result: {d}", .{result});
     
     ## Debugging through debuggers
     
    -Although *print debugging* being a valid and very useful strategy,
    +Although *print debugging* is a valid and very useful strategy,
     most programmers prefer to use a debugger to debug their programs.
     Since Zig is a low-level language, you can use either GDB (GNU Debugger),
     or LLDB (LLVM Project Debugger) as your debugger.
    
    From 77b6549487fa89fba69671cecec2744aac999402 Mon Sep 17 00:00:00 2001
    From: hamza wahed 
    Date: Sat, 8 Feb 2025 22:26:29 -0400
    Subject: [PATCH 055/151] fix: grammar in sentence
    
    ---
     Chapters/02-debugging.qmd | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/Chapters/02-debugging.qmd b/Chapters/02-debugging.qmd
    index 811d5fe3..1fddaa70 100644
    --- a/Chapters/02-debugging.qmd
    +++ b/Chapters/02-debugging.qmd
    @@ -255,7 +255,7 @@ by using the `p` LLDB command. The syntax for this command is `p 
    Date: Sun, 9 Feb 2025 10:50:46 -0300
    Subject: [PATCH 056/151] Recompile book with changes
    
    ---
     _freeze/Chapters/01-zig-weird/execute-results/html.json | 8 +++-----
     docs/Chapters/01-zig-weird.html                         | 2 +-
     docs/search.json                                        | 2 +-
     3 files changed, 5 insertions(+), 7 deletions(-)
    
    diff --git a/_freeze/Chapters/01-zig-weird/execute-results/html.json b/_freeze/Chapters/01-zig-weird/execute-results/html.json
    index 28800571..49b461d6 100644
    --- a/_freeze/Chapters/01-zig-weird/execute-results/html.json
    +++ b/_freeze/Chapters/01-zig-weird/execute-results/html.json
    @@ -1,11 +1,9 @@
     {
    -  "hash": "507166385ff85ccf512b153b7c107291",
    +  "hash": "4ab2f8387f13b3772b2eb726e8e611b5",
       "result": {
         "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it is still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. They really make it sometimes hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscures the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that get's compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e. it is where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n    ├── main.zig\n    └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contain Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nTherefore, Zig contains a native build system in it, and\nwe can use this build system to write small scripts in Zig,\nwhich describes the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e. creating new objects)\nare made in Zig. You can create a new object in Zig by using the following syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). At @sec-assignments we talk more about objects in general.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n    return a + b;\n}\n```\n:::\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that at @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIs worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt is like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n    const stdout = std.io.getStdOut().writer();\n    try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portale C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig  build.zig.zon  main  src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nOn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOs. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e. the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. Thus, if you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith a \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, operations like accessing the `stdout` (or opening a file) on Windows\ndepends on resources that are available only at *runtime* (you will learn more about compile-time\nversus runtime at @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n    break :blk asm {\n               ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword at @sec-comptime.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    // SUCCESS: Stdout initialized at runtime.\n    const stdout = std.io.getStdOut().writer();\n    _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation at a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues \n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described at @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig latter in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig? \nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar in our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentations.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It is a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (at YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e. identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n    age = 25;\n      ~~^~~\n```\n\nIn contrast, if you use `var`, then, the object created is a variable object.\nWith `var` you can declare this object in your source code, and then,\nchange the value of this object how many times you want over future points\nin your source code.\n\nSo, using the same code example exposed above, if I change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it is an \"variable object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIs important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code use this object while it is uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object. \n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e. if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n    const age = 15;\n          ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to an special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It is discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n    of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also get's discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig have many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e. the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\nIs worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it have the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array. \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it is a slice that\naccess all elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhave 2 elements in it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" at @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth at @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially at @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned at @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e. the start and the end of this range)\nis known at compile-time, the slice object that get's created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nat @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that get's created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e. a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can \ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n    1, 2, 3, 4, 5,\n    6, 7, 8, 9, 10\n};\n// This slice have a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n```\n:::\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat get's created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, the `slice` object have a runtime known range, because the end index of the range\nis not known at compile time. In other words, the size of the array at `buffer` is not known\nat compile time. When we execute this program, the size of the array might be 10, or, it might be 12\ndepending on where we execute it. Therefore, we don't know at compile time if\nthe slice object have a range of size 10, or, a range of size 12.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    var n: usize = 0;\n    if (builtin.target.os.tag == .windows) {\n        n = 10;\n    } else {\n        n = 12;\n    }\n    const buffer = try allocator.alloc(u64, n);\n    const slice = buffer[0..];\n    _ = slice;\n}\n```\n:::\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code have its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e. a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n    y += 1;\n    break :add_one y;\n};\nif (x == 124 and y == 124) {\n    try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nIn summary, there are two types of string values that you care about in Zig, which are:\n\n- String literal values.\n- String objects.\n\nA string literal value is just a pointer to a null-terminated array of bytes (i.e. similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string into the data type of the value itself.\nTherefore, a string literal value have a data type in the format `*const [n:0]u8`. The `n` in the data type\nindicates the size of the string.\n\nOn the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes,\nor, in other words, a slice of `u8` values (slices were presented at @sec-arrays). Thus,\na string object have a data type of `[]u8` or `[]const u8`, depending if the string object is\nmarked as constant with `const`, or as variable with `var`.\n\nBecause a string object is essentially a slice, it means that a string object always contains two things:\na pointer to an array of bytes (i.e. `u8` values) that represents the string value; and also, a length value,\nwhich specifies the size of the slice, or, how many elements there is in the slice.\nIs worth to emphasize that the array of bytes in a string object is not null-terminated, like in a\nstring literal value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n\"A literal value\";\n// This is a string object:\nconst object: []const u8 = \"A string object\";\n```\n:::\n\n\n\n\nZig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n    try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"This is an example\";\n    try stdout.print(\"Bytes that represents the string object: \", .{});\n    for (string_object) |byte| {\n        try stdout.print(\"{X} \", .{byte});\n    }\n    try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n   73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n### Strings in C\n\nAt first glance, a string literal value in Zig looks very similar to how C treats strings as well.\nIn more details, string values in C are treated internally as an array of arbitrary bytes,\nand this array is also null-terminated.\n\nBut one key difference between a Zig string literal and a C string, is that Zig also stores the length of\nthe string inside the object itself. In the case of a string literal value, this length is stored in the\ndata type of the value (i.e. the `n` variable in `[n:0]u8`). While, in a string object, the length is stored\nin the `len` attribute of the slice that represents the string object. This small detail makes your code safer,\nbecause it is much easier for the Zig compiler to check if you are trying to access an element that is\n\"out of bounds\", i.e. if your trying to access memory that does not belong to you.\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n    char* array = \"An example of string in C\";\n    int index = 0;\n    while (1) {\n        if (array[index] == '\\0') {\n            break;\n        }\n        index++;\n    }\n    printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible. In a string object for example, you can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"This is an example of string literal in Zig\";\n    try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it is a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    const simple_array = [_]i32{1, 2, 3, 4};\n    const string_obj: []const u8 = \"A string object\";\n    std.debug.print(\n        \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n    );\n    std.debug.print(\n        \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n    );\n    std.debug.print(\n        \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n    );\n    std.debug.print(\n        \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n    );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nType 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons\n  st [4]i32Type 4: []const u8\n```\n\n\n:::\n:::\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIs important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"Ⱥ\";\n    _ = try stdout.write(\n        \"Bytes that represents the string object: \"\n    );\n    for (string_object) |char| {\n        try stdout.print(\"{X} \", .{char});\n    }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n    var iterator = utf8.iterator();\n    while (iterator.nextCodepointSlice()) |codepoint| {\n        try stdout.print(\n            \"got codepoint {}\\n\",\n            .{std.fmt.fmtSliceHexUpper(codepoint)},\n        );\n    }\n}\n\n```\n:::\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n    \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n    \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n    allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n    u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig at @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers at @sec-root-file and especially at @sec-assignments.\n- How strings work in Zig at @sec-zig-strings.\n- How to use arrays and slices at @sec-arrays.\n- How to import functionality from other Zig modules at @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* at @sec-structs-and-oop.\n- Basic control flow syntax at @sec-zig-control-flow.\n- Enums at @sec-enum;\n- Pointers and Optionals at @sec-pointer;\n- Error handling with `try` and `catch` at @sec-error-handling;\n- Unit tests at @sec-unittests;\n- Vectors at @sec-vectors-simd;\n- Build System at @sec-build-system;\n\n\n\n\n",
    -    "supporting": [
    -      "01-zig-weird_files"
    -    ],
    +    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it is still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. They really make it sometimes hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscures the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that get's compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e. it is where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n    ├── main.zig\n    └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contain Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nTherefore, Zig contains a native build system in it, and\nwe can use this build system to write small scripts in Zig,\nwhich describes the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e. creating new objects)\nare made in Zig. You can create a new object in Zig by using the following syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). At @sec-assignments we talk more about objects in general.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n    return a + b;\n}\n```\n:::\n\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that at @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIs worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt is like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n    const stdout = std.io.getStdOut().writer();\n    try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portable C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig  build.zig.zon  main  src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nOn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOs. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e. the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. Thus, if you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith a \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, operations like accessing the `stdout` (or opening a file) on Windows\ndepends on resources that are available only at *runtime* (you will learn more about compile-time\nversus runtime at @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n    break :blk asm {\n               ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword at @sec-comptime.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    // SUCCESS: Stdout initialized at runtime.\n    const stdout = std.io.getStdOut().writer();\n    _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation at a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues \n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described at @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig latter in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig? \nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar in our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentations.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It is a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (at YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e. identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n    age = 25;\n      ~~^~~\n```\n\nIn contrast, if you use `var`, then, the object created is a variable object.\nWith `var` you can declare this object in your source code, and then,\nchange the value of this object how many times you want over future points\nin your source code.\n\nSo, using the same code example exposed above, if I change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it is an \"variable object\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIs important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code use this object while it is uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object. \n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e. if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n    const age = 15;\n          ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to an special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It is discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n    of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also get's discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig have many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e. the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\n\nIs worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it have the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array. \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it is a slice that\naccess all elements in the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhave 2 elements in it.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" at @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth at @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially at @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned at @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e. the start and the end of this range)\nis known at compile-time, the slice object that get's created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nat @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that get's created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e. a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can \ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n    1, 2, 3, 4, 5,\n    6, 7, 8, 9, 10\n};\n// This slice have a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n```\n:::\n\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat get's created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, the `slice` object have a runtime known range, because the end index of the range\nis not known at compile time. In other words, the size of the array at `buffer` is not known\nat compile time. When we execute this program, the size of the array might be 10, or, it might be 12\ndepending on where we execute it. Therefore, we don't know at compile time if\nthe slice object have a range of size 10, or, a range of size 12.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    var n: usize = 0;\n    if (builtin.target.os.tag == .windows) {\n        n = 10;\n    } else {\n        n = 12;\n    }\n    const buffer = try allocator.alloc(u64, n);\n    const slice = buffer[0..];\n    _ = slice;\n}\n```\n:::\n\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code have its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e. a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n    y += 1;\n    break :add_one y;\n};\nif (x == 124 and y == 124) {\n    try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nIn summary, there are two types of string values that you care about in Zig, which are:\n\n- String literal values.\n- String objects.\n\nA string literal value is just a pointer to a null-terminated array of bytes (i.e. similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string into the data type of the value itself.\nTherefore, a string literal value have a data type in the format `*const [n:0]u8`. The `n` in the data type\nindicates the size of the string.\n\nOn the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes,\nor, in other words, a slice of `u8` values (slices were presented at @sec-arrays). Thus,\na string object have a data type of `[]u8` or `[]const u8`, depending if the string object is\nmarked as constant with `const`, or as variable with `var`.\n\nBecause a string object is essentially a slice, it means that a string object always contains two things:\na pointer to an array of bytes (i.e. `u8` values) that represents the string value; and also, a length value,\nwhich specifies the size of the slice, or, how many elements there is in the slice.\nIs worth to emphasize that the array of bytes in a string object is not null-terminated, like in a\nstring literal value.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n\"A literal value\";\n// This is a string object:\nconst object: []const u8 = \"A string object\";\n```\n:::\n\n\n\n\n\nZig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n    try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"This is an example\";\n    try stdout.print(\"Bytes that represents the string object: \", .{});\n    for (string_object) |byte| {\n        try stdout.print(\"{X} \", .{byte});\n    }\n    try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n   73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Strings in C\n\nAt first glance, a string literal value in Zig looks very similar to how C treats strings as well.\nIn more details, string values in C are treated internally as an array of arbitrary bytes,\nand this array is also null-terminated.\n\nBut one key difference between a Zig string literal and a C string, is that Zig also stores the length of\nthe string inside the object itself. In the case of a string literal value, this length is stored in the\ndata type of the value (i.e. the `n` variable in `[n:0]u8`). While, in a string object, the length is stored\nin the `len` attribute of the slice that represents the string object. This small detail makes your code safer,\nbecause it is much easier for the Zig compiler to check if you are trying to access an element that is\n\"out of bounds\", i.e. if your trying to access memory that does not belong to you.\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n    char* array = \"An example of string in C\";\n    int index = 0;\n    while (1) {\n        if (array[index] == '\\0') {\n            break;\n        }\n        index++;\n    }\n    printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible. In a string object for example, you can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"This is an example of string literal in Zig\";\n    try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it is a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    const simple_array = [_]i32{1, 2, 3, 4};\n    const string_obj: []const u8 = \"A string object\";\n    std.debug.print(\n        \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n    );\n    std.debug.print(\n        \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n    );\n    std.debug.print(\n        \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n    );\n    std.debug.print(\n        \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n    );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nType 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons\n  st [4]i32Type 4: []const u8\n```\n\n\n:::\n:::\n\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIs important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"Ⱥ\";\n    _ = try stdout.write(\n        \"Bytes that represents the string object: \"\n    );\n    for (string_object) |char| {\n        try stdout.print(\"{X} \", .{char});\n    }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n    var iterator = utf8.iterator();\n    while (iterator.nextCodepointSlice()) |codepoint| {\n        try stdout.print(\n            \"got codepoint {}\\n\",\n            .{std.fmt.fmtSliceHexUpper(codepoint)},\n        );\n    }\n}\n\n```\n:::\n\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n    \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n    \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n    allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n    u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig at @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers at @sec-root-file and especially at @sec-assignments.\n- How strings work in Zig at @sec-zig-strings.\n- How to use arrays and slices at @sec-arrays.\n- How to import functionality from other Zig modules at @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* at @sec-structs-and-oop.\n- Basic control flow syntax at @sec-zig-control-flow.\n- Enums at @sec-enum;\n- Pointers and Optionals at @sec-pointer;\n- Error handling with `try` and `catch` at @sec-error-handling;\n- Unit tests at @sec-unittests;\n- Vectors at @sec-vectors-simd;\n- Build System at @sec-build-system;\n\n\n\n\n",
    +    "supporting": [],
         "filters": [
           "rmarkdown/pagebreak.lua"
         ],
    diff --git a/docs/Chapters/01-zig-weird.html b/docs/Chapters/01-zig-weird.html
    index f7360c5b..ff08a55e 100644
    --- a/docs/Chapters/01-zig-weird.html
    +++ b/docs/Chapters/01-zig-weird.html
    @@ -459,7 +459,7 @@ 

    You can compile your Zig modules into a binary executable by running the build-exe command from the zig compiler. You simply list all the Zig modules that you want to build after the build-exe command, separated by spaces. In the example below, we are compiling the module main.zig.

    zig build-exe src/main.zig

    Since we are building an executable, the zig compiler will look for a main() function declared in any of the files that you list after the build-exe command. If the compiler does not find a main() function declared somewhere, a compilation error will be raised, warning about this mistake.

    -

    The zig compiler also offers a build-lib and build-obj commands, which work the exact same way as the build-exe command. The only difference is that, they compile your Zig modules into a portale C ABI library, or, into object files, respectively.

    +

    The zig compiler also offers a build-lib and build-obj commands, which work the exact same way as the build-exe command. The only difference is that, they compile your Zig modules into a portable C ABI library, or, into object files, respectively.

    In the case of the build-exe command, a binary executable file is created by the zig compiler in the root directory of your project. If we take a look now at the contents of our current directory, with a simple ls command, we can see the binary file called main that was created by the compiler.

    ls
    build.zig  build.zig.zon  main  src
    diff --git a/docs/search.json b/docs/search.json index 9d8728f7..e3d46f3e 100644 --- a/docs/search.json +++ b/docs/search.json @@ -124,7 +124,7 @@ "href": "Chapters/01-zig-weird.html#hello-world-in-zig", "title": "1  Introducing Zig", "section": "1.2 Hello world in Zig", - "text": "1.2 Hello world in Zig\nWe begin our journey in Zig by creating a small “Hello World” program. To start a new Zig project in your computer, you simply call the init command from the zig compiler. Just create a new directory in your computer, then, init a new Zig project inside this directory, like this:\nmkdir hello_world\ncd hello_world\nzig init\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n\n1.2.1 Understanding the project files\nAfter you run the init command from the zig compiler, some new files are created inside of your current directory. First, a “source” (src) directory is created, containing two files, main.zig and root.zig. Each .zig file is a separate Zig module, which is simply a text file that contains some Zig code.\nBy convention, the main.zig module is where your main function lives. Thus, if you are building an executable program in Zig, you need to declare a main() function, which represents the entrypoint of your program, i.e. it is where the execution of your program begins.\nHowever, if you are building a library (instead of an executable program), then, the normal procedure is to delete this main.zig file and start with the root.zig module. By convention, the root.zig module is the root source file of your library.\ntree .\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\nThe init command also creates two additional files in our working directory: build.zig and build.zig.zon. The first file (build.zig) represents a build script written in Zig. This script is executed when you call the build command from the zig compiler. In other words, this file contain Zig code that executes the necessary steps to build the entire project.\nLow-level languages normally use a compiler to build your source code into binary executables or binary libraries. Nevertheless, this process of compiling your source code and building binary executables or binary libraries from it, became a real challenge in the programming world, once the projects became bigger and bigger. As a result, programmers created “build systems”, which are a second set of tools designed to make this process of compiling and building complex projects, easier.\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja, which are used to build complex C and C++ projects. With these systems, you can write scripts, which are called “build scripts”. They simply are scripts that describes the necessary steps to compile/build your project.\nHowever, these are separate tools, that do not belong to C/C++ compilers, like gcc or clang. As a result, in C/C++ projects, you have not only to install and manage your C/C++ compilers, but you also have to install and manage these build systems separately.\nIn Zig, we don’t need to use a separate set of tools to build our projects, because a build system is embedded inside the language itself. Therefore, Zig contains a native build system in it, and we can use this build system to write small scripts in Zig, which describes the necessary steps to build/compile our Zig project1. So, everything you need to build a complex Zig project is the zig compiler, and nothing more.\nThe second generated file (build.zig.zon) is a JSON-like file, in which you can describe your project, and also, declare a set of dependencies of your project that you want to fetch from the internet. In other words, you can use this build.zig.zon file to include a list of external libraries in your project.\nOne possible way to include an external Zig library in your project, is to manually build and install the library in your system, and just link your source code with the library at the build step of your project.\nHowever, if this external Zig library is available on GitHub for example, and it has a valid build.zig.zon file in root folder of the project, which describes the project, you can easily include this library in your project by simply listing this external library in your build.zig.zon file.\nIn other words, this build.zig.zon file works similarly to the package.json file in Javascript projects, or the Pipfile file in Python projects, or the Cargo.toml file in Rust projects. You can read more about this specific file in a couple of articles on the internet23, and you can also see the expected schema for this build.zig.zon file in a documentation file inside the official repository of Zig4.\n\n\n1.2.2 The file root.zig\nLet’s take a look into the root.zig file. You might have noticed that every line of code with an expression ends with a semicolon (;). This follows the syntax of a C-family programming language5.\nAlso, notice the @import() call at the first line. We use this built-in function to import functionality from other Zig modules into our current module. This @import() function works similarly to the #include pre-processor in C or C++, or, to the import statement in Python or Javascript code. In this example, we are importing the std module, which gives you access to the Zig Standard Library.\nIn this root.zig file, we can also see how assignments (i.e. creating new objects) are made in Zig. You can create a new object in Zig by using the following syntax (const|var) name = value;. In the example below, we are creating two constant objects (std and testing). At Section 1.4 we talk more about objects in general.\n\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n\nFunctions in Zig are declared using the fn keyword. In this root.zig module, we are declaring a function called add(), which has two arguments named a and b. The function returns an integer of the type i32 as result.\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit the type of an object in your code, if this type can be inferred by the zig compiler (we talk more about that at Section 2.4). But there are other situations where you do need to be explicit. For example, you do have to explicitly specify the type of each function argument, and also, the return type of every function that you create in Zig.\nWe specify the type of an object or a function argument in Zig by using a colon character (:) followed by the type after the name of this object/function argument. With the expressions a: i32 and b: i32, we know that both a and b arguments have type i32, which is a signed 32 bit integer. In this part, the syntax in Zig is identical to the syntax in Rust, which also specifies types by using the colon character.\nLastly, we have the return type of the function at the end of the line, before we open the curly braces to start writing the function’s body. In the example above, this type is also a signed 32 bit integer (i32) value.\nNotice that we also have an export keyword before the function declaration. This keyword is similar to the extern keyword in C. It exposes the function to make it available in the library API. Therefore, if you are writing a library for other people to use, you have to expose the functions you write in the public API of this library by using this export keyword. If we removed the export keyword from the add() function declaration, then, this function would be no longer exposed in the library object built by the zig compiler.\n\n\n1.2.3 The main.zig file\nNow that we have learned a lot about Zig’s syntax from the root.zig file, let’s take a look at the main.zig file. A lot of the elements we saw in root.zig are also present in main.zig. But there are some other elements that we haven’t seen yet, so let’s dive in.\nFirst, look at the return type of the main() function in this file. We can see a small change. The return type of the function (void) is accompanied by an exclamation mark (!). This exclamation mark tells us that this main() function might return an error.\nIs worth noting that, a main() function in Zig is allowed to return nothing (void), or an unsigned 8-bit integer (u8) value6, or an error. In other words, you can write your main() function in Zig to return essentially nothing (void), or, if you prefer, you can also write a more C-like main() function, which returns an integer value that usually serves as a “status code” for the process.\nIn this example, the return type annotation of main() indicates that this function can either return nothing (void), or return an error. This exclamation mark in the return type annotation is an interesting and powerful feature of Zig. In summary, if you write a function and something inside the body of this function might return an error, then, you are forced to:\n\neither add the exclamation mark to the return type of the function and make it clear that this function might return an error.\nexplicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through a try catch pattern. Zig does have both try and catch keywords. But they work a little differently than what you’re probably used to in other languages.\nIf we look at the main() function below, you can see that we do have a try keyword on the 5th line. But we do not have a catch keyword in this code. In Zig, we use the try keyword to execute an expression that might return an error, which, in this example, is the stdout.print() expression.\nIn essence, the try keyword executes the expression stdout.print(). If this expression returns a valid value, then, the try keyword does absolutely nothing. It only passes the value forward. It is like if this try keyword was never there. However, if the expression does return an error, then, the try keyword will unwrap the error value, then, it returns this error from the function and also prints the current stack trace to stderr.\nThis might sound weird to you if you come from a high-level language. Because in high-level languages, such as Python, if an error occurs somewhere, this error is automatically returned and the execution of your program will automatically stop even if you don’t want to stop the execution. You are obligated to face the error.\n\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n\nAnother thing that you might have noticed in this code example, is that the main() function is marked with the pub keyword. It marks the main() function as a public function from this module. Every function in your Zig module is by default private to this Zig module and can only be called from within the module. Unless, you explicitly mark this function as a public function with the pub keyword.\nIf you think about it, this pub keyword in Zig does essentially the opposite of what the static keyword do in C/C++. By making a function “public” you allow other Zig modules to access and call this function. A calling Zig module imports another module by using the @import() built-in function, which makes all public functions from the imported module visible to the calling Zig module.\n\n\n1.2.4 Compiling your source code\nYou can compile your Zig modules into a binary executable by running the build-exe command from the zig compiler. You simply list all the Zig modules that you want to build after the build-exe command, separated by spaces. In the example below, we are compiling the module main.zig.\nzig build-exe src/main.zig\nSince we are building an executable, the zig compiler will look for a main() function declared in any of the files that you list after the build-exe command. If the compiler does not find a main() function declared somewhere, a compilation error will be raised, warning about this mistake.\nThe zig compiler also offers a build-lib and build-obj commands, which work the exact same way as the build-exe command. The only difference is that, they compile your Zig modules into a portale C ABI library, or, into object files, respectively.\nIn the case of the build-exe command, a binary executable file is created by the zig compiler in the root directory of your project. If we take a look now at the contents of our current directory, with a simple ls command, we can see the binary file called main that was created by the compiler.\nls\nbuild.zig build.zig.zon main src\nIf I execute this binary executable, I get the “Hello World” message in the terminal , as we expected.\n./main\nHello, world!\n\n\n1.2.5 Compile and execute at the same time\nOn the previous section, I presented the zig build-exe command, which compiles Zig modules into an executable file. However, this means that, in order to execute the executable file, we have to run two different commands. First, the zig build-exe command, and then, we call the executable file created by the compiler.\nBut what if we wanted to perform these two steps, all at once, in a single command? We can do that by using the zig run command.\nzig run src/main.zig\nHello, world!\n\n\n1.2.6 Important note for Windows users\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other operating systems, such as Linux and macOs. In summary, if you have a piece of Zig code that includes some global variables whose initialization rely on runtime resources, then, you might have some troubles while trying to compile this Zig code on Windows.\nAn example of that is accessing the stdout (i.e. the standard output of your system), which is usually done in Zig by using the expression std.io.getStdOut(). Thus, if you use this expression to instantiate a global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows, with a “unable to evaluate comptime expression” error message.\nThis failure in the compilation process happens because all global variables in Zig are initialized at compile-time. However, operations like accessing the stdout (or opening a file) on Windows depends on resources that are available only at runtime (you will learn more about compile-time versus runtime at Section 3.1.1).\nFor example, if you try to compile this code example on Windows, you will likely get the error message exposed below:\n\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\nTo avoid this problem on Windows, we need to force the zig compiler to instantiate this stdout object only at runtime, instead of instantiating it at compile-time. We can achieve that by simply moving the expression to a function body.\nThis solves the problem because all expressions that are inside a function body in Zig are evaluated only at runtime, unless you use the comptime keyword explicitly to change this behaviour. You will learn more about this comptime keyword at Section 12.1.\n\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n\nHello\nYou can read more details about this Windows-specific limitation at a couple of GitHub issues opened at the official Zig repository. More specifically, the issues 17186 7 and 19864 8.\n\n\n1.2.7 Compiling the entire project\nJust as I described at Section 1.2.1, as our project grows in size and complexity, we usually prefer to organize the compilation and build process of the project into a build script, using some sort of “build system”.\nIn other words, as our project grows in size and complexity, the build-exe, build-lib and build-obj commands become harder to use directly. Because then, we start to list multiple and multiple modules at the same time. We also start to add built-in compilation flags to customize the build process for our needs, etc. It becomes a lot of work to write the necessary commands by hand.\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, Makefile or configure scripts to organize this process. However, in Zig, we have a native build system in the language itself. So, we can write build scripts in Zig to compile and build Zig projects. Then, all we need to do, is to call the zig build command to build our project.\nSo, when you execute the zig build command, the zig compiler will search for a Zig module named build.zig inside your current directory, which should be your build script, containing the necessary code to compile and build your project. If the compiler does find this build.zig file in your directory, then, the compiler will essentially execute a zig run command over this build.zig file, to compile and execute this build script, which in turn, will compile and build your entire project.\nzig build\nAfter you execute this “build project” command, a zig-out directory is created in the root of your project directory, where you can find the binary executables and libraries created from your Zig modules accordingly to the build commands that you specified at build.zig. We will talk more about the build system in Zig latter in this book.\nIn the example below, I’m executing the binary executable named hello_world that was generated by the compiler after the zig build command.\n./zig-out/bin/hello_world\nHello, world!", + "text": "1.2 Hello world in Zig\nWe begin our journey in Zig by creating a small “Hello World” program. To start a new Zig project in your computer, you simply call the init command from the zig compiler. Just create a new directory in your computer, then, init a new Zig project inside this directory, like this:\nmkdir hello_world\ncd hello_world\nzig init\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n\n1.2.1 Understanding the project files\nAfter you run the init command from the zig compiler, some new files are created inside of your current directory. First, a “source” (src) directory is created, containing two files, main.zig and root.zig. Each .zig file is a separate Zig module, which is simply a text file that contains some Zig code.\nBy convention, the main.zig module is where your main function lives. Thus, if you are building an executable program in Zig, you need to declare a main() function, which represents the entrypoint of your program, i.e. it is where the execution of your program begins.\nHowever, if you are building a library (instead of an executable program), then, the normal procedure is to delete this main.zig file and start with the root.zig module. By convention, the root.zig module is the root source file of your library.\ntree .\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\nThe init command also creates two additional files in our working directory: build.zig and build.zig.zon. The first file (build.zig) represents a build script written in Zig. This script is executed when you call the build command from the zig compiler. In other words, this file contain Zig code that executes the necessary steps to build the entire project.\nLow-level languages normally use a compiler to build your source code into binary executables or binary libraries. Nevertheless, this process of compiling your source code and building binary executables or binary libraries from it, became a real challenge in the programming world, once the projects became bigger and bigger. As a result, programmers created “build systems”, which are a second set of tools designed to make this process of compiling and building complex projects, easier.\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja, which are used to build complex C and C++ projects. With these systems, you can write scripts, which are called “build scripts”. They simply are scripts that describes the necessary steps to compile/build your project.\nHowever, these are separate tools, that do not belong to C/C++ compilers, like gcc or clang. As a result, in C/C++ projects, you have not only to install and manage your C/C++ compilers, but you also have to install and manage these build systems separately.\nIn Zig, we don’t need to use a separate set of tools to build our projects, because a build system is embedded inside the language itself. Therefore, Zig contains a native build system in it, and we can use this build system to write small scripts in Zig, which describes the necessary steps to build/compile our Zig project1. So, everything you need to build a complex Zig project is the zig compiler, and nothing more.\nThe second generated file (build.zig.zon) is a JSON-like file, in which you can describe your project, and also, declare a set of dependencies of your project that you want to fetch from the internet. In other words, you can use this build.zig.zon file to include a list of external libraries in your project.\nOne possible way to include an external Zig library in your project, is to manually build and install the library in your system, and just link your source code with the library at the build step of your project.\nHowever, if this external Zig library is available on GitHub for example, and it has a valid build.zig.zon file in root folder of the project, which describes the project, you can easily include this library in your project by simply listing this external library in your build.zig.zon file.\nIn other words, this build.zig.zon file works similarly to the package.json file in Javascript projects, or the Pipfile file in Python projects, or the Cargo.toml file in Rust projects. You can read more about this specific file in a couple of articles on the internet23, and you can also see the expected schema for this build.zig.zon file in a documentation file inside the official repository of Zig4.\n\n\n1.2.2 The file root.zig\nLet’s take a look into the root.zig file. You might have noticed that every line of code with an expression ends with a semicolon (;). This follows the syntax of a C-family programming language5.\nAlso, notice the @import() call at the first line. We use this built-in function to import functionality from other Zig modules into our current module. This @import() function works similarly to the #include pre-processor in C or C++, or, to the import statement in Python or Javascript code. In this example, we are importing the std module, which gives you access to the Zig Standard Library.\nIn this root.zig file, we can also see how assignments (i.e. creating new objects) are made in Zig. You can create a new object in Zig by using the following syntax (const|var) name = value;. In the example below, we are creating two constant objects (std and testing). At Section 1.4 we talk more about objects in general.\n\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n\nFunctions in Zig are declared using the fn keyword. In this root.zig module, we are declaring a function called add(), which has two arguments named a and b. The function returns an integer of the type i32 as result.\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit the type of an object in your code, if this type can be inferred by the zig compiler (we talk more about that at Section 2.4). But there are other situations where you do need to be explicit. For example, you do have to explicitly specify the type of each function argument, and also, the return type of every function that you create in Zig.\nWe specify the type of an object or a function argument in Zig by using a colon character (:) followed by the type after the name of this object/function argument. With the expressions a: i32 and b: i32, we know that both a and b arguments have type i32, which is a signed 32 bit integer. In this part, the syntax in Zig is identical to the syntax in Rust, which also specifies types by using the colon character.\nLastly, we have the return type of the function at the end of the line, before we open the curly braces to start writing the function’s body. In the example above, this type is also a signed 32 bit integer (i32) value.\nNotice that we also have an export keyword before the function declaration. This keyword is similar to the extern keyword in C. It exposes the function to make it available in the library API. Therefore, if you are writing a library for other people to use, you have to expose the functions you write in the public API of this library by using this export keyword. If we removed the export keyword from the add() function declaration, then, this function would be no longer exposed in the library object built by the zig compiler.\n\n\n1.2.3 The main.zig file\nNow that we have learned a lot about Zig’s syntax from the root.zig file, let’s take a look at the main.zig file. A lot of the elements we saw in root.zig are also present in main.zig. But there are some other elements that we haven’t seen yet, so let’s dive in.\nFirst, look at the return type of the main() function in this file. We can see a small change. The return type of the function (void) is accompanied by an exclamation mark (!). This exclamation mark tells us that this main() function might return an error.\nIs worth noting that, a main() function in Zig is allowed to return nothing (void), or an unsigned 8-bit integer (u8) value6, or an error. In other words, you can write your main() function in Zig to return essentially nothing (void), or, if you prefer, you can also write a more C-like main() function, which returns an integer value that usually serves as a “status code” for the process.\nIn this example, the return type annotation of main() indicates that this function can either return nothing (void), or return an error. This exclamation mark in the return type annotation is an interesting and powerful feature of Zig. In summary, if you write a function and something inside the body of this function might return an error, then, you are forced to:\n\neither add the exclamation mark to the return type of the function and make it clear that this function might return an error.\nexplicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through a try catch pattern. Zig does have both try and catch keywords. But they work a little differently than what you’re probably used to in other languages.\nIf we look at the main() function below, you can see that we do have a try keyword on the 5th line. But we do not have a catch keyword in this code. In Zig, we use the try keyword to execute an expression that might return an error, which, in this example, is the stdout.print() expression.\nIn essence, the try keyword executes the expression stdout.print(). If this expression returns a valid value, then, the try keyword does absolutely nothing. It only passes the value forward. It is like if this try keyword was never there. However, if the expression does return an error, then, the try keyword will unwrap the error value, then, it returns this error from the function and also prints the current stack trace to stderr.\nThis might sound weird to you if you come from a high-level language. Because in high-level languages, such as Python, if an error occurs somewhere, this error is automatically returned and the execution of your program will automatically stop even if you don’t want to stop the execution. You are obligated to face the error.\n\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n\nAnother thing that you might have noticed in this code example, is that the main() function is marked with the pub keyword. It marks the main() function as a public function from this module. Every function in your Zig module is by default private to this Zig module and can only be called from within the module. Unless, you explicitly mark this function as a public function with the pub keyword.\nIf you think about it, this pub keyword in Zig does essentially the opposite of what the static keyword do in C/C++. By making a function “public” you allow other Zig modules to access and call this function. A calling Zig module imports another module by using the @import() built-in function, which makes all public functions from the imported module visible to the calling Zig module.\n\n\n1.2.4 Compiling your source code\nYou can compile your Zig modules into a binary executable by running the build-exe command from the zig compiler. You simply list all the Zig modules that you want to build after the build-exe command, separated by spaces. In the example below, we are compiling the module main.zig.\nzig build-exe src/main.zig\nSince we are building an executable, the zig compiler will look for a main() function declared in any of the files that you list after the build-exe command. If the compiler does not find a main() function declared somewhere, a compilation error will be raised, warning about this mistake.\nThe zig compiler also offers a build-lib and build-obj commands, which work the exact same way as the build-exe command. The only difference is that, they compile your Zig modules into a portable C ABI library, or, into object files, respectively.\nIn the case of the build-exe command, a binary executable file is created by the zig compiler in the root directory of your project. If we take a look now at the contents of our current directory, with a simple ls command, we can see the binary file called main that was created by the compiler.\nls\nbuild.zig build.zig.zon main src\nIf I execute this binary executable, I get the “Hello World” message in the terminal , as we expected.\n./main\nHello, world!\n\n\n1.2.5 Compile and execute at the same time\nOn the previous section, I presented the zig build-exe command, which compiles Zig modules into an executable file. However, this means that, in order to execute the executable file, we have to run two different commands. First, the zig build-exe command, and then, we call the executable file created by the compiler.\nBut what if we wanted to perform these two steps, all at once, in a single command? We can do that by using the zig run command.\nzig run src/main.zig\nHello, world!\n\n\n1.2.6 Important note for Windows users\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other operating systems, such as Linux and macOs. In summary, if you have a piece of Zig code that includes some global variables whose initialization rely on runtime resources, then, you might have some troubles while trying to compile this Zig code on Windows.\nAn example of that is accessing the stdout (i.e. the standard output of your system), which is usually done in Zig by using the expression std.io.getStdOut(). Thus, if you use this expression to instantiate a global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows, with a “unable to evaluate comptime expression” error message.\nThis failure in the compilation process happens because all global variables in Zig are initialized at compile-time. However, operations like accessing the stdout (or opening a file) on Windows depends on resources that are available only at runtime (you will learn more about compile-time versus runtime at Section 3.1.1).\nFor example, if you try to compile this code example on Windows, you will likely get the error message exposed below:\n\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\nTo avoid this problem on Windows, we need to force the zig compiler to instantiate this stdout object only at runtime, instead of instantiating it at compile-time. We can achieve that by simply moving the expression to a function body.\nThis solves the problem because all expressions that are inside a function body in Zig are evaluated only at runtime, unless you use the comptime keyword explicitly to change this behaviour. You will learn more about this comptime keyword at Section 12.1.\n\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n\nHello\nYou can read more details about this Windows-specific limitation at a couple of GitHub issues opened at the official Zig repository. More specifically, the issues 17186 7 and 19864 8.\n\n\n1.2.7 Compiling the entire project\nJust as I described at Section 1.2.1, as our project grows in size and complexity, we usually prefer to organize the compilation and build process of the project into a build script, using some sort of “build system”.\nIn other words, as our project grows in size and complexity, the build-exe, build-lib and build-obj commands become harder to use directly. Because then, we start to list multiple and multiple modules at the same time. We also start to add built-in compilation flags to customize the build process for our needs, etc. It becomes a lot of work to write the necessary commands by hand.\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, Makefile or configure scripts to organize this process. However, in Zig, we have a native build system in the language itself. So, we can write build scripts in Zig to compile and build Zig projects. Then, all we need to do, is to call the zig build command to build our project.\nSo, when you execute the zig build command, the zig compiler will search for a Zig module named build.zig inside your current directory, which should be your build script, containing the necessary code to compile and build your project. If the compiler does find this build.zig file in your directory, then, the compiler will essentially execute a zig run command over this build.zig file, to compile and execute this build script, which in turn, will compile and build your entire project.\nzig build\nAfter you execute this “build project” command, a zig-out directory is created in the root of your project directory, where you can find the binary executables and libraries created from your Zig modules accordingly to the build commands that you specified at build.zig. We will talk more about the build system in Zig latter in this book.\nIn the example below, I’m executing the binary executable named hello_world that was generated by the compiler after the zig build command.\n./zig-out/bin/hello_world\nHello, world!", "crumbs": [ "1  Introducing Zig" ] From 9ad203426c28a152275997bcba50fa72b3250231 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 9 Feb 2025 10:51:50 -0300 Subject: [PATCH 057/151] Add change to QMD file --- Chapters/01-zig-weird.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapters/01-zig-weird.qmd b/Chapters/01-zig-weird.qmd index f0983bf4..12b677e5 100644 --- a/Chapters/01-zig-weird.qmd +++ b/Chapters/01-zig-weird.qmd @@ -731,7 +731,7 @@ Everytime you declare a new object in Zig, you have two choices: 1. or you explicitly discard the value of the object; To explicitly discard the value of any object (constant or variable), all you need to do is to assign -this object to an special character in Zig, which is the underscore (`_`). +this object to a special character in Zig, which is the underscore (`_`). When you assign an object to a underscore, like in the example below, the `zig` compiler will automatically discard the value of this particular object. From ba6c7bf1bcb6c7a0357fe79d3adc521567d8c30d Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 9 Feb 2025 10:53:11 -0300 Subject: [PATCH 058/151] Recompile book with changes --- _freeze/Chapters/01-zig-weird/execute-results/html.json | 8 +++----- docs/search.json | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/_freeze/Chapters/01-zig-weird/execute-results/html.json b/_freeze/Chapters/01-zig-weird/execute-results/html.json index 28800571..3f48d096 100644 --- a/_freeze/Chapters/01-zig-weird/execute-results/html.json +++ b/_freeze/Chapters/01-zig-weird/execute-results/html.json @@ -1,11 +1,9 @@ { - "hash": "507166385ff85ccf512b153b7c107291", + "hash": "5041be02baff66bca29c690e3dfbfd7c", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it is still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. They really make it sometimes hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscures the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that get's compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e. it is where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contain Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nTherefore, Zig contains a native build system in it, and\nwe can use this build system to write small scripts in Zig,\nwhich describes the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e. creating new objects)\nare made in Zig. You can create a new object in Zig by using the following syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). At @sec-assignments we talk more about objects in general.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n```\n:::\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that at @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIs worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt is like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portale C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig build.zig.zon main src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nOn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOs. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e. the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. Thus, if you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith a \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, operations like accessing the `stdout` (or opening a file) on Windows\ndepends on resources that are available only at *runtime* (you will learn more about compile-time\nversus runtime at @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword at @sec-comptime.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation at a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues \n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described at @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig latter in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig? \nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar in our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentations.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It is a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (at YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e. identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n age = 25;\n ~~^~~\n```\n\nIn contrast, if you use `var`, then, the object created is a variable object.\nWith `var` you can declare this object in your source code, and then,\nchange the value of this object how many times you want over future points\nin your source code.\n\nSo, using the same code example exposed above, if I change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it is an \"variable object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIs important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code use this object while it is uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object. \n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e. if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n const age = 15;\n ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to an special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It is discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also get's discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig have many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e. the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\nIs worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it have the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array. \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it is a slice that\naccess all elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhave 2 elements in it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" at @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth at @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially at @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned at @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e. the start and the end of this range)\nis known at compile-time, the slice object that get's created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nat @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that get's created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e. a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can \ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n 1, 2, 3, 4, 5,\n 6, 7, 8, 9, 10\n};\n// This slice have a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n```\n:::\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat get's created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, the `slice` object have a runtime known range, because the end index of the range\nis not known at compile time. In other words, the size of the array at `buffer` is not known\nat compile time. When we execute this program, the size of the array might be 10, or, it might be 12\ndepending on where we execute it. Therefore, we don't know at compile time if\nthe slice object have a range of size 10, or, a range of size 12.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var n: usize = 0;\n if (builtin.target.os.tag == .windows) {\n n = 10;\n } else {\n n = 12;\n }\n const buffer = try allocator.alloc(u64, n);\n const slice = buffer[0..];\n _ = slice;\n}\n```\n:::\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code have its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e. a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n y += 1;\n break :add_one y;\n};\nif (x == 124 and y == 124) {\n try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nIn summary, there are two types of string values that you care about in Zig, which are:\n\n- String literal values.\n- String objects.\n\nA string literal value is just a pointer to a null-terminated array of bytes (i.e. similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string into the data type of the value itself.\nTherefore, a string literal value have a data type in the format `*const [n:0]u8`. The `n` in the data type\nindicates the size of the string.\n\nOn the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes,\nor, in other words, a slice of `u8` values (slices were presented at @sec-arrays). Thus,\na string object have a data type of `[]u8` or `[]const u8`, depending if the string object is\nmarked as constant with `const`, or as variable with `var`.\n\nBecause a string object is essentially a slice, it means that a string object always contains two things:\na pointer to an array of bytes (i.e. `u8` values) that represents the string value; and also, a length value,\nwhich specifies the size of the slice, or, how many elements there is in the slice.\nIs worth to emphasize that the array of bytes in a string object is not null-terminated, like in a\nstring literal value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n\"A literal value\";\n// This is a string object:\nconst object: []const u8 = \"A string object\";\n```\n:::\n\n\n\n\nZig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example\";\n try stdout.print(\"Bytes that represents the string object: \", .{});\n for (string_object) |byte| {\n try stdout.print(\"{X} \", .{byte});\n }\n try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n 73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n### Strings in C\n\nAt first glance, a string literal value in Zig looks very similar to how C treats strings as well.\nIn more details, string values in C are treated internally as an array of arbitrary bytes,\nand this array is also null-terminated.\n\nBut one key difference between a Zig string literal and a C string, is that Zig also stores the length of\nthe string inside the object itself. In the case of a string literal value, this length is stored in the\ndata type of the value (i.e. the `n` variable in `[n:0]u8`). While, in a string object, the length is stored\nin the `len` attribute of the slice that represents the string object. This small detail makes your code safer,\nbecause it is much easier for the Zig compiler to check if you are trying to access an element that is\n\"out of bounds\", i.e. if your trying to access memory that does not belong to you.\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n char* array = \"An example of string in C\";\n int index = 0;\n while (1) {\n if (array[index] == '\\0') {\n break;\n }\n index++;\n }\n printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible. In a string object for example, you can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example of string literal in Zig\";\n try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it is a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const simple_array = [_]i32{1, 2, 3, 4};\n const string_obj: []const u8 = \"A string object\";\n std.debug.print(\n \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n );\n std.debug.print(\n \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n );\n std.debug.print(\n \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n );\n std.debug.print(\n \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nType 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons\n st [4]i32Type 4: []const u8\n```\n\n\n:::\n:::\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIs important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"Ⱥ\";\n _ = try stdout.write(\n \"Bytes that represents the string object: \"\n );\n for (string_object) |char| {\n try stdout.print(\"{X} \", .{char});\n }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n var iterator = utf8.iterator();\n while (iterator.nextCodepointSlice()) |codepoint| {\n try stdout.print(\n \"got codepoint {}\\n\",\n .{std.fmt.fmtSliceHexUpper(codepoint)},\n );\n }\n}\n\n```\n:::\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig at @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers at @sec-root-file and especially at @sec-assignments.\n- How strings work in Zig at @sec-zig-strings.\n- How to use arrays and slices at @sec-arrays.\n- How to import functionality from other Zig modules at @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* at @sec-structs-and-oop.\n- Basic control flow syntax at @sec-zig-control-flow.\n- Enums at @sec-enum;\n- Pointers and Optionals at @sec-pointer;\n- Error handling with `try` and `catch` at @sec-error-handling;\n- Unit tests at @sec-unittests;\n- Vectors at @sec-vectors-simd;\n- Build System at @sec-build-system;\n\n\n\n\n", - "supporting": [ - "01-zig-weird_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it is still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. They really make it sometimes hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscures the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that get's compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e. it is where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contain Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nTherefore, Zig contains a native build system in it, and\nwe can use this build system to write small scripts in Zig,\nwhich describes the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e. creating new objects)\nare made in Zig. You can create a new object in Zig by using the following syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). At @sec-assignments we talk more about objects in general.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n```\n:::\n\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that at @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIs worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt is like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portale C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig build.zig.zon main src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nOn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOs. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e. the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. Thus, if you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith a \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, operations like accessing the `stdout` (or opening a file) on Windows\ndepends on resources that are available only at *runtime* (you will learn more about compile-time\nversus runtime at @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword at @sec-comptime.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation at a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues \n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described at @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig latter in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig? \nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar in our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentations.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It is a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (at YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e. identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n age = 25;\n ~~^~~\n```\n\nIn contrast, if you use `var`, then, the object created is a variable object.\nWith `var` you can declare this object in your source code, and then,\nchange the value of this object how many times you want over future points\nin your source code.\n\nSo, using the same code example exposed above, if I change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it is an \"variable object\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIs important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code use this object while it is uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object. \n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e. if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n const age = 15;\n ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to a special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It is discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also get's discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig have many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e. the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\n\nIs worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it have the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array. \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it is a slice that\naccess all elements in the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhave 2 elements in it.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" at @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth at @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially at @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned at @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e. the start and the end of this range)\nis known at compile-time, the slice object that get's created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nat @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that get's created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e. a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can \ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n 1, 2, 3, 4, 5,\n 6, 7, 8, 9, 10\n};\n// This slice have a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n```\n:::\n\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat get's created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, the `slice` object have a runtime known range, because the end index of the range\nis not known at compile time. In other words, the size of the array at `buffer` is not known\nat compile time. When we execute this program, the size of the array might be 10, or, it might be 12\ndepending on where we execute it. Therefore, we don't know at compile time if\nthe slice object have a range of size 10, or, a range of size 12.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var n: usize = 0;\n if (builtin.target.os.tag == .windows) {\n n = 10;\n } else {\n n = 12;\n }\n const buffer = try allocator.alloc(u64, n);\n const slice = buffer[0..];\n _ = slice;\n}\n```\n:::\n\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code have its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e. a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n y += 1;\n break :add_one y;\n};\nif (x == 124 and y == 124) {\n try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nIn summary, there are two types of string values that you care about in Zig, which are:\n\n- String literal values.\n- String objects.\n\nA string literal value is just a pointer to a null-terminated array of bytes (i.e. similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string into the data type of the value itself.\nTherefore, a string literal value have a data type in the format `*const [n:0]u8`. The `n` in the data type\nindicates the size of the string.\n\nOn the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes,\nor, in other words, a slice of `u8` values (slices were presented at @sec-arrays). Thus,\na string object have a data type of `[]u8` or `[]const u8`, depending if the string object is\nmarked as constant with `const`, or as variable with `var`.\n\nBecause a string object is essentially a slice, it means that a string object always contains two things:\na pointer to an array of bytes (i.e. `u8` values) that represents the string value; and also, a length value,\nwhich specifies the size of the slice, or, how many elements there is in the slice.\nIs worth to emphasize that the array of bytes in a string object is not null-terminated, like in a\nstring literal value.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n\"A literal value\";\n// This is a string object:\nconst object: []const u8 = \"A string object\";\n```\n:::\n\n\n\n\n\nZig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example\";\n try stdout.print(\"Bytes that represents the string object: \", .{});\n for (string_object) |byte| {\n try stdout.print(\"{X} \", .{byte});\n }\n try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n 73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Strings in C\n\nAt first glance, a string literal value in Zig looks very similar to how C treats strings as well.\nIn more details, string values in C are treated internally as an array of arbitrary bytes,\nand this array is also null-terminated.\n\nBut one key difference between a Zig string literal and a C string, is that Zig also stores the length of\nthe string inside the object itself. In the case of a string literal value, this length is stored in the\ndata type of the value (i.e. the `n` variable in `[n:0]u8`). While, in a string object, the length is stored\nin the `len` attribute of the slice that represents the string object. This small detail makes your code safer,\nbecause it is much easier for the Zig compiler to check if you are trying to access an element that is\n\"out of bounds\", i.e. if your trying to access memory that does not belong to you.\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n char* array = \"An example of string in C\";\n int index = 0;\n while (1) {\n if (array[index] == '\\0') {\n break;\n }\n index++;\n }\n printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible. In a string object for example, you can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example of string literal in Zig\";\n try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it is a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const simple_array = [_]i32{1, 2, 3, 4};\n const string_obj: []const u8 = \"A string object\";\n std.debug.print(\n \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n );\n std.debug.print(\n \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n );\n std.debug.print(\n \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n );\n std.debug.print(\n \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nType 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons\n st [4]i32Type 4: []const u8\n```\n\n\n:::\n:::\n\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIs important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"Ⱥ\";\n _ = try stdout.write(\n \"Bytes that represents the string object: \"\n );\n for (string_object) |char| {\n try stdout.print(\"{X} \", .{char});\n }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n var iterator = utf8.iterator();\n while (iterator.nextCodepointSlice()) |codepoint| {\n try stdout.print(\n \"got codepoint {}\\n\",\n .{std.fmt.fmtSliceHexUpper(codepoint)},\n );\n }\n}\n\n```\n:::\n\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig at @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers at @sec-root-file and especially at @sec-assignments.\n- How strings work in Zig at @sec-zig-strings.\n- How to use arrays and slices at @sec-arrays.\n- How to import functionality from other Zig modules at @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* at @sec-structs-and-oop.\n- Basic control flow syntax at @sec-zig-control-flow.\n- Enums at @sec-enum;\n- Pointers and Optionals at @sec-pointer;\n- Error handling with `try` and `catch` at @sec-error-handling;\n- Unit tests at @sec-unittests;\n- Vectors at @sec-vectors-simd;\n- Build System at @sec-build-system;\n\n\n\n\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/docs/search.json b/docs/search.json index 9d8728f7..805ce92a 100644 --- a/docs/search.json +++ b/docs/search.json @@ -144,7 +144,7 @@ "href": "Chapters/01-zig-weird.html#sec-assignments", "title": "1  Introducing Zig", "section": "1.4 Creating new objects in Zig (i.e. identifiers)", - "text": "1.4 Creating new objects in Zig (i.e. identifiers)\nLet’s talk more about objects in Zig. Readers that have past experience with other programming languages might know this concept through a different name, such as: “variable” or “identifier”. In this book, I choose to use the term “object” to refer to this concept.\nTo create a new object (or a new “identifier”) in Zig, we use the keywords const or var. These keywords specify if the object that you are creating is mutable or not. If you use const, then the object you are creating is a constant (or immutable) object, which means that once you declare this object, you can no longer change the value stored inside this object.\nOn the other side, if you use var, then, you are creating a variable (or mutable) object. You can change the value of this object as many times you want. Using the keyword var in Zig is similar to using the keywords let mut in Rust.\n\n1.4.1 Constant objects vs variable objects\nIn the code example below, we are creating a new constant object called age. This object stores a number representing the age of someone. However, this code example does not compile successfully. Because on the next line of code, we are trying to change the value of the object age to 25.\nThe zig compiler detects that we are trying to change the value of an object/identifier that is constant, and because of that, the compiler will raise a compilation error, warning us about the mistake.\n\nconst age = 24;\n// The line below is not valid!\nage = 25;\n\nt.zig:10:5: error: cannot assign to constant\n age = 25;\n ~~^~~\nIn contrast, if you use var, then, the object created is a variable object. With var you can declare this object in your source code, and then, change the value of this object how many times you want over future points in your source code.\nSo, using the same code example exposed above, if I change the declaration of the age object to use the var keyword, then, the program gets compiled successfully. Because now, the zig compiler detects that we are changing the value of an object that allows this behaviour, because it is an “variable object”.\n\nvar age: u8 = 24;\nage = 25;\n\n\n\n1.4.2 Declaring without an initial value\nBy default, when you declare a new object in Zig, you must give it an initial value. In other words, this means that we have to declare, and, at the same time, initialize every object we create in our source code.\nOn the other hand, you can, in fact, declare a new object in your source code, and not give it an explicit value. But we need to use a special keyword for that, which is the undefined keyword.\nIs important to emphasize that, you should avoid using undefined as much as possible. Because when you use this keyword, you leave your object uninitialized, and, as a consequence, if for some reason, your code use this object while it is uninitialized, then, you will definitely have undefined behaviour and major bugs in your program.\nIn the example below, I’m declaring the age object again. But this time, I do not give it an initial value. The variable is only initialized at the second line of code, where I store the number 25 in this object.\n\nvar age: u8 = undefined;\nage = 25;\n\nHaving these points in mind, just remember that you should avoid as much as possible to use undefined in your code. Always declare and initialize your objects. Because this gives you much more safety in your program. But in case you really need to declare an object without initializing it… the undefined keyword is the way to do it in Zig.\n\n\n1.4.3 There is no such thing as unused objects\nEvery object (being constant or variable) that you declare in Zig must be used in some way. You can give this object to a function call, as a function argument, or, you can use it in another expression to calculate the value of another object, or, you can call a method that belongs to this particular object.\nIt doesn’t matter in which way you use it. As long as you use it. If you try to break this rule, i.e. if your try to declare a object, but not use it, the zig compiler will not compile your Zig source code, and it will issue a error message warning that you have unused objects in your code.\nLet’s demonstrate this with an example. In the source code below, we declare a constant object called age. If you try to compile a simple Zig program with this line of code below, the compiler will return an error as demonstrated below:\n\nconst age = 15;\n\nt.zig:4:11: error: unused local constant\n const age = 15;\n ^~~\nEverytime you declare a new object in Zig, you have two choices:\n\nyou either use the value of this object;\nor you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign this object to an special character in Zig, which is the underscore (_). When you assign an object to a underscore, like in the example below, the zig compiler will automatically discard the value of this particular object.\nYou can see in the example below that, this time, the compiler did not complain about any “unused constant”, and successfully compiled our source code.\n\n// It compiles!\nconst age = 15;\n_ = age;\n\nNow, remember, everytime you assign a particular object to the underscore, this object is essentially destroyed. It is discarded by the compiler. This means that you can no longer use this object further in your code. It doesn’t exist anymore.\nSo if you try to use the constant age in the example below, after we discarded it, you will get a loud error message from the compiler (talking about a “pointless discard”) warning you about this mistake.\n\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n\nt.zig:7:5: error: pointless discard\n of local constant\nThis same rule applies to variable objects. Every variable object must also be used in some way. And if you assign a variable object to the underscore, this object also get’s discarded, and you can no longer use this object.\n\n\n1.4.4 You must mutate every variable objects\nEvery variable object that you create in your source code must be mutated at some point. In other words, if you declare an object as a variable object, with the keyword var, and you do not change the value of this object at some point in the future, the zig compiler will detect this, and it will raise an error warning you about this mistake.\nThe concept behind this is that every object you create in Zig should be preferably a constant object, unless you really need an object whose value will change during the execution of your program.\nSo, if I try to declare a variable object such as where_i_live below, and I do not change the value of this object in some way, the zig compiler raises an error message with the phrase “variable is never mutated”.\n\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'", + "text": "1.4 Creating new objects in Zig (i.e. identifiers)\nLet’s talk more about objects in Zig. Readers that have past experience with other programming languages might know this concept through a different name, such as: “variable” or “identifier”. In this book, I choose to use the term “object” to refer to this concept.\nTo create a new object (or a new “identifier”) in Zig, we use the keywords const or var. These keywords specify if the object that you are creating is mutable or not. If you use const, then the object you are creating is a constant (or immutable) object, which means that once you declare this object, you can no longer change the value stored inside this object.\nOn the other side, if you use var, then, you are creating a variable (or mutable) object. You can change the value of this object as many times you want. Using the keyword var in Zig is similar to using the keywords let mut in Rust.\n\n1.4.1 Constant objects vs variable objects\nIn the code example below, we are creating a new constant object called age. This object stores a number representing the age of someone. However, this code example does not compile successfully. Because on the next line of code, we are trying to change the value of the object age to 25.\nThe zig compiler detects that we are trying to change the value of an object/identifier that is constant, and because of that, the compiler will raise a compilation error, warning us about the mistake.\n\nconst age = 24;\n// The line below is not valid!\nage = 25;\n\nt.zig:10:5: error: cannot assign to constant\n age = 25;\n ~~^~~\nIn contrast, if you use var, then, the object created is a variable object. With var you can declare this object in your source code, and then, change the value of this object how many times you want over future points in your source code.\nSo, using the same code example exposed above, if I change the declaration of the age object to use the var keyword, then, the program gets compiled successfully. Because now, the zig compiler detects that we are changing the value of an object that allows this behaviour, because it is an “variable object”.\n\nvar age: u8 = 24;\nage = 25;\n\n\n\n1.4.2 Declaring without an initial value\nBy default, when you declare a new object in Zig, you must give it an initial value. In other words, this means that we have to declare, and, at the same time, initialize every object we create in our source code.\nOn the other hand, you can, in fact, declare a new object in your source code, and not give it an explicit value. But we need to use a special keyword for that, which is the undefined keyword.\nIs important to emphasize that, you should avoid using undefined as much as possible. Because when you use this keyword, you leave your object uninitialized, and, as a consequence, if for some reason, your code use this object while it is uninitialized, then, you will definitely have undefined behaviour and major bugs in your program.\nIn the example below, I’m declaring the age object again. But this time, I do not give it an initial value. The variable is only initialized at the second line of code, where I store the number 25 in this object.\n\nvar age: u8 = undefined;\nage = 25;\n\nHaving these points in mind, just remember that you should avoid as much as possible to use undefined in your code. Always declare and initialize your objects. Because this gives you much more safety in your program. But in case you really need to declare an object without initializing it… the undefined keyword is the way to do it in Zig.\n\n\n1.4.3 There is no such thing as unused objects\nEvery object (being constant or variable) that you declare in Zig must be used in some way. You can give this object to a function call, as a function argument, or, you can use it in another expression to calculate the value of another object, or, you can call a method that belongs to this particular object.\nIt doesn’t matter in which way you use it. As long as you use it. If you try to break this rule, i.e. if your try to declare a object, but not use it, the zig compiler will not compile your Zig source code, and it will issue a error message warning that you have unused objects in your code.\nLet’s demonstrate this with an example. In the source code below, we declare a constant object called age. If you try to compile a simple Zig program with this line of code below, the compiler will return an error as demonstrated below:\n\nconst age = 15;\n\nt.zig:4:11: error: unused local constant\n const age = 15;\n ^~~\nEverytime you declare a new object in Zig, you have two choices:\n\nyou either use the value of this object;\nor you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign this object to a special character in Zig, which is the underscore (_). When you assign an object to a underscore, like in the example below, the zig compiler will automatically discard the value of this particular object.\nYou can see in the example below that, this time, the compiler did not complain about any “unused constant”, and successfully compiled our source code.\n\n// It compiles!\nconst age = 15;\n_ = age;\n\nNow, remember, everytime you assign a particular object to the underscore, this object is essentially destroyed. It is discarded by the compiler. This means that you can no longer use this object further in your code. It doesn’t exist anymore.\nSo if you try to use the constant age in the example below, after we discarded it, you will get a loud error message from the compiler (talking about a “pointless discard”) warning you about this mistake.\n\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n\nt.zig:7:5: error: pointless discard\n of local constant\nThis same rule applies to variable objects. Every variable object must also be used in some way. And if you assign a variable object to the underscore, this object also get’s discarded, and you can no longer use this object.\n\n\n1.4.4 You must mutate every variable objects\nEvery variable object that you create in your source code must be mutated at some point. In other words, if you declare an object as a variable object, with the keyword var, and you do not change the value of this object at some point in the future, the zig compiler will detect this, and it will raise an error warning you about this mistake.\nThe concept behind this is that every object you create in Zig should be preferably a constant object, unless you really need an object whose value will change during the execution of your program.\nSo, if I try to declare a variable object such as where_i_live below, and I do not change the value of this object in some way, the zig compiler raises an error message with the phrase “variable is never mutated”.\n\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'", "crumbs": [ "1  Introducing Zig" ] From b9d4b94598b9645e161f2ace6d73cfc0026d8752 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 9 Feb 2025 10:58:34 -0300 Subject: [PATCH 059/151] Recompile book with changes --- .../01-zig-weird/execute-results/html.json | 4 ++-- docs/Chapters/01-zig-weird.html | 14 +++++++------- docs/search.json | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/_freeze/Chapters/01-zig-weird/execute-results/html.json b/_freeze/Chapters/01-zig-weird/execute-results/html.json index 3f48d096..1238c4cd 100644 --- a/_freeze/Chapters/01-zig-weird/execute-results/html.json +++ b/_freeze/Chapters/01-zig-weird/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "5041be02baff66bca29c690e3dfbfd7c", + "hash": "8ffa4a01e784b723e1aaf1806367c53c", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it is still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. They really make it sometimes hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscures the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that get's compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e. it is where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contain Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nTherefore, Zig contains a native build system in it, and\nwe can use this build system to write small scripts in Zig,\nwhich describes the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e. creating new objects)\nare made in Zig. You can create a new object in Zig by using the following syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). At @sec-assignments we talk more about objects in general.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n```\n:::\n\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that at @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIs worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt is like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portale C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig build.zig.zon main src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nOn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOs. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e. the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. Thus, if you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith a \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, operations like accessing the `stdout` (or opening a file) on Windows\ndepends on resources that are available only at *runtime* (you will learn more about compile-time\nversus runtime at @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword at @sec-comptime.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation at a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues \n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described at @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig latter in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig? \nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar in our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentations.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It is a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (at YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e. identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n age = 25;\n ~~^~~\n```\n\nIn contrast, if you use `var`, then, the object created is a variable object.\nWith `var` you can declare this object in your source code, and then,\nchange the value of this object how many times you want over future points\nin your source code.\n\nSo, using the same code example exposed above, if I change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it is an \"variable object\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIs important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code use this object while it is uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object. \n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e. if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n const age = 15;\n ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to a special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It is discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also get's discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig have many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e. the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\n\nIs worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it have the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array. \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it is a slice that\naccess all elements in the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhave 2 elements in it.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" at @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth at @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially at @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned at @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e. the start and the end of this range)\nis known at compile-time, the slice object that get's created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nat @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that get's created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e. a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can \ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n 1, 2, 3, 4, 5,\n 6, 7, 8, 9, 10\n};\n// This slice have a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n```\n:::\n\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat get's created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, the `slice` object have a runtime known range, because the end index of the range\nis not known at compile time. In other words, the size of the array at `buffer` is not known\nat compile time. When we execute this program, the size of the array might be 10, or, it might be 12\ndepending on where we execute it. Therefore, we don't know at compile time if\nthe slice object have a range of size 10, or, a range of size 12.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var n: usize = 0;\n if (builtin.target.os.tag == .windows) {\n n = 10;\n } else {\n n = 12;\n }\n const buffer = try allocator.alloc(u64, n);\n const slice = buffer[0..];\n _ = slice;\n}\n```\n:::\n\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code have its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e. a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n y += 1;\n break :add_one y;\n};\nif (x == 124 and y == 124) {\n try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nIn summary, there are two types of string values that you care about in Zig, which are:\n\n- String literal values.\n- String objects.\n\nA string literal value is just a pointer to a null-terminated array of bytes (i.e. similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string into the data type of the value itself.\nTherefore, a string literal value have a data type in the format `*const [n:0]u8`. The `n` in the data type\nindicates the size of the string.\n\nOn the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes,\nor, in other words, a slice of `u8` values (slices were presented at @sec-arrays). Thus,\na string object have a data type of `[]u8` or `[]const u8`, depending if the string object is\nmarked as constant with `const`, or as variable with `var`.\n\nBecause a string object is essentially a slice, it means that a string object always contains two things:\na pointer to an array of bytes (i.e. `u8` values) that represents the string value; and also, a length value,\nwhich specifies the size of the slice, or, how many elements there is in the slice.\nIs worth to emphasize that the array of bytes in a string object is not null-terminated, like in a\nstring literal value.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n\"A literal value\";\n// This is a string object:\nconst object: []const u8 = \"A string object\";\n```\n:::\n\n\n\n\n\nZig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example\";\n try stdout.print(\"Bytes that represents the string object: \", .{});\n for (string_object) |byte| {\n try stdout.print(\"{X} \", .{byte});\n }\n try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n 73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Strings in C\n\nAt first glance, a string literal value in Zig looks very similar to how C treats strings as well.\nIn more details, string values in C are treated internally as an array of arbitrary bytes,\nand this array is also null-terminated.\n\nBut one key difference between a Zig string literal and a C string, is that Zig also stores the length of\nthe string inside the object itself. In the case of a string literal value, this length is stored in the\ndata type of the value (i.e. the `n` variable in `[n:0]u8`). While, in a string object, the length is stored\nin the `len` attribute of the slice that represents the string object. This small detail makes your code safer,\nbecause it is much easier for the Zig compiler to check if you are trying to access an element that is\n\"out of bounds\", i.e. if your trying to access memory that does not belong to you.\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n char* array = \"An example of string in C\";\n int index = 0;\n while (1) {\n if (array[index] == '\\0') {\n break;\n }\n index++;\n }\n printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible. In a string object for example, you can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example of string literal in Zig\";\n try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it is a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const simple_array = [_]i32{1, 2, 3, 4};\n const string_obj: []const u8 = \"A string object\";\n std.debug.print(\n \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n );\n std.debug.print(\n \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n );\n std.debug.print(\n \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n );\n std.debug.print(\n \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nType 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons\n st [4]i32Type 4: []const u8\n```\n\n\n:::\n:::\n\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIs important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"Ⱥ\";\n _ = try stdout.write(\n \"Bytes that represents the string object: \"\n );\n for (string_object) |char| {\n try stdout.print(\"{X} \", .{char});\n }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n var iterator = utf8.iterator();\n while (iterator.nextCodepointSlice()) |codepoint| {\n try stdout.print(\n \"got codepoint {}\\n\",\n .{std.fmt.fmtSliceHexUpper(codepoint)},\n );\n }\n}\n\n```\n:::\n\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig at @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers at @sec-root-file and especially at @sec-assignments.\n- How strings work in Zig at @sec-zig-strings.\n- How to use arrays and slices at @sec-arrays.\n- How to import functionality from other Zig modules at @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* at @sec-structs-and-oop.\n- Basic control flow syntax at @sec-zig-control-flow.\n- Enums at @sec-enum;\n- Pointers and Optionals at @sec-pointer;\n- Error handling with `try` and `catch` at @sec-error-handling;\n- Unit tests at @sec-unittests;\n- Vectors at @sec-vectors-simd;\n- Build System at @sec-build-system;\n\n\n\n\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it is still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. They really make it sometimes hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscures the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that get's compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e. it is where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contain Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nTherefore, Zig contains a native build system in it, and\nwe can use this build system to write small scripts in Zig,\nwhich describes the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e. creating new objects)\nare made in Zig. You can create a new object in Zig by using the following syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). At @sec-assignments we talk more about objects in general.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n```\n:::\n\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that at @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIs worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt is like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portable C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig build.zig.zon main src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nIn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e. the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. Thus, if you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith a \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, operations like accessing the `stdout` (or opening a file) on Windows\ndepends on resources that are available only at *runtime* (you will learn more about compile-time\nversus runtime at @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword at @sec-comptime.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation at a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues \n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described in @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig later in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig? \nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar to our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentation.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It is a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (on YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e. identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n age = 25;\n ~~^~~\n```\n\nIn contrast, if you use `var`, then, the object created is a variable object.\nWith `var` you can declare this object in your source code, and then,\nchange the value of this object how many times you want over future points\nin your source code.\n\nSo, using the same code example exposed above, if I change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it is an \"variable object\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIs important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code use this object while it is uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object. \n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e. if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n const age = 15;\n ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to a special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It is discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also get's discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig have many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e. the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\n\nIs worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it have the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array. \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it is a slice that\naccess all elements in the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhave 2 elements in it.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" at @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth at @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially at @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned at @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e. the start and the end of this range)\nis known at compile-time, the slice object that get's created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nat @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that get's created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e. a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can \ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n 1, 2, 3, 4, 5,\n 6, 7, 8, 9, 10\n};\n// This slice have a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n```\n:::\n\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat get's created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, the `slice` object have a runtime known range, because the end index of the range\nis not known at compile time. In other words, the size of the array at `buffer` is not known\nat compile time. When we execute this program, the size of the array might be 10, or, it might be 12\ndepending on where we execute it. Therefore, we don't know at compile time if\nthe slice object have a range of size 10, or, a range of size 12.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var n: usize = 0;\n if (builtin.target.os.tag == .windows) {\n n = 10;\n } else {\n n = 12;\n }\n const buffer = try allocator.alloc(u64, n);\n const slice = buffer[0..];\n _ = slice;\n}\n```\n:::\n\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code have its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e. a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n y += 1;\n break :add_one y;\n};\nif (x == 124 and y == 124) {\n try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nIn summary, there are two types of string values that you care about in Zig, which are:\n\n- String literal values.\n- String objects.\n\nA string literal value is just a pointer to a null-terminated array of bytes (i.e. similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string into the data type of the value itself.\nTherefore, a string literal value have a data type in the format `*const [n:0]u8`. The `n` in the data type\nindicates the size of the string.\n\nOn the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes,\nor, in other words, a slice of `u8` values (slices were presented at @sec-arrays). Thus,\na string object have a data type of `[]u8` or `[]const u8`, depending if the string object is\nmarked as constant with `const`, or as variable with `var`.\n\nBecause a string object is essentially a slice, it means that a string object always contains two things:\na pointer to an array of bytes (i.e. `u8` values) that represents the string value; and also, a length value,\nwhich specifies the size of the slice, or, how many elements there is in the slice.\nIs worth to emphasize that the array of bytes in a string object is not null-terminated, like in a\nstring literal value.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n\"A literal value\";\n// This is a string object:\nconst object: []const u8 = \"A string object\";\n```\n:::\n\n\n\n\n\nZig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example\";\n try stdout.print(\"Bytes that represents the string object: \", .{});\n for (string_object) |byte| {\n try stdout.print(\"{X} \", .{byte});\n }\n try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n 73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Strings in C\n\nAt first glance, a string literal value in Zig looks very similar to how C treats strings as well.\nIn more details, string values in C are treated internally as an array of arbitrary bytes,\nand this array is also null-terminated.\n\nBut one key difference between a Zig string literal and a C string, is that Zig also stores the length of\nthe string inside the object itself. In the case of a string literal value, this length is stored in the\ndata type of the value (i.e. the `n` variable in `[n:0]u8`). While, in a string object, the length is stored\nin the `len` attribute of the slice that represents the string object. This small detail makes your code safer,\nbecause it is much easier for the Zig compiler to check if you are trying to access an element that is\n\"out of bounds\", i.e. if your trying to access memory that does not belong to you.\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n char* array = \"An example of string in C\";\n int index = 0;\n while (1) {\n if (array[index] == '\\0') {\n break;\n }\n index++;\n }\n printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible. In a string object for example, you can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example of string literal in Zig\";\n try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it is a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const simple_array = [_]i32{1, 2, 3, 4};\n const string_obj: []const u8 = \"A string object\";\n std.debug.print(\n \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n );\n std.debug.print(\n \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n );\n std.debug.print(\n \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n );\n std.debug.print(\n \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nType 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons\n st [4]i32Type 4: []const u8\n```\n\n\n:::\n:::\n\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIs important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"Ⱥ\";\n _ = try stdout.write(\n \"Bytes that represents the string object: \"\n );\n for (string_object) |char| {\n try stdout.print(\"{X} \", .{char});\n }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n var iterator = utf8.iterator();\n while (iterator.nextCodepointSlice()) |codepoint| {\n try stdout.print(\n \"got codepoint {}\\n\",\n .{std.fmt.fmtSliceHexUpper(codepoint)},\n );\n }\n}\n\n```\n:::\n\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig at @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers at @sec-root-file and especially at @sec-assignments.\n- How strings work in Zig at @sec-zig-strings.\n- How to use arrays and slices at @sec-arrays.\n- How to import functionality from other Zig modules at @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* at @sec-structs-and-oop.\n- Basic control flow syntax at @sec-zig-control-flow.\n- Enums at @sec-enum;\n- Pointers and Optionals at @sec-pointer;\n- Error handling with `try` and `catch` at @sec-error-handling;\n- Unit tests at @sec-unittests;\n- Vectors at @sec-vectors-simd;\n- Build System at @sec-build-system;\n\n\n\n\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/docs/Chapters/01-zig-weird.html b/docs/Chapters/01-zig-weird.html index 1bd1fbd3..fed40272 100644 --- a/docs/Chapters/01-zig-weird.html +++ b/docs/Chapters/01-zig-weird.html @@ -469,14 +469,14 @@

    1.2.5 Compile and execute at the same time

    -

    On the previous section, I presented the zig build-exe command, which compiles Zig modules into an executable file. However, this means that, in order to execute the executable file, we have to run two different commands. First, the zig build-exe command, and then, we call the executable file created by the compiler.

    +

    In the previous section, I presented the zig build-exe command, which compiles Zig modules into an executable file. However, this means that, in order to execute the executable file, we have to run two different commands. First, the zig build-exe command, and then, we call the executable file created by the compiler.

    But what if we wanted to perform these two steps, all at once, in a single command? We can do that by using the zig run command.

    zig run src/main.zig
    Hello, world!

    1.2.6 Important note for Windows users

    -

    First of all, this is a Windows-specific thing, and, therefore, does not apply to other operating systems, such as Linux and macOs. In summary, if you have a piece of Zig code that includes some global variables whose initialization rely on runtime resources, then, you might have some troubles while trying to compile this Zig code on Windows.

    +

    First of all, this is a Windows-specific thing, and, therefore, does not apply to other operating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that includes some global variables whose initialization rely on runtime resources, then, you might have some troubles while trying to compile this Zig code on Windows.

    An example of that is accessing the stdout (i.e. the standard output of your system), which is usually done in Zig by using the expression std.io.getStdOut(). Thus, if you use this expression to instantiate a global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows, with a “unable to evaluate comptime expression” error message.

    This failure in the compilation process happens because all global variables in Zig are initialized at compile-time. However, operations like accessing the stdout (or opening a file) on Windows depends on resources that are available only at runtime (you will learn more about compile-time versus runtime at Section 3.1.1).

    For example, if you try to compile this code example on Windows, you will likely get the error message exposed below:

    @@ -508,12 +508,12 @@

    1.2.7 Compiling the entire project

    -

    Just as I described at Section 1.2.1, as our project grows in size and complexity, we usually prefer to organize the compilation and build process of the project into a build script, using some sort of “build system”.

    +

    Just as I described in Section 1.2.1, as our project grows in size and complexity, we usually prefer to organize the compilation and build process of the project into a build script, using some sort of “build system”.

    In other words, as our project grows in size and complexity, the build-exe, build-lib and build-obj commands become harder to use directly. Because then, we start to list multiple and multiple modules at the same time. We also start to add built-in compilation flags to customize the build process for our needs, etc. It becomes a lot of work to write the necessary commands by hand.

    In C/C++ projects, programmers normally opt to use CMake, Ninja, Makefile or configure scripts to organize this process. However, in Zig, we have a native build system in the language itself. So, we can write build scripts in Zig to compile and build Zig projects. Then, all we need to do, is to call the zig build command to build our project.

    So, when you execute the zig build command, the zig compiler will search for a Zig module named build.zig inside your current directory, which should be your build script, containing the necessary code to compile and build your project. If the compiler does find this build.zig file in your directory, then, the compiler will essentially execute a zig run command over this build.zig file, to compile and execute this build script, which in turn, will compile and build your entire project.

    zig build
    -

    After you execute this “build project” command, a zig-out directory is created in the root of your project directory, where you can find the binary executables and libraries created from your Zig modules accordingly to the build commands that you specified at build.zig. We will talk more about the build system in Zig latter in this book.

    +

    After you execute this “build project” command, a zig-out directory is created in the root of your project directory, where you can find the binary executables and libraries created from your Zig modules accordingly to the build commands that you specified at build.zig. We will talk more about the build system in Zig later in this book.

    In the example below, I’m executing the binary executable named hello_world that was generated by the compiler after the zig build command.

    ./zig-out/bin/hello_world
    Hello, world!
    @@ -541,8 +541,8 @@

    the Language Protocol implementation for Zig, zls16.
  • the event-loop library libxev17.
  • -

    All these assets are available on GitHub, and this is great, because we can use the GitHub search bar in our advantage, to find Zig code that fits our description. For example, you can always include lang:Zig in the GitHub search bar when you are searching for a particular pattern. This will limit the search to only Zig modules.

    -

    Also, a great alternative is to consult online resources and documentations. Here is a quick list of resources that I personally use from time to time to learn more about the language each day:

    +

    All these assets are available on GitHub, and this is great, because we can use the GitHub search bar to our advantage, to find Zig code that fits our description. For example, you can always include lang:Zig in the GitHub search bar when you are searching for a particular pattern. This will limit the search to only Zig modules.

    +

    Also, a great alternative is to consult online resources and documentation. Here is a quick list of resources that I personally use from time to time to learn more about the language each day:

    Another great strategy to learn Zig, or honestly, to learn any language you want, is to practice it by solving exercises. For example, there is a famous repository in the Zig community called Ziglings18 , which contains more than 100 small exercises that you can solve. It is a repository of tiny programs written in Zig that are currently broken, and your responsibility is to fix these programs, and make them work again.

    -

    A famous tech YouTuber known as The Primeagen also posted some videos (at YouTube) where he solves these exercises from Ziglings. The first video is named “Trying Zig Part 1”19.

    +

    A famous tech YouTuber known as The Primeagen also posted some videos (on YouTube) where he solves these exercises from Ziglings. The first video is named “Trying Zig Part 1”19.

    Another great alternative, is to solve the Advent of Code exercises20. There are people that already took the time to learn and solve the exercises, and they posted their solutions on GitHub as well, so, in case you need some resource to compare while solving the exercises, you can look at these two repositories:

    • https://github.com/SpexGuy/Zig-AoC-Template;
    • diff --git a/docs/search.json b/docs/search.json index 160e2623..09d33825 100644 --- a/docs/search.json +++ b/docs/search.json @@ -124,7 +124,7 @@ "href": "Chapters/01-zig-weird.html#hello-world-in-zig", "title": "1  Introducing Zig", "section": "1.2 Hello world in Zig", - "text": "1.2 Hello world in Zig\nWe begin our journey in Zig by creating a small “Hello World” program. To start a new Zig project in your computer, you simply call the init command from the zig compiler. Just create a new directory in your computer, then, init a new Zig project inside this directory, like this:\nmkdir hello_world\ncd hello_world\nzig init\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n\n1.2.1 Understanding the project files\nAfter you run the init command from the zig compiler, some new files are created inside of your current directory. First, a “source” (src) directory is created, containing two files, main.zig and root.zig. Each .zig file is a separate Zig module, which is simply a text file that contains some Zig code.\nBy convention, the main.zig module is where your main function lives. Thus, if you are building an executable program in Zig, you need to declare a main() function, which represents the entrypoint of your program, i.e. it is where the execution of your program begins.\nHowever, if you are building a library (instead of an executable program), then, the normal procedure is to delete this main.zig file and start with the root.zig module. By convention, the root.zig module is the root source file of your library.\ntree .\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\nThe init command also creates two additional files in our working directory: build.zig and build.zig.zon. The first file (build.zig) represents a build script written in Zig. This script is executed when you call the build command from the zig compiler. In other words, this file contain Zig code that executes the necessary steps to build the entire project.\nLow-level languages normally use a compiler to build your source code into binary executables or binary libraries. Nevertheless, this process of compiling your source code and building binary executables or binary libraries from it, became a real challenge in the programming world, once the projects became bigger and bigger. As a result, programmers created “build systems”, which are a second set of tools designed to make this process of compiling and building complex projects, easier.\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja, which are used to build complex C and C++ projects. With these systems, you can write scripts, which are called “build scripts”. They simply are scripts that describes the necessary steps to compile/build your project.\nHowever, these are separate tools, that do not belong to C/C++ compilers, like gcc or clang. As a result, in C/C++ projects, you have not only to install and manage your C/C++ compilers, but you also have to install and manage these build systems separately.\nIn Zig, we don’t need to use a separate set of tools to build our projects, because a build system is embedded inside the language itself. Therefore, Zig contains a native build system in it, and we can use this build system to write small scripts in Zig, which describes the necessary steps to build/compile our Zig project1. So, everything you need to build a complex Zig project is the zig compiler, and nothing more.\nThe second generated file (build.zig.zon) is a JSON-like file, in which you can describe your project, and also, declare a set of dependencies of your project that you want to fetch from the internet. In other words, you can use this build.zig.zon file to include a list of external libraries in your project.\nOne possible way to include an external Zig library in your project, is to manually build and install the library in your system, and just link your source code with the library at the build step of your project.\nHowever, if this external Zig library is available on GitHub for example, and it has a valid build.zig.zon file in root folder of the project, which describes the project, you can easily include this library in your project by simply listing this external library in your build.zig.zon file.\nIn other words, this build.zig.zon file works similarly to the package.json file in Javascript projects, or the Pipfile file in Python projects, or the Cargo.toml file in Rust projects. You can read more about this specific file in a couple of articles on the internet23, and you can also see the expected schema for this build.zig.zon file in a documentation file inside the official repository of Zig4.\n\n\n1.2.2 The file root.zig\nLet’s take a look into the root.zig file. You might have noticed that every line of code with an expression ends with a semicolon (;). This follows the syntax of a C-family programming language5.\nAlso, notice the @import() call at the first line. We use this built-in function to import functionality from other Zig modules into our current module. This @import() function works similarly to the #include pre-processor in C or C++, or, to the import statement in Python or Javascript code. In this example, we are importing the std module, which gives you access to the Zig Standard Library.\nIn this root.zig file, we can also see how assignments (i.e. creating new objects) are made in Zig. You can create a new object in Zig by using the following syntax (const|var) name = value;. In the example below, we are creating two constant objects (std and testing). At Section 1.4 we talk more about objects in general.\n\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n\nFunctions in Zig are declared using the fn keyword. In this root.zig module, we are declaring a function called add(), which has two arguments named a and b. The function returns an integer of the type i32 as result.\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit the type of an object in your code, if this type can be inferred by the zig compiler (we talk more about that at Section 2.4). But there are other situations where you do need to be explicit. For example, you do have to explicitly specify the type of each function argument, and also, the return type of every function that you create in Zig.\nWe specify the type of an object or a function argument in Zig by using a colon character (:) followed by the type after the name of this object/function argument. With the expressions a: i32 and b: i32, we know that both a and b arguments have type i32, which is a signed 32 bit integer. In this part, the syntax in Zig is identical to the syntax in Rust, which also specifies types by using the colon character.\nLastly, we have the return type of the function at the end of the line, before we open the curly braces to start writing the function’s body. In the example above, this type is also a signed 32 bit integer (i32) value.\nNotice that we also have an export keyword before the function declaration. This keyword is similar to the extern keyword in C. It exposes the function to make it available in the library API. Therefore, if you are writing a library for other people to use, you have to expose the functions you write in the public API of this library by using this export keyword. If we removed the export keyword from the add() function declaration, then, this function would be no longer exposed in the library object built by the zig compiler.\n\n\n1.2.3 The main.zig file\nNow that we have learned a lot about Zig’s syntax from the root.zig file, let’s take a look at the main.zig file. A lot of the elements we saw in root.zig are also present in main.zig. But there are some other elements that we haven’t seen yet, so let’s dive in.\nFirst, look at the return type of the main() function in this file. We can see a small change. The return type of the function (void) is accompanied by an exclamation mark (!). This exclamation mark tells us that this main() function might return an error.\nIs worth noting that, a main() function in Zig is allowed to return nothing (void), or an unsigned 8-bit integer (u8) value6, or an error. In other words, you can write your main() function in Zig to return essentially nothing (void), or, if you prefer, you can also write a more C-like main() function, which returns an integer value that usually serves as a “status code” for the process.\nIn this example, the return type annotation of main() indicates that this function can either return nothing (void), or return an error. This exclamation mark in the return type annotation is an interesting and powerful feature of Zig. In summary, if you write a function and something inside the body of this function might return an error, then, you are forced to:\n\neither add the exclamation mark to the return type of the function and make it clear that this function might return an error.\nexplicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through a try catch pattern. Zig does have both try and catch keywords. But they work a little differently than what you’re probably used to in other languages.\nIf we look at the main() function below, you can see that we do have a try keyword on the 5th line. But we do not have a catch keyword in this code. In Zig, we use the try keyword to execute an expression that might return an error, which, in this example, is the stdout.print() expression.\nIn essence, the try keyword executes the expression stdout.print(). If this expression returns a valid value, then, the try keyword does absolutely nothing. It only passes the value forward. It is like if this try keyword was never there. However, if the expression does return an error, then, the try keyword will unwrap the error value, then, it returns this error from the function and also prints the current stack trace to stderr.\nThis might sound weird to you if you come from a high-level language. Because in high-level languages, such as Python, if an error occurs somewhere, this error is automatically returned and the execution of your program will automatically stop even if you don’t want to stop the execution. You are obligated to face the error.\n\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n\nAnother thing that you might have noticed in this code example, is that the main() function is marked with the pub keyword. It marks the main() function as a public function from this module. Every function in your Zig module is by default private to this Zig module and can only be called from within the module. Unless, you explicitly mark this function as a public function with the pub keyword.\nIf you think about it, this pub keyword in Zig does essentially the opposite of what the static keyword do in C/C++. By making a function “public” you allow other Zig modules to access and call this function. A calling Zig module imports another module by using the @import() built-in function, which makes all public functions from the imported module visible to the calling Zig module.\n\n\n1.2.4 Compiling your source code\nYou can compile your Zig modules into a binary executable by running the build-exe command from the zig compiler. You simply list all the Zig modules that you want to build after the build-exe command, separated by spaces. In the example below, we are compiling the module main.zig.\nzig build-exe src/main.zig\nSince we are building an executable, the zig compiler will look for a main() function declared in any of the files that you list after the build-exe command. If the compiler does not find a main() function declared somewhere, a compilation error will be raised, warning about this mistake.\nThe zig compiler also offers a build-lib and build-obj commands, which work the exact same way as the build-exe command. The only difference is that, they compile your Zig modules into a portable C ABI library, or, into object files, respectively.\nIn the case of the build-exe command, a binary executable file is created by the zig compiler in the root directory of your project. If we take a look now at the contents of our current directory, with a simple ls command, we can see the binary file called main that was created by the compiler.\nls\nbuild.zig build.zig.zon main src\nIf I execute this binary executable, I get the “Hello World” message in the terminal , as we expected.\n./main\nHello, world!\n\n\n1.2.5 Compile and execute at the same time\nOn the previous section, I presented the zig build-exe command, which compiles Zig modules into an executable file. However, this means that, in order to execute the executable file, we have to run two different commands. First, the zig build-exe command, and then, we call the executable file created by the compiler.\nBut what if we wanted to perform these two steps, all at once, in a single command? We can do that by using the zig run command.\nzig run src/main.zig\nHello, world!\n\n\n1.2.6 Important note for Windows users\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other operating systems, such as Linux and macOs. In summary, if you have a piece of Zig code that includes some global variables whose initialization rely on runtime resources, then, you might have some troubles while trying to compile this Zig code on Windows.\nAn example of that is accessing the stdout (i.e. the standard output of your system), which is usually done in Zig by using the expression std.io.getStdOut(). Thus, if you use this expression to instantiate a global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows, with a “unable to evaluate comptime expression” error message.\nThis failure in the compilation process happens because all global variables in Zig are initialized at compile-time. However, operations like accessing the stdout (or opening a file) on Windows depends on resources that are available only at runtime (you will learn more about compile-time versus runtime at Section 3.1.1).\nFor example, if you try to compile this code example on Windows, you will likely get the error message exposed below:\n\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\nTo avoid this problem on Windows, we need to force the zig compiler to instantiate this stdout object only at runtime, instead of instantiating it at compile-time. We can achieve that by simply moving the expression to a function body.\nThis solves the problem because all expressions that are inside a function body in Zig are evaluated only at runtime, unless you use the comptime keyword explicitly to change this behaviour. You will learn more about this comptime keyword at Section 12.1.\n\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n\nHello\nYou can read more details about this Windows-specific limitation at a couple of GitHub issues opened at the official Zig repository. More specifically, the issues 17186 7 and 19864 8.\n\n\n1.2.7 Compiling the entire project\nJust as I described at Section 1.2.1, as our project grows in size and complexity, we usually prefer to organize the compilation and build process of the project into a build script, using some sort of “build system”.\nIn other words, as our project grows in size and complexity, the build-exe, build-lib and build-obj commands become harder to use directly. Because then, we start to list multiple and multiple modules at the same time. We also start to add built-in compilation flags to customize the build process for our needs, etc. It becomes a lot of work to write the necessary commands by hand.\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, Makefile or configure scripts to organize this process. However, in Zig, we have a native build system in the language itself. So, we can write build scripts in Zig to compile and build Zig projects. Then, all we need to do, is to call the zig build command to build our project.\nSo, when you execute the zig build command, the zig compiler will search for a Zig module named build.zig inside your current directory, which should be your build script, containing the necessary code to compile and build your project. If the compiler does find this build.zig file in your directory, then, the compiler will essentially execute a zig run command over this build.zig file, to compile and execute this build script, which in turn, will compile and build your entire project.\nzig build\nAfter you execute this “build project” command, a zig-out directory is created in the root of your project directory, where you can find the binary executables and libraries created from your Zig modules accordingly to the build commands that you specified at build.zig. We will talk more about the build system in Zig latter in this book.\nIn the example below, I’m executing the binary executable named hello_world that was generated by the compiler after the zig build command.\n./zig-out/bin/hello_world\nHello, world!", + "text": "1.2 Hello world in Zig\nWe begin our journey in Zig by creating a small “Hello World” program. To start a new Zig project in your computer, you simply call the init command from the zig compiler. Just create a new directory in your computer, then, init a new Zig project inside this directory, like this:\nmkdir hello_world\ncd hello_world\nzig init\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n\n1.2.1 Understanding the project files\nAfter you run the init command from the zig compiler, some new files are created inside of your current directory. First, a “source” (src) directory is created, containing two files, main.zig and root.zig. Each .zig file is a separate Zig module, which is simply a text file that contains some Zig code.\nBy convention, the main.zig module is where your main function lives. Thus, if you are building an executable program in Zig, you need to declare a main() function, which represents the entrypoint of your program, i.e. it is where the execution of your program begins.\nHowever, if you are building a library (instead of an executable program), then, the normal procedure is to delete this main.zig file and start with the root.zig module. By convention, the root.zig module is the root source file of your library.\ntree .\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\nThe init command also creates two additional files in our working directory: build.zig and build.zig.zon. The first file (build.zig) represents a build script written in Zig. This script is executed when you call the build command from the zig compiler. In other words, this file contain Zig code that executes the necessary steps to build the entire project.\nLow-level languages normally use a compiler to build your source code into binary executables or binary libraries. Nevertheless, this process of compiling your source code and building binary executables or binary libraries from it, became a real challenge in the programming world, once the projects became bigger and bigger. As a result, programmers created “build systems”, which are a second set of tools designed to make this process of compiling and building complex projects, easier.\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja, which are used to build complex C and C++ projects. With these systems, you can write scripts, which are called “build scripts”. They simply are scripts that describes the necessary steps to compile/build your project.\nHowever, these are separate tools, that do not belong to C/C++ compilers, like gcc or clang. As a result, in C/C++ projects, you have not only to install and manage your C/C++ compilers, but you also have to install and manage these build systems separately.\nIn Zig, we don’t need to use a separate set of tools to build our projects, because a build system is embedded inside the language itself. Therefore, Zig contains a native build system in it, and we can use this build system to write small scripts in Zig, which describes the necessary steps to build/compile our Zig project1. So, everything you need to build a complex Zig project is the zig compiler, and nothing more.\nThe second generated file (build.zig.zon) is a JSON-like file, in which you can describe your project, and also, declare a set of dependencies of your project that you want to fetch from the internet. In other words, you can use this build.zig.zon file to include a list of external libraries in your project.\nOne possible way to include an external Zig library in your project, is to manually build and install the library in your system, and just link your source code with the library at the build step of your project.\nHowever, if this external Zig library is available on GitHub for example, and it has a valid build.zig.zon file in root folder of the project, which describes the project, you can easily include this library in your project by simply listing this external library in your build.zig.zon file.\nIn other words, this build.zig.zon file works similarly to the package.json file in Javascript projects, or the Pipfile file in Python projects, or the Cargo.toml file in Rust projects. You can read more about this specific file in a couple of articles on the internet23, and you can also see the expected schema for this build.zig.zon file in a documentation file inside the official repository of Zig4.\n\n\n1.2.2 The file root.zig\nLet’s take a look into the root.zig file. You might have noticed that every line of code with an expression ends with a semicolon (;). This follows the syntax of a C-family programming language5.\nAlso, notice the @import() call at the first line. We use this built-in function to import functionality from other Zig modules into our current module. This @import() function works similarly to the #include pre-processor in C or C++, or, to the import statement in Python or Javascript code. In this example, we are importing the std module, which gives you access to the Zig Standard Library.\nIn this root.zig file, we can also see how assignments (i.e. creating new objects) are made in Zig. You can create a new object in Zig by using the following syntax (const|var) name = value;. In the example below, we are creating two constant objects (std and testing). At Section 1.4 we talk more about objects in general.\n\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n\nFunctions in Zig are declared using the fn keyword. In this root.zig module, we are declaring a function called add(), which has two arguments named a and b. The function returns an integer of the type i32 as result.\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit the type of an object in your code, if this type can be inferred by the zig compiler (we talk more about that at Section 2.4). But there are other situations where you do need to be explicit. For example, you do have to explicitly specify the type of each function argument, and also, the return type of every function that you create in Zig.\nWe specify the type of an object or a function argument in Zig by using a colon character (:) followed by the type after the name of this object/function argument. With the expressions a: i32 and b: i32, we know that both a and b arguments have type i32, which is a signed 32 bit integer. In this part, the syntax in Zig is identical to the syntax in Rust, which also specifies types by using the colon character.\nLastly, we have the return type of the function at the end of the line, before we open the curly braces to start writing the function’s body. In the example above, this type is also a signed 32 bit integer (i32) value.\nNotice that we also have an export keyword before the function declaration. This keyword is similar to the extern keyword in C. It exposes the function to make it available in the library API. Therefore, if you are writing a library for other people to use, you have to expose the functions you write in the public API of this library by using this export keyword. If we removed the export keyword from the add() function declaration, then, this function would be no longer exposed in the library object built by the zig compiler.\n\n\n1.2.3 The main.zig file\nNow that we have learned a lot about Zig’s syntax from the root.zig file, let’s take a look at the main.zig file. A lot of the elements we saw in root.zig are also present in main.zig. But there are some other elements that we haven’t seen yet, so let’s dive in.\nFirst, look at the return type of the main() function in this file. We can see a small change. The return type of the function (void) is accompanied by an exclamation mark (!). This exclamation mark tells us that this main() function might return an error.\nIs worth noting that, a main() function in Zig is allowed to return nothing (void), or an unsigned 8-bit integer (u8) value6, or an error. In other words, you can write your main() function in Zig to return essentially nothing (void), or, if you prefer, you can also write a more C-like main() function, which returns an integer value that usually serves as a “status code” for the process.\nIn this example, the return type annotation of main() indicates that this function can either return nothing (void), or return an error. This exclamation mark in the return type annotation is an interesting and powerful feature of Zig. In summary, if you write a function and something inside the body of this function might return an error, then, you are forced to:\n\neither add the exclamation mark to the return type of the function and make it clear that this function might return an error.\nexplicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through a try catch pattern. Zig does have both try and catch keywords. But they work a little differently than what you’re probably used to in other languages.\nIf we look at the main() function below, you can see that we do have a try keyword on the 5th line. But we do not have a catch keyword in this code. In Zig, we use the try keyword to execute an expression that might return an error, which, in this example, is the stdout.print() expression.\nIn essence, the try keyword executes the expression stdout.print(). If this expression returns a valid value, then, the try keyword does absolutely nothing. It only passes the value forward. It is like if this try keyword was never there. However, if the expression does return an error, then, the try keyword will unwrap the error value, then, it returns this error from the function and also prints the current stack trace to stderr.\nThis might sound weird to you if you come from a high-level language. Because in high-level languages, such as Python, if an error occurs somewhere, this error is automatically returned and the execution of your program will automatically stop even if you don’t want to stop the execution. You are obligated to face the error.\n\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n\nAnother thing that you might have noticed in this code example, is that the main() function is marked with the pub keyword. It marks the main() function as a public function from this module. Every function in your Zig module is by default private to this Zig module and can only be called from within the module. Unless, you explicitly mark this function as a public function with the pub keyword.\nIf you think about it, this pub keyword in Zig does essentially the opposite of what the static keyword do in C/C++. By making a function “public” you allow other Zig modules to access and call this function. A calling Zig module imports another module by using the @import() built-in function, which makes all public functions from the imported module visible to the calling Zig module.\n\n\n1.2.4 Compiling your source code\nYou can compile your Zig modules into a binary executable by running the build-exe command from the zig compiler. You simply list all the Zig modules that you want to build after the build-exe command, separated by spaces. In the example below, we are compiling the module main.zig.\nzig build-exe src/main.zig\nSince we are building an executable, the zig compiler will look for a main() function declared in any of the files that you list after the build-exe command. If the compiler does not find a main() function declared somewhere, a compilation error will be raised, warning about this mistake.\nThe zig compiler also offers a build-lib and build-obj commands, which work the exact same way as the build-exe command. The only difference is that, they compile your Zig modules into a portable C ABI library, or, into object files, respectively.\nIn the case of the build-exe command, a binary executable file is created by the zig compiler in the root directory of your project. If we take a look now at the contents of our current directory, with a simple ls command, we can see the binary file called main that was created by the compiler.\nls\nbuild.zig build.zig.zon main src\nIf I execute this binary executable, I get the “Hello World” message in the terminal , as we expected.\n./main\nHello, world!\n\n\n1.2.5 Compile and execute at the same time\nIn the previous section, I presented the zig build-exe command, which compiles Zig modules into an executable file. However, this means that, in order to execute the executable file, we have to run two different commands. First, the zig build-exe command, and then, we call the executable file created by the compiler.\nBut what if we wanted to perform these two steps, all at once, in a single command? We can do that by using the zig run command.\nzig run src/main.zig\nHello, world!\n\n\n1.2.6 Important note for Windows users\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other operating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that includes some global variables whose initialization rely on runtime resources, then, you might have some troubles while trying to compile this Zig code on Windows.\nAn example of that is accessing the stdout (i.e. the standard output of your system), which is usually done in Zig by using the expression std.io.getStdOut(). Thus, if you use this expression to instantiate a global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows, with a “unable to evaluate comptime expression” error message.\nThis failure in the compilation process happens because all global variables in Zig are initialized at compile-time. However, operations like accessing the stdout (or opening a file) on Windows depends on resources that are available only at runtime (you will learn more about compile-time versus runtime at Section 3.1.1).\nFor example, if you try to compile this code example on Windows, you will likely get the error message exposed below:\n\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\nTo avoid this problem on Windows, we need to force the zig compiler to instantiate this stdout object only at runtime, instead of instantiating it at compile-time. We can achieve that by simply moving the expression to a function body.\nThis solves the problem because all expressions that are inside a function body in Zig are evaluated only at runtime, unless you use the comptime keyword explicitly to change this behaviour. You will learn more about this comptime keyword at Section 12.1.\n\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n\nHello\nYou can read more details about this Windows-specific limitation at a couple of GitHub issues opened at the official Zig repository. More specifically, the issues 17186 7 and 19864 8.\n\n\n1.2.7 Compiling the entire project\nJust as I described in Section 1.2.1, as our project grows in size and complexity, we usually prefer to organize the compilation and build process of the project into a build script, using some sort of “build system”.\nIn other words, as our project grows in size and complexity, the build-exe, build-lib and build-obj commands become harder to use directly. Because then, we start to list multiple and multiple modules at the same time. We also start to add built-in compilation flags to customize the build process for our needs, etc. It becomes a lot of work to write the necessary commands by hand.\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, Makefile or configure scripts to organize this process. However, in Zig, we have a native build system in the language itself. So, we can write build scripts in Zig to compile and build Zig projects. Then, all we need to do, is to call the zig build command to build our project.\nSo, when you execute the zig build command, the zig compiler will search for a Zig module named build.zig inside your current directory, which should be your build script, containing the necessary code to compile and build your project. If the compiler does find this build.zig file in your directory, then, the compiler will essentially execute a zig run command over this build.zig file, to compile and execute this build script, which in turn, will compile and build your entire project.\nzig build\nAfter you execute this “build project” command, a zig-out directory is created in the root of your project directory, where you can find the binary executables and libraries created from your Zig modules accordingly to the build commands that you specified at build.zig. We will talk more about the build system in Zig later in this book.\nIn the example below, I’m executing the binary executable named hello_world that was generated by the compiler after the zig build command.\n./zig-out/bin/hello_world\nHello, world!", "crumbs": [ "1  Introducing Zig" ] @@ -134,7 +134,7 @@ "href": "Chapters/01-zig-weird.html#how-to-learn-zig", "title": "1  Introducing Zig", "section": "1.3 How to learn Zig?", - "text": "1.3 How to learn Zig?\nWhat are the best strategies to learn Zig? First of all, of course this book will help you a lot on your journey through Zig. But you will also need some extra resources if you want to be really good at Zig.\nAs a first tip, you can join a community with Zig programmers to get some help , when you need it:\n\nReddit forum: https://www.reddit.com/r/Zig/;\nZiggit community: https://ziggit.dev/;\nDiscord, Slack, Telegram, and others: https://github.com/ziglang/zig/wiki/Community;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try to read Zig code often, and things will become more clear. A C/C++ programmer would also probably give you this same tip. Because this strategy really works!\nNow, where can you find Zig code to read? I personally think that, the best way of reading Zig code is to read the source code of the Zig Standard Library. The Zig Standard Library is available at the lib/std folder9 on the official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\nAlso, a great alternative is to read code from other large Zig codebases, such as:\n\nthe Javascript runtime Bun10.\nthe game engine Mach11.\na LLama 2 LLM model implementation in Zig12.\nthe financial transactions database tigerbeetle13.\nthe command-line arguments parser zig-clap14.\nthe UI framework capy15.\nthe Language Protocol implementation for Zig, zls16.\nthe event-loop library libxev17.\n\nAll these assets are available on GitHub, and this is great, because we can use the GitHub search bar in our advantage, to find Zig code that fits our description. For example, you can always include lang:Zig in the GitHub search bar when you are searching for a particular pattern. This will limit the search to only Zig modules.\nAlso, a great alternative is to consult online resources and documentations. Here is a quick list of resources that I personally use from time to time to learn more about the language each day:\n\nZig Language Reference: https://ziglang.org/documentation/master/;\nZig Standard Library Reference: https://ziglang.org/documentation/master/std/;\nZig Guide: https://zig.guide/;\nKarl Seguin Blog: https://www.openmymind.net/;\nZig News: https://zig.news/;\nRead the code written by one of the Zig core team members: https://github.com/kubkon;\nSome livecoding sessions are transmitted in the Zig Showtime Youtube Channel: https://www.youtube.com/@ZigSHOWTIME/videos;\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want, is to practice it by solving exercises. For example, there is a famous repository in the Zig community called Ziglings18 , which contains more than 100 small exercises that you can solve. It is a repository of tiny programs written in Zig that are currently broken, and your responsibility is to fix these programs, and make them work again.\nA famous tech YouTuber known as The Primeagen also posted some videos (at YouTube) where he solves these exercises from Ziglings. The first video is named “Trying Zig Part 1”19.\nAnother great alternative, is to solve the Advent of Code exercises20. There are people that already took the time to learn and solve the exercises, and they posted their solutions on GitHub as well, so, in case you need some resource to compare while solving the exercises, you can look at these two repositories:\n\nhttps://github.com/SpexGuy/Zig-AoC-Template;\nhttps://github.com/fjebaker/advent-of-code-2022;", + "text": "1.3 How to learn Zig?\nWhat are the best strategies to learn Zig? First of all, of course this book will help you a lot on your journey through Zig. But you will also need some extra resources if you want to be really good at Zig.\nAs a first tip, you can join a community with Zig programmers to get some help , when you need it:\n\nReddit forum: https://www.reddit.com/r/Zig/;\nZiggit community: https://ziggit.dev/;\nDiscord, Slack, Telegram, and others: https://github.com/ziglang/zig/wiki/Community;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try to read Zig code often, and things will become more clear. A C/C++ programmer would also probably give you this same tip. Because this strategy really works!\nNow, where can you find Zig code to read? I personally think that, the best way of reading Zig code is to read the source code of the Zig Standard Library. The Zig Standard Library is available at the lib/std folder9 on the official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\nAlso, a great alternative is to read code from other large Zig codebases, such as:\n\nthe Javascript runtime Bun10.\nthe game engine Mach11.\na LLama 2 LLM model implementation in Zig12.\nthe financial transactions database tigerbeetle13.\nthe command-line arguments parser zig-clap14.\nthe UI framework capy15.\nthe Language Protocol implementation for Zig, zls16.\nthe event-loop library libxev17.\n\nAll these assets are available on GitHub, and this is great, because we can use the GitHub search bar to our advantage, to find Zig code that fits our description. For example, you can always include lang:Zig in the GitHub search bar when you are searching for a particular pattern. This will limit the search to only Zig modules.\nAlso, a great alternative is to consult online resources and documentation. Here is a quick list of resources that I personally use from time to time to learn more about the language each day:\n\nZig Language Reference: https://ziglang.org/documentation/master/;\nZig Standard Library Reference: https://ziglang.org/documentation/master/std/;\nZig Guide: https://zig.guide/;\nKarl Seguin Blog: https://www.openmymind.net/;\nZig News: https://zig.news/;\nRead the code written by one of the Zig core team members: https://github.com/kubkon;\nSome livecoding sessions are transmitted in the Zig Showtime Youtube Channel: https://www.youtube.com/@ZigSHOWTIME/videos;\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want, is to practice it by solving exercises. For example, there is a famous repository in the Zig community called Ziglings18 , which contains more than 100 small exercises that you can solve. It is a repository of tiny programs written in Zig that are currently broken, and your responsibility is to fix these programs, and make them work again.\nA famous tech YouTuber known as The Primeagen also posted some videos (on YouTube) where he solves these exercises from Ziglings. The first video is named “Trying Zig Part 1”19.\nAnother great alternative, is to solve the Advent of Code exercises20. There are people that already took the time to learn and solve the exercises, and they posted their solutions on GitHub as well, so, in case you need some resource to compare while solving the exercises, you can look at these two repositories:\n\nhttps://github.com/SpexGuy/Zig-AoC-Template;\nhttps://github.com/fjebaker/advent-of-code-2022;", "crumbs": [ "1  Introducing Zig" ] From cf894390924eb48cb38015bd1219ae07d0edca41 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 9 Feb 2025 11:10:52 -0300 Subject: [PATCH 060/151] Update contributors list --- .../01-memory/execute-results/html.json | 8 +++--- .../02-debugging/execute-results/html.json | 4 +-- .../03-structs/execute-results/html.json | 4 +-- _freeze/index/execute-results/html.json | 2 +- contributors.txt | 2 ++ docs/Chapters/01-memory.html | 26 +++++++++---------- docs/Chapters/02-debugging.html | 8 +++--- docs/Chapters/03-structs.html | 13 +++++----- docs/index.html | 8 +++--- docs/search.json | 22 ++++++++-------- 10 files changed, 50 insertions(+), 47 deletions(-) diff --git a/_freeze/Chapters/01-memory/execute-results/html.json b/_freeze/Chapters/01-memory/execute-results/html.json index 29ccbc27..10d58cd7 100644 --- a/_freeze/Chapters/01-memory/execute-results/html.json +++ b/_freeze/Chapters/01-memory/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "0a086161bb0eedee4b92cc3e013bd2f2", + "hash": "fb71dc5e7458622bbc561ed2983d0bb1", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Memory and Allocators\n\n\nIn this chapter, we will talk about memory. How does Zig control memory? What\ncommon tools are used? Are there any important aspects that make memory\ndifferent/special in Zig? You will find the answers here.\n\nComputers fundamentally rely on memory to function. This memory acts as a temporary storage\nspace for the data and values generated during computations. Without memory, the core\nconcepts of \"variables\" and \"objects\" in programming languages would be impossible.\n\n\n\n\n## Memory spaces\n\nEvery object that you create in your Zig source code needs to be stored somewhere,\nin your computer's memory. Depending on where and how you define your object, Zig\nwill use a different \"memory space\", or a different\ntype of memory to store this object.\n\nEach type of memory normally serves for different purposes.\nIn Zig, there are 3 types of memory (or 3 different memory spaces) that we care about. They are:\n\n- Global data register (or the \"global data section\");\n- Stack;\n- Heap;\n\n\n### Compile-time known versus runtime known {#sec-compile-time}\n\nOne strategy that Zig uses to decide where it will store each object that you declare, is by looking\nat the value of this particular object. More specifically, by investigating if this value is\nknown at \"compile-time\" or at \"runtime\".\n\nWhen you write a program in Zig, the values of some of the objects that you write in your program are *known\nat compile time*. Meaning that, when you compile your Zig source code, during the compilation process,\nthe `zig` compiler can figure out the exact value of a particular object\nthat exists in your source code.\nKnowing the length (or the size) of each object is also important. So the length (or the size) of each object that you write in your program is,\nin some cases, *known at compile time*.\n\nThe `zig` compiler cares more about knowing the length (or the size) of a particular object\n, than to know its actual value. But, if the `zig` compiler knows the value of the object, then, it\nautomatically knows the size of this object. Because it can simply calculate the\nsize of the object by looking at the size of the value.\n\nTherefore, the priority for the `zig` compiler is to discover the size of each object in your source code.\nIf the value of the object in question is known at compile-time, then, the `zig` compiler\nautomatically knows the size/length of this object. But if the value of this object is not\nknown at compile-time, then, the size of this object is only known at compile-time if,\nand only if, the type of this object has a known fixed size.\n\nIn order for a type to have a known fixed size, this type must have data members whose size is fixed.\nIf this type includes, for example, a variable sized array in it, then, this type does not have a known\nfixed size. Because this array can have any size at runtime\n(i.e. it can be an array of 2 elements, or 50 elements, or 1 thousand elements, etc.).\n\nFor example, a string object, which internally is an array of constant u8 values (`[]const u8`)\nhas a variable size. It can be a string object with 100 or 500 characters in it. If we do not\nknow at compile-time, which exact string will be stored inside this string object, then, we cannot calculate\nthe size of this string object at compile-time. So, any type, or any struct declaration that you make, that\nincludes a string data member that does not have an explicit fixed size, makes this type, or this\nnew struct that you are declaring, a type that does not have a known fixed size at compile-time.\n\nIn contrast, if the type of this struct that you are declaring, includes a data member that is an array,\nbut this array has a known fixed size, like `[60]u8` (which declares an array of 60 `u8` values), then,\nthis type, or, this struct that you are declaring, becomes a type with a known fixed size at compile-time.\nAnd because of that, in this case, the `zig` compiler does not need to know at compile-time the exact value of\nany object of this type. Since the compiler can find the necessary size to store this object by\nlooking at the size of its type.\n\n\nLet's look at an example. In the source code below, we have two constant objects (`name` and `array`) declared.\nBecause the values of these particular objects are written down, in the source code itself (`\"Pedro\"`\nand the number sequence from 1 to 4), the `zig` compiler can easily discover the values of these constant\nobjects (`name` and `array`) during the compilation process.\nThis is what \"known at compile time\" means. It refers to any object that you have in your Zig source code\nwhose value can be identified at compile time.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn input_length(input: []const u8) usize {\n const n = input.len;\n return n;\n}\n\npub fn main() !void {\n const name = \"Pedro\";\n const array = [_]u8{1, 2, 3, 4};\n _ = name; _ = array;\n}\n```\n:::\n\n\n\n\n\nThe other side of the spectrum are objects whose values are not known at compile time.\nFunction arguments are a classic example of this. Because the value of each function\nargument depends on the value that you assign to this particular argument,\nwhen you call the function.\n\nFor example, the function `input_length()` contains an argument named `input`, which is an array of constant `u8` integers (`[]const u8`).\nIt is impossible to know the value of this particular argument at compile time. And it also is impossible to know the size/length\nof this particular argument. Because it is an array that do not have a fixed size specified explicitly in the argument type annotation.\n\nSo, we know that this `input` argument will be an array of `u8` integers. But we do not know at compile-time, its value, and neither his size.\nThis information is known only at runtime, which is the period of time when you program is executed.\nAs a consequence, the value of the expression `input.len` is also known only at runtime.\nThis is an intrinsic characteristic of any function. Just remember that the value of function arguments is usually not \"compile-time known\".\n\nHowever, as I mentioned earlier, what really matters to the compiler is to know the size of the object\nat compile-time, and not necessarily its value. So, although we don't know the value of the object `n`, which is the result of the expression\n`input.len`, at compile-time, we do know its size. Because the expression `input.len` always returns a value of type `usize`,\nand the type `usize` has a known fixed size.\n\n\n\n### Global data register\n\nThe global data register is a specific section of the executable of your Zig program, that is responsible\nfor storing any value that is known at compile time.\n\nEvery constant object whose value is known at compile time that you declare in your source code,\nis stored in the global data register. Also, every literal value that you write in your source code,\nsuch as the string `\"this is a string\"`, or the integer `10`, or a boolean value such as `true`,\nis also stored in the global data register.\n\nHonestly, you don't need to care much about this memory space. Because you can't control it,\nyou can't deliberately access it or use it for your own purposes.\nAlso, this memory space does not affect the logic of your program.\nIt simply exists in your program.\n\n\n### Stack vs Heap\n\nIf you are familiar with system's programming, or just low-level programming in general, you\nprobably have heard of the \"duel\" between Stack vs Heap. These are two different types of memory,\nor different memory spaces, which are both available in Zig.\n\nThese two types of memory don't actually duel with\neach other. This is a common mistake that beginners have, when seeing \"x vs y\" styles of\ntabloid headlines. These two types of memory are actually complementary to each other.\nSo, in almost every Zig program that you ever write, you will likely use a combination of both.\nI will describe each memory space in detail over the next sections. But for now, I just want to\nstablish the main difference between these two types of memory.\n\nIn essence, the stack memory is normally used to store values whose length is fixed and known\nat compile time. In contrast, the heap memory is a *dynamic* type of memory space, meaning that, it is\nused to store values whose length might grow during the execution (runtime) of your program [@jenny2022].\n\nLengths that grow during runtime are intrinsically associated with \"runtime known\" type of values.\nIn other words, if you have an object whose length might grow during runtime, then, the length\nof this object becomes not known at compile time. If the length is not known at compile-time,\nthe value of this object also becomes not known at compile-time.\nThese types of objects should be stored in the heap memory space, which is\na dynamic memory space, which can grow or shrink to fit the size of your objects.\n\n\n\n### Stack {#sec-stack}\n\nThe stack is a type of memory that uses the power of the *stack data structure*, hence the name. \nA \"stack\" is a type of *data structure* that uses a \"last in, first out\" (LIFO) mechanism to store the values\nyou give it to. I imagine you are familiar with this data structure.\nBut, if you are not, the [Wikipedia page](https://en.wikipedia.org/wiki/Stack_(abstract_data_type))[^wiki-stack]\n, or, the [Geeks For Geeks page](https://www.geeksforgeeks.org/stack-data-structure/)[^geek-stack] are both\nexcellent and easy resources to fully understand how this data structure works.\n\n[^wiki-stack]: \n[^geek-stack]: \n\nSo, the stack memory space is a type of memory that stores values using a stack data structure.\nIt adds and removes values from the memory by following a \"last in, first out\" (LIFO) principle.\n\nEvery time you make a function call in Zig, an amount of space in the stack is\nreserved for this particular function call [@jenny2022; @zigdocs].\nThe value of each function argument given to the function in this function call is stored in this\nstack space. Also, every local object that you declare inside the function scope is\nusually stored in this same stack space.\n\n\nLooking at the example below, the object `result` is a local object declared inside the scope of the `add()`\nfunction. Because of that, this object is stored inside the stack space reserved for the `add()` function.\nThe `r` object (which is declared outside of the `add()` function scope) is also stored in the stack.\nBut since it is declared in the \"outer\" scope, this object is stored in the\nstack space that belongs to this outer scope.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn add(x: u8, y: u8) u8 {\n const result = x + y;\n return result;\n}\n\npub fn main() !void {\n const r = add(5, 27);\n _ = r;\n}\n```\n:::\n\n\n\n\n\n\nSo, any object that you declare inside the scope of a function is always stored inside\nthe space that was reserved for that particular function in the stack memory. This\nalso counts for any object declared inside the scope of your `main()` function for example.\nAs you would expect, in this case, they\nare stored inside the stack space reserved for the `main()` function.\n\nOne very important detail about the stack memory is that **it frees itself automatically**.\nThis is very important, remember that. When objects are stored in the stack memory,\nyou don't have the work (or the responsibility) of freeing/destroying these objects.\nBecause they will be automatically destroyed once the stack space is freed at the end of the function scope.\n\nSo, once the function call returns (or ends, if you prefer to call it this way)\nthe space that was reserved in the stack is destroyed, and all of the objects that were in that space goes away with it.\nThis mechanism exists because this space, and the objects within it, are not necessary anymore,\nsince the function \"finished its business\".\nUsing the `add()` function that we exposed above as an example, it means that the object `result` is automatically\ndestroyed once the function returns.\n\n::: {.callout-important}\nLocal objects that are stored in the stack space of a function are automatically\nfreed/destroyed at the end of the function scope.\n:::\n\n\nThis same logic applies to any other special structure in Zig that have its own scope by surrounding\nit with curly braces (`{}`).\nFor loops, while loops, if else statements, etc. For example, if you declare any local\nobject in the scope of a for loop, this local object is accessible only within the scope\nof this particular for loop. Because once the scope of this for loop ends, the space in the stack\nreserved for this for loop is freed.\nThe example below demonstrates this idea.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This does not compile successfully!\nconst a = [_]u8{0, 1, 2, 3, 4};\nfor (0..a.len) |i| {\n const index = i;\n _ = index;\n}\n// Trying to use an object that was\n// declared in the for loop scope,\n// and that does not exist anymore.\nstd.debug.print(\"{d}\\n\", index);\n```\n:::\n\n\n\n\n\n\n\nOne important consequence of this mechanism is that, once the function returns, you can no longer access any memory\naddress that was inside the space in the stack reserved for this particular function. Because this space was\ndestroyed. This means that, if this local object is stored in the stack,\nyou cannot make a function that **returns a pointer to this object**.\n\nThink about that for a second. If all local objects in the stack are destroyed at the end of the function scope, why\nwould you even consider returning a pointer to one of these objects? This pointer is at best,\ninvalid, or, more likely, \"undefined\".\n\nConclusion, it is totally fine to write a function that returns the local object\nitself as result, because then, you return the value of that object as the result.\nBut, if this local object is stored in the stack, you should never write a function\nthat returns a pointer to this local object. Because the memory address pointed by the pointer\nno longer exists.\n\n\nSo, using again the `add()` function as an example, if you rewrite this function so that it\nreturns a pointer to the local object `result`, the `zig` compiler will actually compile\nyour program, with no warnings or errors. At first glance, it looks that this is good code\nthat works as expected. But this is a lie!\n\nIf you try to take a look at the value inside of the `r` object,\nor, if you try to use this `r` object in another expression\nor function call, then, you would have undefined behaviour, and major\nbugs in your program [@zigdocs, see \"Lifetime and Ownership\"[^life] and \"Undefined Behaviour\"[^undef] sections].\n\n[^life]: \n[^undef]: \n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn add(x: u8, y: u8) *const u8 {\n const result = x + y;\n return &result;\n}\n\npub fn main() !void {\n // This code compiles successfully. But it has\n // undefined behaviour. Never do this!!!\n // The `r` object is undefined!\n const r = add(5, 27); _ = r;\n}\n```\n:::\n\n\n\n\n\nThis \"invalid pointer to stack variable\" problem is very known across many programming language communities.\nIf you try to do the same thing, for example, in a C or C++ program (i.e. returning an address to\na local object stored in the stack), you would also get undefined behaviour\nin the program.\n\n::: {.callout-important}\nIf a local object in your function is stored in the stack, you should never\nreturn a pointer to this local object from the function. Because\nthis pointer will always become undefined after the function returns, since the stack space of the function\nis destroyed at the end of its scope.\n:::\n\nBut what if you really need to use this local object in some way after your function returns?\nHow can you do this? The answer is: \"in the same you would do if this was a C or C++ program. By returning\nan address to an object stored in the heap\". The heap memory has a much more flexible lifecycle,\nand allows you to get a valid pointer to a local object of a function that already returned\nfrom its scope.\n\n\n### Heap {#sec-heap}\n\nOne important limitation of the stack, is that, only objects whose length/size is known at compile-time can be\nstored in it. In contrast, the heap is a much more dynamic\n(and flexible) type of memory. It is the perfect type of memory to use\nfor objects whose size/length might grow during the execution of your program.\n\nVirtually any application that behaves as a server is a classic use case of the heap.\nA HTTP server, a SSH server, a DNS server, a LSP server, ... any type of server.\nIn summary, a server is a type of application that runs for long periods of time,\nand that serves (or \"deals with\") any incoming request that reaches this particular server.\n\nThe heap is a good choice for this type of system, mainly because the server does not know upfront\nhow many requests it will receive from users, while it is active. It could be one single request,\nor, 5 thousand requests, or, it could also be zero requests.\nThe server needs to have the ability to allocate and manage its memory according to how many requests it receives.\n\nAnother key difference between the stack and the heap, is that the heap is a type\nof memory that you, the programmer, have complete control over. This makes the heap a\nmore flexible type of memory, but it also makes it harder to work with. Because you,\nthe programmer, is responsible for managing everything related to it. Including where the memory is allocated,\nhow much memory is allocated, and where this memory is freed.\n\n> Unlike stack memory, heap memory is allocated explicitly by programmers and it won’t be deallocated until it is explicitly freed [@jenny2022].\n\nTo store an object in the heap, you, the programmer, needs to explicitly tells Zig to do so,\nby using an allocator to allocate some space in the heap. At @sec-allocators, I will present how you can use allocators to allocate memory\nin Zig.\n\n::: {.callout-important}\nEvery memory you allocate in the heap needs to be explicitly freed by you, the programmer.\n:::\n\nThe majority of allocators in Zig do allocate memory on the heap. But some exceptions to this rule are\n`ArenaAllocator()` and `FixedBufferAllocator()`. The `ArenaAllocator()` is a special\ntype of allocator that works in conjunction with a second type of allocator.\nOn the other side, the `FixedBufferAllocator()` is an allocator that works based on\nbuffer objects created on the stack. This means that the `FixedBufferAllocator()` makes\nallocations only on the stack.\n\n\n\n\n### Summary\n\nAfter discussing all of these boring details, we can quickly recap what we learned.\nIn summary, the Zig compiler will use the following rules to decide where each\nobject you declare is stored:\n\n1. every literal value (such as `\"this is string\"`, `10`, or `true`) is stored in the global data section.\n1. every constant object (`const`) whose value **is known at compile-time** is also stored in the global data section.\n1. every object (constant or not) whose length/size **is known at compile time** is stored in the stack space for the current scope.\n1. if an object is created with the method `alloc()` or `create()` of an allocator object, this object is stored in the memory space used by this particular allocator object. Most of allocators available in Zig use the heap memory, so, this object is likely stored in the heap (`FixedBufferAllocator()` is an exception to that).\n1. the heap can only be accessed through allocators. If your object was not created through the `alloc()` or `create()` methods of an allocator object, then, he is most certainly not an object stored in the heap.\n\n\n## Stack overflows {#sec-stack-overflow}\n\nAllocating memory on the stack is generally faster than allocating it on the heap.\nBut this better performance comes with many restrictions. We have already discussed\nmany of these restrictions of the stack at @sec-stack. But there is one more important\nlimitation that I want to talk about, which is the size of the stack itself.\n\nThe stack is limited in size. This size varies from computer to computer, and it depends on\na lot of things (the computer architecture, the operating system, etc.). Nevertheless, this size is usually\nnot that big. This is why we normally use the stack to store only temporary and small objects in memory.\n\nIn essence, if you try to make an allocation on the stack, that is so big that exceeds the stack size limit,\na *stack overflow* happens, and your program just crashes as a result of that. In other words, a stack overflow happens when\nyou attempt to use more space than is available on the stack.\n\nThis type of problem is very similar to a *buffer overflow*, i.e. you are trying to use more space\nthan is available in the \"buffer object\". However, a stack overflow always cause your program to crash,\nwhile a buffer overflow not always cause your program to crash (although it often does).\n\nYou can see an example of a stack overflow in the example below. We are trying to allocate a very big array of `u64` values\non the stack. You can see below that this program does not run succesfully, because it crashed\nwith a \"segmentation fault\" error message.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar very_big_alloc: [1000 * 1000 * 24]u64 = undefined;\n@memset(very_big_alloc[0..], 0);\n```\n:::\n\n\n\n\n\n```\nSegmentation fault (core dumped)\n```\n\nThis segmentation fault error is a result of the stack overflow that was caused by the big\nmemory allocation made on the stack, to store the `very_big_alloc` object.\nThis is why very big objects are usually stored on the heap, instead of the stack.\n\n\n\n## Allocators {#sec-allocators}\n\nOne key aspect about Zig, is that there are \"no hidden-memory allocations\" in Zig.\nWhat that really means, is that \"no allocations happen behind your back in the standard library\" [@zigguide].\n\nThis is a known problem, especially in C++. Because in C++, there are some operators that do allocate\nmemory behind the scene, and there is no way for you to know that, until you actually read the\nsource code of these operators, and find the memory allocation calls.\nMany programmers find this behaviour annoying and hard to keep track of.\n\nBut, in Zig, if a function, an operator, or anything from the standard library\nneeds to allocate some memory during its execution, then, this function/operator needs to receive (as input) an allocator\nprovided by the user, to actually be able to allocate the memory it needs.\n\nThis creates a clear distinction between functions that \"do not\" from those that \"actually do\"\nallocate memory. Just look at the arguments of this function.\nIf a function, or operator, has an allocator object as one of its inputs/arguments, then, you know for\nsure that this function/operator will allocate some memory during its execution.\n\nAn example is the `allocPrint()` function from the Zig Standard Library. With this function, you can\nwrite a new string using format specifiers. So, this function is, for example, very similar to the function `sprintf()` in C.\nIn order to write such new string, the `allocPrint()` function needs to allocate some memory to store the\noutput string.\n\nThat is why, the first argument of this function is an allocator object that you, the user/programmer, gives\nas input to the function. In the example below, I am using the `GeneralPurposeAllocator()` as my allocator\nobject. But I could easily use any other type of allocator object from the Zig Standard Library.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nconst name = \"Pedro\";\nconst output = try std.fmt.allocPrint(\n allocator,\n \"Hello {s}!!!\",\n .{name}\n);\ntry stdout.print(\"{s}\\n\", .{output});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello Pedro!!!\n```\n\n\n:::\n:::\n\n\n\n\n\n\nYou get a lot of control over where and how much memory this function can allocate.\nBecause it is you, the user/programmer, that provides the allocator for the function to use.\nThis makes \"total control\" over memory management easier to achieve in Zig.\n\n### What are allocators?\n\nAllocators in Zig are objects that you can use to allocate memory for your program.\nThey are similar to the memory allocating functions in C, like `malloc()` and `calloc()`.\nSo, if you need to use more memory than you initially have, during the execution of your program, you can simply ask\nfor more memory by using an allocator object.\n\nZig offers different types of allocators, and they are usually available through the `std.heap` module of\nthe standard library. Thus, just import the Zig Standard Library into your Zig module (with `@import(\"std\")`), and you can start\nusing these allocators in your code.\n\nFurthermore, every allocator object is built on top of the `Allocator` interface in Zig.\nThis means that, every allocator object you find in Zig must have the methods `alloc()`,\n`create()`, `free()` and `destroy()`. So, you can change the type of allocator you are using,\nbut you don't need to change the function calls to the methods that do the memory allocation\n(and the free memory operations) for your program.\n\n### Why you need an allocator?\n\nAs we described at @sec-stack, everytime you make a function call in Zig,\na space in the stack is reserved for this function call. But the stack\nhas a key limitation which is: every object stored in the stack have a\nknown fixed length.\n\nBut in reality, there are two very common instances where this \"fixed length limitation\" of the stack is a deal braker:\n\n1. the objects that you create inside your function might grow in size during the execution of the function.\n1. sometimes, it is impossible to know upfront how many inputs you will receive, or how big this input will be.\n\nAlso, there is another instance where you might want to use an allocator, which is when you want to write a function that returns a pointer\nto a local object. As I described at @sec-stack, you cannot do that if this local object is stored in the\nstack. However, if this object is stored in the heap, then, you can return a pointer to this object at the\nend of the function. Because you (the programmer) control the lifetime of any heap memory that you allocate. You decide\nwhen this memory gets destroyed/freed.\n\nThese are common situations where the stack is not good for.\nThat is why you need a different memory management strategy to\nstore these objects inside your function. You need to use\na memory type that can grow together with your objects, or that you\ncan control the lifetime of this memory.\nThe heap fits this description.\n\nAllocating memory on the heap is commonly known as dynamic memory management. As the objects you create grow in size\nduring the execution of your program, you grow the amount of memory\nyou have by allocating more memory in the heap to store these objects. \nAnd you do that in Zig, by using an allocator object.\n\n\n### The different types of allocators\n\n\nAt the moment of the writing of this book, in Zig, we have 6 different\nallocators available in the standard library:\n\n- `GeneralPurposeAllocator()`.\n- `page_allocator()`.\n- `FixedBufferAllocator()` and `ThreadSafeFixedBufferAllocator()`.\n- `ArenaAllocator()`.\n- `c_allocator()` (requires you to link to libc).\n\n\nEach allocator has its own perks and limitations. All allocators, except `FixedBufferAllocator()` and `ArenaAllocator()`,\nare allocators that use the heap memory. So any memory that you allocate with\nthese allocators, will be placed in the heap.\n\n### General-purpose allocators\n\nThe `GeneralPurposeAllocator()`, as the name suggests, is a \"general purpose\" allocator. You can use it for every type\nof task. In the example below, I'm allocating enough space to store a single integer in the object `some_number`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const some_number = try allocator.create(u32);\n defer allocator.destroy(some_number);\n\n some_number.* = @as(u32, 45);\n}\n```\n:::\n\n\n\n\n\n\nWhile useful, you might want to use the `c_allocator()`, which is a alias to the C standard allocator `malloc()`. So, yes, you can use\n`malloc()` in Zig if you want to. Just use the `c_allocator()` from the Zig standard library. However,\nif you do use `c_allocator()`, you must link to Libc when compiling your source code with the\n`zig` compiler, by including the flag `-lc` in your compilation process.\nIf you do not link your source code to Libc, Zig will not be able to find the\n`malloc()` implementation in your system.\n\n### Page allocator\n\nThe `page_allocator()` is an allocator that allocates full pages of memory in the heap. In other words,\nevery time you allocate memory with `page_allocator()`, a full page of memory in the heap is allocated,\ninstead of just a small piece of it.\n\nThe size of this page depends on the system you are using.\nMost systems use a page size of 4KB in the heap, so, that is the amount of memory that is normally\nallocated in each call by `page_allocator()`. That is why, `page_allocator()` is considered a\nfast, but also \"wasteful\" allocator in Zig. Because it allocates a big amount of memory\nin each call, and you most likely will not need that much memory in your program.\n\n### Buffer allocators\n\nThe `FixedBufferAllocator()` and `ThreadSafeFixedBufferAllocator()` are allocator objects that\nwork with a fixed sized buffer object at the back. In other words, they use a fixed sized buffer\nobject as the basis for the memory. When you ask these allocator objects to allocate some memory for you,\nthey are essentially reserving some amount of space inside this fixed sized buffer object for you to use.\n\nThis means that, in order to use these allocators, you must first create a buffer object in your code,\nand then, give this buffer object as an input to these allocators.\n\nThis also means that, these allocator objects can allocate memory both in the stack or in the heap.\nEverything depends on where the buffer object that you provide lives. If this buffer object lives\nin the stack, then, the memory allocated is \"stack-based\". But if it lives on the heap, then,\nthe memory allocated is \"heap-based\".\n\n\nIn the example below, I'm creating a `buffer` object on the stack that is 10 elements long.\nNotice that I give this `buffer` object to the `FixedBufferAllocator()` constructor.\nNow, because this `buffer` object is 10 elements long, this means that I am limited to this space.\nI cannot allocate more than 10 elements with this allocator object. If I try to\nallocate more than that, the `alloc()` method will return an `OutOfMemory` error value.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar buffer: [10]u8 = undefined;\nfor (0..buffer.len) |i| {\n buffer[i] = 0; // Initialize to zero\n}\n\nvar fba = std.heap.FixedBufferAllocator.init(&buffer);\nconst allocator = fba.allocator();\nconst input = try allocator.alloc(u8, 5);\ndefer allocator.free(input);\n```\n:::\n\n\n\n\n\nRemember, the memory allocated by these allocator objects can be either from\nthe stack, or, from the heap. It all depends on where the buffer object that you provide lives.\nIn the above example, the `buffer` object lives in the stack, and, therefore, the memory allocated\nis based in the stack. But what if it was based on the heap?\n\nAs we described at @sec-stack-overflow, one of the main reasons why you would use the heap,\ninstead of the stack, is to allocate huge amounts of space to store very big objects.\nThus, let's suppose you wanted to use a very big buffer object as the basis for your\nallocator objects. You would have to allocate this very big buffer object on the heap.\nThe example below demonstrates this case.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst heap = std.heap.page_allocator;\nconst memory_buffer = try heap.alloc(\n u8, 100 * 1024 * 1024 // 100 MB memory\n);\ndefer heap.free(memory_buffer);\nvar fba = std.heap.FixedBufferAllocator.init(\n memory_buffer\n);\nconst allocator = fba.allocator();\n\nconst input = try allocator.alloc(u8, 1000);\ndefer allocator.free(input);\n```\n:::\n\n\n\n\n\n\n\n### Arena allocator {#sec-arena-allocator}\n\nThe `ArenaAllocator()` is an allocator object that takes a child allocator as input. The idea behind the `ArenaAllocator()` in Zig\nis similar to the concept of \"arenas\" in the programming language Go[^go-arena]. It is an allocator object that allows you\nto allocate memory as many times you want, but free all memory only once.\nIn other words, if you have, for example, called 5 times the method `alloc()` of an `ArenaAllocator()` object, you can\nfree all the memory you allocated over these 5 calls at once, by simply calling the `deinit()` method of the same `ArenaAllocator()` object.\n\n[^go-arena]: \n\nIf you give, for example, a `GeneralPurposeAllocator()` object as input to the `ArenaAllocator()` constructor, like in the example below, then, the allocations\nyou perform with `alloc()` will actually be made with the underlying object `GeneralPurposeAllocator()` that was passed.\nSo, with an arena allocator, any new memory you ask for is allocated by the child allocator. The only thing that an arena allocator\nreally does is help you to free all the memory you allocated multiple times with just a single command. In the example\nbelow, I called `alloc()` 3 times. So, if I did not use an arena allocator, then, I would need to call\n`free()` 3 times to free all the allocated memory.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nvar aa = std.heap.ArenaAllocator.init(gpa.allocator());\ndefer aa.deinit();\nconst allocator = aa.allocator();\n\nconst in1 = try allocator.alloc(u8, 5);\nconst in2 = try allocator.alloc(u8, 10);\nconst in3 = try allocator.alloc(u8, 15);\n_ = in1; _ = in2; _ = in3;\n```\n:::\n\n\n\n\n\n\n\n### The `alloc()` and `free()` methods\n\nIn the code example below, we are accessing the `stdin`, which is\nthe standard input channel, to receive an input from the\nuser. We read the input given by the user with the `readUntilDelimiterOrEof()`\nmethod.\n\nNow, after reading the input of the user, we need to store this input somewhere in\nour program. That is why I use an allocator in this example. I use it to allocate some\namount of memory to store this input given by the user. More specifically, the method `alloc()`\nof the allocator object is used to allocate an array capable of storing 50 `u8` values.\n\nNotice that this `alloc()` method receives two inputs. The first one, is a type.\nThis defines what type of values the allocated array will store. In the example\nbelow, we are allocating an array of unsigned 8-bit integers (`u8`). But\nyou can create an array to store any type of value you want. Next, on the second argument, we\ndefine the size of the allocated array, by specifying how many elements\nthis array will contain. In the case below, we are allocating an array of 50 elements.\n\nAt @sec-zig-strings we described that strings in Zig are simply arrays of characters.\nEach character is represented by a `u8` value. So, this means that the array that\nwas allocated in the object `input` is capable of storing a string that is\n50-characters long.\n\nSo, in essence, the expression `var input: [50]u8 = undefined` would create\nan array for 50 `u8` values in the stack of the current scope. But, you\ncan allocate the same array in the heap by using the expression `var input = try allocator.alloc(u8, 50)`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdin = std.io.getStdIn();\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var input = try allocator.alloc(u8, 50);\n defer allocator.free(input);\n for (0..input.len) |i| {\n input[i] = 0; // initialize all fields to zero.\n }\n // read user input\n const input_reader = stdin.reader();\n _ = try input_reader.readUntilDelimiterOrEof(\n input,\n '\\n'\n );\n std.debug.print(\"{s}\\n\", .{input});\n}\n```\n:::\n\n\n\n\n\nAlso, notice that in this example, we use the `defer` keyword (which I described at @sec-defer) to run a small\npiece of code at the end of the current scope, which is the expression `allocator.free(input)`.\nWhen you execute this expression, the allocator will free the memory that it allocated\nfor the `input` object.\n\nWe have talked about this at @sec-heap. You **should always** explicitly free any memory that you allocate\nusing an allocator! You do that by using the `free()` method of the same allocator object you\nused to allocate this memory. The `defer` keyword is used in this example only to help us execute\nthis free operation at the end of the current scope.\n\n\n### The `create()` and `destroy()` methods\n\nWith the `alloc()` and `free()` methods, you can allocate memory to store multiple elements\nat once. In other words, with these methods, we always allocate an array to store multiple elements at once.\nBut what if you need enough space to store just a single item? Should you\nallocate an array of a single element through `alloc()`?\n\nThe answer is no! In this case,\nyou should use the `create()` method of the allocator object.\nEvery allocator object offers the `create()` and `destroy()` methods,\nwhich are used to allocate and free memory for a single item, respectively.\n\nSo, in essence, if you want to allocate memory to store an array of elements, you\nshould use `alloc()` and `free()`. But if you need to store just a single item,\nthen, the `create()` and `destroy()` methods are ideal for you.\n\nIn the example below, I'm defining a struct to represent an user of some sort.\nIt could be an user for a game, or a software to manage resources, it doesn't mater.\nNotice that I use the `create()` method this time, to store a single `User` object\nin the program. Also notice that I use the `destroy()` method to free the memory\nused by this object at the end of the scope.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst User = struct {\n id: usize,\n name: []const u8,\n\n pub fn init(id: usize, name: []const u8) User {\n return .{ .id = id, .name = name };\n }\n};\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const user = try allocator.create(User);\n defer allocator.destroy(user);\n\n user.* = User.init(0, \"Pedro\");\n}\n```\n:::\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Memory and Allocators\n\n\nIn this chapter, we will talk about memory. How does Zig control memory? What\ncommon tools are used? Are there any important aspects that make memory\ndifferent/special in Zig? You will find the answers here.\n\nComputers fundamentally rely on memory to function. This memory acts as a temporary storage\nspace for the data and values generated during computations. Without memory, the core\nconcepts of \"variables\" and \"objects\" in programming languages would be impossible.\n\n\n\n\n## Memory spaces\n\nEvery object that you create in your Zig source code needs to be stored somewhere,\nin your computer's memory. Depending on where and how you define your object, Zig\nwill use a different \"memory space\", or a different\ntype of memory to store this object.\n\nEach type of memory normally serves for different purposes.\nIn Zig, there are 3 types of memory (or 3 different memory spaces) that we care about. They are:\n\n- Global data register (or the \"global data section\");\n- Stack;\n- Heap;\n\n\n### Compile-time known versus runtime known {#sec-compile-time}\n\nOne strategy that Zig uses to decide where it will store each object that you declare, is by looking\nat the value of this particular object. More specifically, by investigating if this value is\nknown at \"compile-time\" or at \"runtime\".\n\nWhen you write a program in Zig, the values of some of the objects that you write in your program are *known\nat compile time*. Meaning that, when you compile your Zig source code, during the compilation process,\nthe `zig` compiler can figure out the exact value of a particular object\nthat exists in your source code.\nKnowing the length (or the size) of each object is also important. So the length (or the size) of each object that you write in your program is,\nin some cases, *known at compile time*.\n\nThe `zig` compiler cares more about knowing the length (or the size) of a particular object\n, than to know its actual value. But, if the `zig` compiler knows the value of the object, then, it\nautomatically knows the size of this object. Because it can simply calculate the\nsize of the object by looking at the size of the value.\n\nTherefore, the priority for the `zig` compiler is to discover the size of each object in your source code.\nIf the value of the object in question is known at compile-time, then, the `zig` compiler\nautomatically knows the size/length of this object. But if the value of this object is not\nknown at compile-time, then, the size of this object is only known at compile-time if,\nand only if, the type of this object has a known fixed size.\n\nIn order for a type to have a known fixed size, this type must have data members whose size is fixed.\nIf this type includes, for example, a variable sized array in it, then, this type does not have a known\nfixed size. Because this array can have any size at runtime\n(i.e. it can be an array of 2 elements, or 50 elements, or 1 thousand elements, etc.).\n\nFor example, a string object, which internally is an array of constant u8 values (`[]const u8`)\nhas a variable size. It can be a string object with 100 or 500 characters in it. If we do not\nknow at compile-time, which exact string will be stored inside this string object, then, we cannot calculate\nthe size of this string object at compile-time. So, any type, or any struct declaration that you make, that\nincludes a string data member that does not have an explicit fixed size, makes this type, or this\nnew struct that you are declaring, a type that does not have a known fixed size at compile-time.\n\nIn contrast, if the type of this struct that you are declaring, includes a data member that is an array,\nbut this array has a known fixed size, like `[60]u8` (which declares an array of 60 `u8` values), then,\nthis type, or, this struct that you are declaring, becomes a type with a known fixed size at compile-time.\nAnd because of that, in this case, the `zig` compiler does not need to know at compile-time the exact value of\nany object of this type. Since the compiler can find the necessary size to store this object by\nlooking at the size of its type.\n\n\nLet's look at an example. In the source code below, we have two constant objects (`name` and `array`) declared.\nBecause the values of these particular objects are written down, in the source code itself (`\"Pedro\"`\nand the number sequence from 1 to 4), the `zig` compiler can easily discover the values of these constant\nobjects (`name` and `array`) during the compilation process.\nThis is what \"known at compile time\" means. It refers to any object that you have in your Zig source code\nwhose value can be identified at compile time.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn input_length(input: []const u8) usize {\n const n = input.len;\n return n;\n}\n\npub fn main() !void {\n const name = \"Pedro\";\n const array = [_]u8{1, 2, 3, 4};\n _ = name; _ = array;\n}\n```\n:::\n\n\n\n\nThe other side of the spectrum are objects whose values are not known at compile time.\nFunction arguments are a classic example of this. Because the value of each function\nargument depends on the value that you assign to this particular argument,\nwhen you call the function.\n\nFor example, the function `input_length()` contains an argument named `input`, which is an array of constant `u8` integers (`[]const u8`).\nIt is impossible to know the value of this particular argument at compile time. And it also is impossible to know the size/length\nof this particular argument. Because it is an array that do not have a fixed size specified explicitly in the argument type annotation.\n\nSo, we know that this `input` argument will be an array of `u8` integers. But we do not know at compile-time, its value, and neither its size.\nThis information is known only at runtime, which is the period of time when you program is executed.\nAs a consequence, the value of the expression `input.len` is also known only at runtime.\nThis is an intrinsic characteristic of any function. Just remember that the value of function arguments is usually not \"compile-time known\".\n\nHowever, as I mentioned earlier, what really matters to the compiler is to know the size of the object\nat compile-time, and not necessarily its value. So, although we don't know the value of the object `n`, which is the result of the expression\n`input.len`, at compile-time, we do know its size. Because the expression `input.len` always returns a value of type `usize`,\nand the type `usize` has a known fixed size.\n\n\n\n### Global data register\n\nThe global data register is a specific section of the executable of your Zig program, that is responsible\nfor storing any value that is known at compile time.\n\nEvery constant object whose value is known at compile time that you declare in your source code,\nis stored in the global data register. Also, every literal value that you write in your source code,\nsuch as the string `\"this is a string\"`, or the integer `10`, or a boolean value such as `true`,\nis also stored in the global data register.\n\nHonestly, you don't need to care much about this memory space. Because you can't control it,\nyou can't deliberately access it or use it for your own purposes.\nAlso, this memory space does not affect the logic of your program.\nIt simply exists in your program.\n\n\n### Stack vs Heap\n\nIf you are familiar with systems programming, or just low-level programming in general, you\nprobably have heard of the \"duel\" between Stack vs Heap. These are two different types of memory,\nor different memory spaces, which are both available in Zig.\n\nThese two types of memory don't actually duel with\neach other. This is a common mistake that beginners have, when seeing \"x vs y\" styles of\ntabloid headlines. These two types of memory are actually complementary to each other.\nSo, in almost every Zig program that you ever write, you will likely use a combination of both.\nI will describe each memory space in detail over the next sections. But for now, I just want to\nstablish the main difference between these two types of memory.\n\nIn essence, the stack memory is normally used to store values whose length is fixed and known\nat compile time. In contrast, the heap memory is a *dynamic* type of memory space, meaning that, it is\nused to store values whose length might grow during the execution (runtime) of your program [@jenny2022].\n\nLengths that grow during runtime are intrinsically associated with \"runtime known\" type of values.\nIn other words, if you have an object whose length might grow during runtime, then, the length\nof this object becomes not known at compile time. If the length is not known at compile-time,\nthe value of this object also becomes not known at compile-time.\nThese types of objects should be stored in the heap memory space, which is\na dynamic memory space, which can grow or shrink to fit the size of your objects.\n\n\n\n### Stack {#sec-stack}\n\nThe stack is a type of memory that uses the power of the *stack data structure*, hence the name. \nA \"stack\" is a type of *data structure* that uses a \"last in, first out\" (LIFO) mechanism to store the values\nyou give it to. I imagine you are familiar with this data structure.\nBut, if you are not, the [Wikipedia page](https://en.wikipedia.org/wiki/Stack_(abstract_data_type))[^wiki-stack]\n, or, the [Geeks For Geeks page](https://www.geeksforgeeks.org/stack-data-structure/)[^geek-stack] are both\nexcellent and easy resources to fully understand how this data structure works.\n\n[^wiki-stack]: \n[^geek-stack]: \n\nSo, the stack memory space is a type of memory that stores values using a stack data structure.\nIt adds and removes values from the memory by following a \"last in, first out\" (LIFO) principle.\n\nEvery time you make a function call in Zig, an amount of space in the stack is\nreserved for this particular function call [@jenny2022; @zigdocs].\nThe value of each function argument given to the function in this function call is stored in this\nstack space. Also, every local object that you declare inside the function scope is\nusually stored in this same stack space.\n\n\nLooking at the example below, the object `result` is a local object declared inside the scope of the `add()`\nfunction. Because of that, this object is stored inside the stack space reserved for the `add()` function.\nThe `r` object (which is declared outside of the `add()` function scope) is also stored in the stack.\nBut since it is declared in the \"outer\" scope, this object is stored in the\nstack space that belongs to this outer scope.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn add(x: u8, y: u8) u8 {\n const result = x + y;\n return result;\n}\n\npub fn main() !void {\n const r = add(5, 27);\n _ = r;\n}\n```\n:::\n\n\n\n\n\nSo, any object that you declare inside the scope of a function is always stored inside\nthe space that was reserved for that particular function in the stack memory. This\nalso counts for any object declared inside the scope of your `main()` function for example.\nAs you would expect, in this case, they\nare stored inside the stack space reserved for the `main()` function.\n\nOne very important detail about the stack memory is that **it frees itself automatically**.\nThis is very important, remember that. When objects are stored in the stack memory,\nyou don't have the work (or the responsibility) of freeing/destroying these objects.\nBecause they will be automatically destroyed once the stack space is freed at the end of the function scope.\n\nSo, once the function call returns (or ends, if you prefer to call it this way)\nthe space that was reserved in the stack is destroyed, and all of the objects that were in that space goes away with it.\nThis mechanism exists because this space, and the objects within it, are not necessary anymore,\nsince the function \"finished its business\".\nUsing the `add()` function that we exposed above as an example, it means that the object `result` is automatically\ndestroyed once the function returns.\n\n::: {.callout-important}\nLocal objects that are stored in the stack space of a function are automatically\nfreed/destroyed at the end of the function scope.\n:::\n\n\nThis same logic applies to any other special structure in Zig that has its own scope by surrounding\nit with curly braces (`{}`).\nFor loops, while loops, if else statements, etc. For example, if you declare any local\nobject in the scope of a for loop, this local object is accessible only within the scope\nof this particular for loop. Because once the scope of this for loop ends, the space in the stack\nreserved for this for loop is freed.\nThe example below demonstrates this idea.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This does not compile successfully!\nconst a = [_]u8{0, 1, 2, 3, 4};\nfor (0..a.len) |i| {\n const index = i;\n _ = index;\n}\n// Trying to use an object that was\n// declared in the for loop scope,\n// and that does not exist anymore.\nstd.debug.print(\"{d}\\n\", index);\n```\n:::\n\n\n\n\n\n\nOne important consequence of this mechanism is that, once the function returns, you can no longer access any memory\naddress that was inside the space in the stack reserved for this particular function. Because this space was\ndestroyed. This means that, if this local object is stored in the stack,\nyou cannot make a function that **returns a pointer to this object**.\n\nThink about that for a second. If all local objects in the stack are destroyed at the end of the function scope, why\nwould you even consider returning a pointer to one of these objects? This pointer is at best,\ninvalid, or, more likely, \"undefined\".\n\nConclusion, it is totally fine to write a function that returns the local object\nitself as result, because then, you return the value of that object as the result.\nBut, if this local object is stored in the stack, you should never write a function\nthat returns a pointer to this local object. Because the memory address pointed by the pointer\nno longer exists.\n\n\nSo, using again the `add()` function as an example, if you rewrite this function so that it\nreturns a pointer to the local object `result`, the `zig` compiler will actually compile\nyour program, with no warnings or errors. At first glance, it looks that this is good code\nthat works as expected. But this is a lie!\n\nIf you try to take a look at the value inside of the `r` object,\nor, if you try to use this `r` object in another expression\nor function call, then, you would have undefined behaviour, and major\nbugs in your program [@zigdocs, see \"Lifetime and Ownership\"[^life] and \"Undefined Behaviour\"[^undef] sections].\n\n[^life]: \n[^undef]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn add(x: u8, y: u8) *const u8 {\n const result = x + y;\n return &result;\n}\n\npub fn main() !void {\n // This code compiles successfully. But it has\n // undefined behaviour. Never do this!!!\n // The `r` object is undefined!\n const r = add(5, 27); _ = r;\n}\n```\n:::\n\n\n\n\nThis \"invalid pointer to stack variable\" problem is well known across many programming language communities.\nIf you try to do the same thing, for example, in a C or C++ program (i.e. returning an address to\na local object stored in the stack), you would also get undefined behaviour\nin the program.\n\n::: {.callout-important}\nIf a local object in your function is stored in the stack, you should never\nreturn a pointer to this local object from the function. Because\nthis pointer will always become undefined after the function returns, since the stack space of the function\nis destroyed at the end of its scope.\n:::\n\nBut what if you really need to use this local object in some way after your function returns?\nHow can you do this? The answer is: \"in the same way you would do if this were a C or C++ program. By returning\nan address to an object stored in the heap\". The heap memory has a much more flexible lifecycle,\nand allows you to get a valid pointer to a local object of a function that already returned\nfrom its scope.\n\n\n### Heap {#sec-heap}\n\nOne important limitation of the stack, is that, only objects whose length/size is known at compile-time can be\nstored in it. In contrast, the heap is a much more dynamic\n(and flexible) type of memory. It is the perfect type of memory to use\nfor objects whose size/length might grow during the execution of your program.\n\nVirtually any application that behaves as a server is a classic use case of the heap.\nA HTTP server, a SSH server, a DNS server, a LSP server, ... any type of server.\nIn summary, a server is a type of application that runs for long periods of time,\nand that serves (or \"deals with\") any incoming request that reaches this particular server.\n\nThe heap is a good choice for this type of system, mainly because the server does not know upfront\nhow many requests it will receive from users, while it is active. It could be a single request,\n5 thousand requests, or even zero requests.\nThe server needs to have the ability to allocate and manage its memory according to how many requests it receives.\n\nAnother key difference between the stack and the heap, is that the heap is a type\nof memory that you, the programmer, have complete control over. This makes the heap a\nmore flexible type of memory, but it also makes it harder to work with. Because you,\nthe programmer, is responsible for managing everything related to it. Including where the memory is allocated,\nhow much memory is allocated, and where this memory is freed.\n\n> Unlike stack memory, heap memory is allocated explicitly by programmers and it won’t be deallocated until it is explicitly freed [@jenny2022].\n\nTo store an object in the heap, you, the programmer, needs to explicitly tells Zig to do so,\nby using an allocator to allocate some space in the heap. At @sec-allocators, I will present how you can use allocators to allocate memory\nin Zig.\n\n::: {.callout-important}\nEvery memory you allocate in the heap needs to be explicitly freed by you, the programmer.\n:::\n\nThe majority of allocators in Zig do allocate memory on the heap. But some exceptions to this rule are\n`ArenaAllocator()` and `FixedBufferAllocator()`. The `ArenaAllocator()` is a special\ntype of allocator that works in conjunction with a second type of allocator.\nOn the other side, the `FixedBufferAllocator()` is an allocator that works based on\nbuffer objects created on the stack. This means that the `FixedBufferAllocator()` makes\nallocations only on the stack.\n\n\n\n\n### Summary\n\nAfter discussing all of these boring details, we can quickly recap what we learned.\nIn summary, the Zig compiler will use the following rules to decide where each\nobject you declare is stored:\n\n1. every literal value (such as `\"this is string\"`, `10`, or `true`) is stored in the global data section.\n1. every constant object (`const`) whose value **is known at compile-time** is also stored in the global data section.\n1. every object (constant or not) whose length/size **is known at compile time** is stored in the stack space for the current scope.\n1. if an object is created with the method `alloc()` or `create()` of an allocator object, this object is stored in the memory space used by this particular allocator object. Most of allocators available in Zig use the heap memory, so, this object is likely stored in the heap (`FixedBufferAllocator()` is an exception to that).\n1. the heap can only be accessed through allocators. If your object was not created through the `alloc()` or `create()` methods of an allocator object, then, it is most certainly not an object stored in the heap.\n\n\n## Stack overflows {#sec-stack-overflow}\n\nAllocating memory on the stack is generally faster than allocating it on the heap.\nBut this better performance comes with many restrictions. We have already discussed\nmany of these restrictions of the stack at @sec-stack. But there is one more important\nlimitation that I want to talk about, which is the size of the stack itself.\n\nThe stack is limited in size. This size varies from computer to computer, and it depends on\na lot of things (the computer architecture, the operating system, etc.). Nevertheless, this size is usually\nnot that big. This is why we normally use the stack to store only temporary and small objects in memory.\n\nIn essence, if you try to make an allocation on the stack, that is so big that exceeds the stack size limit,\na *stack overflow* happens, and your program just crashes as a result of that. In other words, a stack overflow happens when\nyou attempt to use more space than is available on the stack.\n\nThis type of problem is very similar to a *buffer overflow*, i.e. you are trying to use more space\nthan is available in the \"buffer object\". However, a stack overflow always causes your program to crash,\nwhile a buffer overflow does not always cause your program to crash (although it often does).\n\nYou can see an example of a stack overflow in the example below. We are trying to allocate a very big array of `u64` values\non the stack. You can see below that this program does not run successfully, because it crashed\nwith a \"segmentation fault\" error message.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar very_big_alloc: [1000 * 1000 * 24]u64 = undefined;\n@memset(very_big_alloc[0..], 0);\n```\n:::\n\n\n\n\n```\nSegmentation fault (core dumped)\n```\n\nThis segmentation fault error is a result of the stack overflow that was caused by the big\nmemory allocation made on the stack, to store the `very_big_alloc` object.\nThis is why very big objects are usually stored on the heap, instead of the stack.\n\n\n\n## Allocators {#sec-allocators}\n\nOne key aspect about Zig, is that there are \"no hidden-memory allocations\" in Zig.\nWhat that really means, is that \"no allocations happen behind your back in the standard library\" [@zigguide].\n\nThis is a known problem, especially in C++. Because in C++, there are some operators that do allocate\nmemory behind the scene, and there is no way for you to know that, until you actually read the\nsource code of these operators, and find the memory allocation calls.\nMany programmers find this behaviour annoying and hard to keep track of.\n\nBut, in Zig, if a function, an operator, or anything from the standard library\nneeds to allocate some memory during its execution, then, this function/operator needs to receive (as input) an allocator\nprovided by the user, to actually be able to allocate the memory it needs.\n\nThis creates a clear distinction between functions that \"do not\" from those that \"actually do\"\nallocate memory. Just look at the arguments of this function.\nIf a function, or operator, has an allocator object as one of its inputs/arguments, then, you know for\nsure that this function/operator will allocate some memory during its execution.\n\nAn example is the `allocPrint()` function from the Zig Standard Library. With this function, you can\nwrite a new string using format specifiers. So, this function is, for example, very similar to the function `sprintf()` in C.\nIn order to write such a new string, the `allocPrint()` function needs to allocate some memory to store the\noutput string.\n\nThat is why, the first argument of this function is an allocator object that you, the user/programmer, gives\nas input to the function. In the example below, I am using the `GeneralPurposeAllocator()` as my allocator\nobject. But I could easily use any other type of allocator object from the Zig Standard Library.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nconst name = \"Pedro\";\nconst output = try std.fmt.allocPrint(\n allocator,\n \"Hello {s}!!!\",\n .{name}\n);\ntry stdout.print(\"{s}\\n\", .{output});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello Pedro!!!\n```\n\n\n:::\n:::\n\n\n\n\n\nYou get a lot of control over where and how much memory this function can allocate.\nBecause it is you, the user/programmer, that provides the allocator for the function to use.\nThis makes \"total control\" over memory management easier to achieve in Zig.\n\n### What are allocators?\n\nAllocators in Zig are objects that you can use to allocate memory for your program.\nThey are similar to the memory allocating functions in C, like `malloc()` and `calloc()`.\nSo, if you need to use more memory than you initially have, during the execution of your program, you can simply ask\nfor more memory by using an allocator object.\n\nZig offers different types of allocators, and they are usually available through the `std.heap` module of\nthe standard library. Thus, just import the Zig Standard Library into your Zig module (with `@import(\"std\")`), and you can start\nusing these allocators in your code.\n\nFurthermore, every allocator object is built on top of the `Allocator` interface in Zig.\nThis means that, every allocator object you find in Zig must have the methods `alloc()`,\n`create()`, `free()` and `destroy()`. So, you can change the type of allocator you are using,\nbut you don't need to change the function calls to the methods that do the memory allocation\n(and the free memory operations) for your program.\n\n### Why you need an allocator?\n\nAs we described at @sec-stack, everytime you make a function call in Zig,\na space in the stack is reserved for this function call. But the stack\nhas a key limitation which is: every object stored in the stack has a\nknown fixed length.\n\nBut in reality, there are two very common instances where this \"fixed length limitation\" of the stack is a deal braker:\n\n1. the objects that you create inside your function might grow in size during the execution of the function.\n1. sometimes, it is impossible to know upfront how many inputs you will receive, or how big this input will be.\n\nAlso, there is another instance where you might want to use an allocator, which is when you want to write a function that returns a pointer\nto a local object. As I described at @sec-stack, you cannot do that if this local object is stored in the\nstack. However, if this object is stored in the heap, then, you can return a pointer to this object at the\nend of the function. Because you (the programmer) control the lifetime of any heap memory that you allocate. You decide\nwhen this memory gets destroyed/freed.\n\nThese are common situations for which the stack is not good. \nThat is why you need a different memory management strategy to\nstore these objects inside your function. You need to use\na memory type that can grow together with your objects, or that you\ncan control the lifetime of this memory.\nThe heap fits this description.\n\nAllocating memory on the heap is commonly known as dynamic memory management. As the objects you create grow in size\nduring the execution of your program, you grow the amount of memory\nyou have by allocating more memory in the heap to store these objects. \nAnd you do that in Zig, by using an allocator object.\n\n\n### The different types of allocators\n\n\nAt the moment of the writing of this book, in Zig, we have 6 different\nallocators available in the standard library:\n\n- `GeneralPurposeAllocator()`.\n- `page_allocator()`.\n- `FixedBufferAllocator()` and `ThreadSafeFixedBufferAllocator()`.\n- `ArenaAllocator()`.\n- `c_allocator()` (requires you to link to libc).\n\n\nEach allocator has its own perks and limitations. All allocators, except `FixedBufferAllocator()` and `ArenaAllocator()`,\nare allocators that use the heap memory. So any memory that you allocate with\nthese allocators, will be placed in the heap.\n\n### General-purpose allocators\n\nThe `GeneralPurposeAllocator()`, as the name suggests, is a \"general purpose\" allocator. You can use it for every type\nof task. In the example below, I'm allocating enough space to store a single integer in the object `some_number`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const some_number = try allocator.create(u32);\n defer allocator.destroy(some_number);\n\n some_number.* = @as(u32, 45);\n}\n```\n:::\n\n\n\n\n\nWhile useful, you might want to use the `c_allocator()`, which is a alias to the C standard allocator `malloc()`. So, yes, you can use\n`malloc()` in Zig if you want to. Just use the `c_allocator()` from the Zig standard library. However,\nif you do use `c_allocator()`, you must link to Libc when compiling your source code with the\n`zig` compiler, by including the flag `-lc` in your compilation process.\nIf you do not link your source code to Libc, Zig will not be able to find the\n`malloc()` implementation in your system.\n\n### Page allocator\n\nThe `page_allocator()` is an allocator that allocates full pages of memory in the heap. In other words,\nevery time you allocate memory with `page_allocator()`, a full page of memory in the heap is allocated,\ninstead of just a small piece of it.\n\nThe size of this page depends on the system you are using.\nMost systems use a page size of 4KB in the heap, so, that is the amount of memory that is normally\nallocated in each call by `page_allocator()`. That is why, `page_allocator()` is considered a\nfast, but also \"wasteful\" allocator in Zig. Because it allocates a big amount of memory\nin each call, and you most likely will not need that much memory in your program.\n\n### Buffer allocators\n\nThe `FixedBufferAllocator()` and `ThreadSafeFixedBufferAllocator()` are allocator objects that\nwork with a fixed sized buffer object at the back. In other words, they use a fixed sized buffer\nobject as the basis for the memory. When you ask these allocator objects to allocate some memory for you,\nthey are essentially reserving some amount of space inside this fixed sized buffer object for you to use.\n\nThis means that, in order to use these allocators, you must first create a buffer object in your code,\nand then, give this buffer object as an input to these allocators.\n\nThis also means that, these allocator objects can allocate memory both in the stack or in the heap.\nEverything depends on where the buffer object that you provide lives. If this buffer object lives\nin the stack, then, the memory allocated is \"stack-based\". But if it lives on the heap, then,\nthe memory allocated is \"heap-based\".\n\n\nIn the example below, I'm creating a `buffer` object on the stack that is 10 elements long.\nNotice that I give this `buffer` object to the `FixedBufferAllocator()` constructor.\nNow, because this `buffer` object is 10 elements long, this means that I am limited to this space.\nI cannot allocate more than 10 elements with this allocator object. If I try to\nallocate more than that, the `alloc()` method will return an `OutOfMemory` error value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar buffer: [10]u8 = undefined;\nfor (0..buffer.len) |i| {\n buffer[i] = 0; // Initialize to zero\n}\n\nvar fba = std.heap.FixedBufferAllocator.init(&buffer);\nconst allocator = fba.allocator();\nconst input = try allocator.alloc(u8, 5);\ndefer allocator.free(input);\n```\n:::\n\n\n\n\nRemember, the memory allocated by these allocator objects can be either from\nthe stack, or, from the heap. It all depends on where the buffer object that you provide lives.\nIn the above example, the `buffer` object lives in the stack, and, therefore, the memory allocated\nis based in the stack. But what if it was based on the heap?\n\nAs we described at @sec-stack-overflow, one of the main reasons why you would use the heap,\ninstead of the stack, is to allocate huge amounts of space to store very big objects.\nThus, let's suppose you wanted to use a very big buffer object as the basis for your\nallocator objects. You would have to allocate this very big buffer object on the heap.\nThe example below demonstrates this case.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst heap = std.heap.page_allocator;\nconst memory_buffer = try heap.alloc(\n u8, 100 * 1024 * 1024 // 100 MB memory\n);\ndefer heap.free(memory_buffer);\nvar fba = std.heap.FixedBufferAllocator.init(\n memory_buffer\n);\nconst allocator = fba.allocator();\n\nconst input = try allocator.alloc(u8, 1000);\ndefer allocator.free(input);\n```\n:::\n\n\n\n\n\n\n### Arena allocator {#sec-arena-allocator}\n\nThe `ArenaAllocator()` is an allocator object that takes a child allocator as input. The idea behind the `ArenaAllocator()` in Zig\nis similar to the concept of \"arenas\" in the programming language Go[^go-arena]. It is an allocator object that allows you\nto allocate memory as many times you want, but free all memory only once.\nIn other words, if you have, for example, called 5 times the method `alloc()` of an `ArenaAllocator()` object, you can\nfree all the memory you allocated over these 5 calls at once, by simply calling the `deinit()` method of the same `ArenaAllocator()` object.\n\n[^go-arena]: \n\nIf you give, for example, a `GeneralPurposeAllocator()` object as input to the `ArenaAllocator()` constructor, like in the example below, then, the allocations\nyou perform with `alloc()` will actually be made with the underlying object `GeneralPurposeAllocator()` that was passed.\nSo, with an arena allocator, any new memory you ask for is allocated by the child allocator. The only thing that an arena allocator\nreally does is help you to free all the memory you allocated multiple times with just a single command. In the example\nbelow, I called `alloc()` 3 times. So, if I did not use an arena allocator, then, I would need to call\n`free()` 3 times to free all the allocated memory.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nvar aa = std.heap.ArenaAllocator.init(gpa.allocator());\ndefer aa.deinit();\nconst allocator = aa.allocator();\n\nconst in1 = try allocator.alloc(u8, 5);\nconst in2 = try allocator.alloc(u8, 10);\nconst in3 = try allocator.alloc(u8, 15);\n_ = in1; _ = in2; _ = in3;\n```\n:::\n\n\n\n\n\n\n### The `alloc()` and `free()` methods\n\nIn the code example below, we are accessing the `stdin`, which is\nthe standard input channel, to receive an input from the\nuser. We read the input given by the user with the `readUntilDelimiterOrEof()`\nmethod.\n\nNow, after reading the input of the user, we need to store this input somewhere in\nour program. That is why I use an allocator in this example. I use it to allocate some\namount of memory to store this input given by the user. More specifically, the method `alloc()`\nof the allocator object is used to allocate an array capable of storing 50 `u8` values.\n\nNotice that this `alloc()` method receives two inputs. The first one, is a type.\nThis defines what type of values the allocated array will store. In the example\nbelow, we are allocating an array of unsigned 8-bit integers (`u8`). But\nyou can create an array to store any type of value you want. Next, on the second argument, we\ndefine the size of the allocated array, by specifying how many elements\nthis array will contain. In the case below, we are allocating an array of 50 elements.\n\nAt @sec-zig-strings we described that strings in Zig are simply arrays of characters.\nEach character is represented by a `u8` value. So, this means that the array that\nwas allocated in the object `input` is capable of storing a string that is\n50-characters long.\n\nSo, in essence, the expression `var input: [50]u8 = undefined` would create\nan array for 50 `u8` values in the stack of the current scope. But, you\ncan allocate the same array in the heap by using the expression `var input = try allocator.alloc(u8, 50)`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdin = std.io.getStdIn();\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var input = try allocator.alloc(u8, 50);\n defer allocator.free(input);\n for (0..input.len) |i| {\n input[i] = 0; // initialize all fields to zero.\n }\n // read user input\n const input_reader = stdin.reader();\n _ = try input_reader.readUntilDelimiterOrEof(\n input,\n '\\n'\n );\n std.debug.print(\"{s}\\n\", .{input});\n}\n```\n:::\n\n\n\n\nAlso, notice that in this example, we use the `defer` keyword (which I described at @sec-defer) to run a small\npiece of code at the end of the current scope, which is the expression `allocator.free(input)`.\nWhen you execute this expression, the allocator will free the memory that it allocated\nfor the `input` object.\n\nWe have talked about this at @sec-heap. You **should always** explicitly free any memory that you allocate\nusing an allocator! You do that by using the `free()` method of the same allocator object you\nused to allocate this memory. The `defer` keyword is used in this example only to help us execute\nthis free operation at the end of the current scope.\n\n\n### The `create()` and `destroy()` methods\n\nWith the `alloc()` and `free()` methods, you can allocate memory to store multiple elements\nat once. In other words, with these methods, we always allocate an array to store multiple elements at once.\nBut what if you need enough space to store just a single item? Should you\nallocate an array of a single element through `alloc()`?\n\nThe answer is no! In this case,\nyou should use the `create()` method of the allocator object.\nEvery allocator object offers the `create()` and `destroy()` methods,\nwhich are used to allocate and free memory for a single item, respectively.\n\nSo, in essence, if you want to allocate memory to store an array of elements, you\nshould use `alloc()` and `free()`. But if you need to store just a single item,\nthen, the `create()` and `destroy()` methods are ideal for you.\n\nIn the example below, I'm defining a struct to represent an user of some sort.\nIt could be a user for a game, or software to manage resources, it doesn't mater.\nNotice that I use the `create()` method this time, to store a single `User` object\nin the program. Also notice that I use the `destroy()` method to free the memory\nused by this object at the end of the scope.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst User = struct {\n id: usize,\n name: []const u8,\n\n pub fn init(id: usize, name: []const u8) User {\n return .{ .id = id, .name = name };\n }\n};\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const user = try allocator.create(User);\n defer allocator.destroy(user);\n\n user.* = User.init(0, \"Pedro\");\n}\n```\n:::\n", + "supporting": [ + "01-memory_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/02-debugging/execute-results/html.json b/_freeze/Chapters/02-debugging/execute-results/html.json index dcd81837..09ed5640 100644 --- a/_freeze/Chapters/02-debugging/execute-results/html.json +++ b/_freeze/Chapters/02-debugging/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "d955858e8c96c11c36427af044c591f0", + "hash": "8b14f21d35335dfe950f1e6461a7c890", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Debugging Zig applications\n\nBeing able to debug your applications is essential for any programmer who wants to\ndo serious programming in any language. That is why, in this chapter, we are going to talk about the\navailable strategies and tools to debug applications written in Zig.\n\n\n## Print debugging\n\nWe begin with the classic and battle-tested *print debugging* strategy.\nThe key advantage that debugging offers you is *visibility*.\nWith *print statements* you can easily see what results and objects\nare being produced by your application.\n\nThat is the essence of *print debugging*. Is to use\nprint expressions to see the values that are being generated by your program,\nand, as a result, get a much better understanding of how your program\nis behaving.\n\nMany programmers often resort to the print functions in Zig, such as the `stdout.print()`,\nor, the `std.debug.print()`, to get a better understanding of their programs.\nThis is a known and old strategy that is very simple and effective, and it is better known within\nthe programming community as *print debugging*.\nIn Zig, you can print information to the `stdout` or `stderr` streams of your system.\n\nLet's begin with `stdout`. First, you\nneed to get access to the `stdout`, by calling the `getStdOut()` method, from\nthe Zig Standard Library. This method returns a *file descriptor* object,\nand, through this object you can read/write to the `stdout`.\nI recommend you to check out all methods available in this object, by [checking the page in\nthe Zig Standard Library Official Reference for the type `File`](https://ziglang.org/documentation/master/std/#std.fs.File)[^zig-fiile-reference].\n\n[^zig-fiile-reference]: .\n\nFor our purpose here, which is to write something to the `stdout`, especially to debug our\nprogram, I recommend you to use the `writer()` method, which gives your a *writer* object.\nThis *writer* object offers some helper methods to write stuff into the file descriptor object\nthat represents the `stdout` stream. In special, the `print()` method.\n\n\nThe `print()` method from this *writer* object is a \"print formatter\" type of a function.\nIn other words, this method works exactly like the `printf()` function from C,\nor, like `println!()` from Rust.\nIn the first argument of the function, you specify a template string, and,\nin the second argument, you provide a list of values (or objects) that you want to insert\ninto your template message.\n\nIdeally, the template string in the first argument should contain some format specifier.\nEach format specifier is matched to a value (or object) that you have listed in the second argument.\nSo, if you provided 5 different objects in the second argument, then, the template string\nshould contain 5 format specifiers, one for each object provided.\n\nEach format specifier is represented by a single letter, and\nyou provide this format specifier inside a pair of curly braces. So, if you want to format\nyour object using the string specifier (`s`), then, you can insert the text `{s}` in your template string.\nHere is a quick list of the most used format specifiers:\n\n- `d`: for printing integers and floating-point numbers.\n- `c`: for printing characters.\n- `s`: for printing strings.\n- `p`: for printing memory addresses.\n- `x`: for printing hexadecimal values.\n- `any`: use any compatible format specifier (i.e. it automatically selects a format specifier for you).\n\nThe code example below gives you an example of use of this `print()` method\nwith the `d` format specifier.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn add(x: u8, y: u8) u8 {\n return x + y;\n}\n\npub fn main() !void {\n const result = add(34, 16);\n _ = try stdout.print(\"Result: {d}\", .{result});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 50\n```\n\n\n:::\n:::\n\n\n\n\nIs important to emphasize that, the `stdout.print()` method, as you would expect,\nprint your template string into the `stdout` stream of your system.\nHowever, you can also print your template string into the `stderr` stream\nif your prefer. All you need to do, is to replace the `stdout.print()`\ncall with the function `std.debug.print()`. Like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add(x: u8, y: u8) u8 {\n return x + y;\n}\n\npub fn main() !void {\n const result = add(34, 16);\n std.debug.print(\"Result: {d}\\n\", .{result});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 50\n```\n\n\n:::\n:::\n\n\n\n\n\nYou could also achieve the exact same result by getting a file descriptor object to `stderr`,\nthen, creating a *writer* object to `stderr`, then, using the `print()` method of this\n*writer* object, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stderr = std.io.getStdErr().writer();\n// some more lines ...\n_ = try stderr.print(\"Result: {d}\", .{result});\n```\n:::\n\n\n\n\n\n\n## Debugging through debuggers\n\nAlthough *print debugging* being a valid and very useful strategy,\nmost programmers prefer to use a debugger to debug their programs.\nSince Zig is a low-level language, you can use either GDB (GNU Debugger),\nor LLDB (LLVM Project Debugger) as your debugger.\n\nBoth debuggers can work with Zig code, and it's a matter of taste here.\nYou choose the debugger of your preference, and you work with it.\nIn this book, I will use LLDB as my debugger on the examples.\n\n\n### Compile your source code in debug mode {#sec-compile-debug-mode}\n\nIn order to debug your program through a debugger, you must compile\nyour source code in `Debug` mode. Because when you compile your\nsource code in other modes (such as `Release`), the compiler usually\nstrips out some essential information that is used by the debugger\nto read and track your program, like PDB (*Program Database*) files.\n\nBy compiling your source code in `Debug` mode, you ensure that the debugger\nwill find the necessary information in your program to debug it.\nBy default, the compiler uses the `Debug` mode when compiling your code.\nHaving this in mind, when you compile your program with the `build-exe`\ncommand (which was described at @sec-compile-code), if you don't specify\nan explicit mode through the `-O` command-line [^oargument]\nargument, then, the compiler will compile your code in `Debug` mode.\n\n[^oargument]: See .\n\n\n### Let's debug a program\n\nAs an example, let's use LLDB to navigate and investigate the following\npiece of Zig code:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\nfn add_and_increment(a: u8, b: u8) u8 {\n const sum = a + b;\n const incremented = sum + 1;\n return incremented;\n}\n\npub fn main() !void {\n var n = add_and_increment(2, 3);\n n = add_and_increment(n, n);\n _ = try stdout.print(\"Result: {d}!\\n\", .{n});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 13!\n```\n\n\n:::\n:::\n\n\n\n\nThere is nothing wrong with this program. But it is\na good start for us. First, we need to compile\nthis program with the `zig build-exe` command.\nFor this example, suppose that I have compiled the above\nZig code into a binary executable called `add_program`.\n\n```bash\nzig build-exe add_program.zig\n```\n\nNow, we can start LLDB with `add_program`, like this:\n\n```bash\nlldb add_program\n```\n\nFrom now on, LLDB is started, and you can know that I'm\nexecuting LLDB commands by looking at the prefix `(lldb)`.\nIf something is prefixed with `(lldb)`, then you know\nthat it is a LLDB command.\n\nThe first thing I will do, is to set a breakpoint at\nthe `main()` function, by executing `b main`.\nAfter that, I just start the execution of the program\nwith `run`.\nYou can see in the output below, that the execution\nstopped at the first line in the function `main()`, as we expected.\n\n```bash\n(lldb) b main\nBreakpoint 1: where = debugging`debug1.main + 22\n at debug1.zig:11:30, address = 0x00000000010341a6\n(lldb) run\nProcess 8654 launched: 'add_program' (x86_64)\nProcess 8654 stopped\n* thread #1, name = 'add_program',\n stop reason = breakpoint 1.1 frame #0: 0x10341a6\n add_program`debug1.main at add_program.zig:11:30\n 8 \t}\n 9 \t\n 10 \tpub fn main() !void {\n-> 11 \t var n = add_and_increment(2, 3);\n 12 \t n = add_and_increment(n, n);\n 13 \t try stdout.print(\"Result: {d}!\\n\", .{n});\n 14 \t}\n```\n\nI can start navigating through the code, and checking the objects\nthat are being generated. If you are not familiar with the commands\navailable in LLDB, I recommend you to read the official documentation\nof the project[^lldb].\nYou can also look for cheat sheets, which quickly describes all commands\navailable for you[^lldb-quick-list].\n\n[^lldb]: \n[^lldb-quick-list]: .\n\nCurrently, we are in the first line at the `main()` function. In this line, we create\nthe `n` object, by executing the `add_and_increment()` function.\nTo execute the current line of code, and go to the next line, we can\nrun the `n` LLDB command. Let's execute this command.\n\nAfter we executed this line, we can also look at the value stored inside this `n` object\nby using the `p` LLDB command. The syntax for this command is `p `.\n\nIf we take a look at the value stored in the `n` object (`p n`),\nnotice that it stores the hexadecimal value `0x06`, which\nis the number 6 in decimal. We can also see that, this value have a type `unsigned char`,\nwhich is an unsigned 8-bit integer.\nWe have talked already about this at @sec-zig-strings, that `u8` integers in Zig are equivalent\nto the C data type `unsigned char`.\n\n\n\n```bash\n(lldb) n\nProcess 4798 stopped\n* thread #1, name = 'debugging',\n stop reason = step over frame #0: 0x10341ae\n debugging`debug1.main at debug1.zig:12:26\n 9 \t\n 10 \tpub fn main() !void {\n 11 \t var n = add_and_increment(2, 3);\n-> 12 \t n = add_and_increment(n, n);\n 13 \t try stdout.print(\"Result: {d}!\\n\", .{n});\n 14 \t}\n(lldb) p n\n(unsigned char) $1 = '\\x06'\n```\n\nNow, on the next line of code, we are executing the `add_and_increment()` function once again.\nWhy not step inside this function? Shall we? We can do that, by executing the `s` LLDB command.\nNotice in the example below that, after executing this command, we have entered into the context of the\n`add_and_increment()` function.\n\nAlso notice in the example below that, I have walked two more lines in the function's body, then,\nI execute the `frame variable` LLDB command, to see at once, the value stored in each of the variables\nthat were created inside the current scope.\n\nYou can see in the output below that, the object `sum` stores the value `\\f`,\nwhich represents the *form feed* character. This character in the ASCII table,\ncorresponds to the hexadecimal value `0x0C`, or, in decimal, the number 12.\nSo, this means that the result of the expression `a + b` executed at line\n5, resulted in the number 12.\n\n```bash\n(lldb) s\nProcess 4798 stopped\n* thread #1, name = 'debugging',\n stop reason = step in frame #0: 0x10342de\n debugging`debug1.add_and_increment(a='\\x02', b='\\x03')\n at debug1.zig:4:39\n-> 4 \tfn add_and_increment(a: u8, b: u8) u8 {\n 5 \t const sum = a + b;\n 6 \t const incremented = sum + 1;\n 7 \t return incremented;\n(lldb) n\n(lldb) n\n(lldb) frame variable\n(unsigned char) a = '\\x06'\n(unsigned char) b = '\\x06'\n(unsigned char) sum = '\\f'\n(unsigned char) incremented = '\\x06'\n```\n\n\n\n## How to investigate the data type of your objects\n\nSince Zig is a strongly-typed language, the data types associated with your objects\nare very important for your program. So, debugging the data types associated\nwith your objects might be important to understand bugs and errors in your program.\n\nWhen you walk through your program with a debugger, you can inspect the types of\nyour objects by simply printing them to the console, with the LLDB `p` command.\nBut you also have alternatives embedded in the language itself to access the data\ntypes of your objects.\n\nIn Zig, you can retrieve the data type of an object, by using the built-in function\n`@TypeOf()`. Just apply this function over the object, and you get access to \nthe data type of the object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst expect = std.testing.expect;\n\npub fn main() !void {\n const number: i32 = 5;\n try expect(@TypeOf(number) == i32);\n try stdout.print(\"{any}\\n\", .{@TypeOf(number)});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ni32\n```\n\n\n:::\n:::\n\n\n\n\nThis function is similar to the `type()` built-in function from Python,\nor, the `typeof` operator in Javascript.\n\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Debugging Zig applications\n\nBeing able to debug your applications is essential for any programmer who wants to\ndo serious programming in any language. That is why, in this chapter, we are going to talk about the\navailable strategies and tools to debug applications written in Zig.\n\n\n## Print debugging\n\nWe begin with the classic and battle-tested *print debugging* strategy.\nThe key advantage that debugging offers you is *visibility*.\nWith *print statements* you can easily see what results and objects\nare being produced by your application.\n\nThat is the essence of *print debugging*. Is to use\nprint expressions to see the values that are being generated by your program,\nand, as a result, get a much better understanding of how your program\nis behaving.\n\nMany programmers often resort to the print functions in Zig, such as the `stdout.print()`,\nor, the `std.debug.print()`, to get a better understanding of their programs.\nThis is a known and old strategy that is very simple and effective, and it is better known within\nthe programming community as *print debugging*.\nIn Zig, you can print information to the `stdout` or `stderr` streams of your system.\n\nLet's begin with `stdout`. First, you\nneed to get access to the `stdout`, by calling the `getStdOut()` method, from\nthe Zig Standard Library. This method returns a *file descriptor* object,\nand, through this object you can read/write to the `stdout`.\nI recommend you to check out all methods available in this object, by [checking the page in\nthe Zig Standard Library Official Reference for the type `File`](https://ziglang.org/documentation/master/std/#std.fs.File)[^zig-fiile-reference].\n\n[^zig-fiile-reference]: .\n\nFor our purpose here, which is to write something to the `stdout`, especially to debug our\nprogram, I recommend you to use the `writer()` method, which gives you a *writer* object.\nThis *writer* object offers some helper methods to write stuff into the file descriptor object\nthat represents the `stdout` stream. In special, the `print()` method.\n\n\nThe `print()` method from this *writer* object is a \"print formatter\" type of a function.\nIn other words, this method works exactly like the `printf()` function from C,\nor, like `println!()` from Rust.\nIn the first argument of the function, you specify a template string, and,\nin the second argument, you provide a list of values (or objects) that you want to insert\ninto your template message.\n\nIdeally, the template string in the first argument should contain some format specifier.\nEach format specifier is matched to a value (or object) that you have listed in the second argument.\nSo, if you provided 5 different objects in the second argument, then, the template string\nshould contain 5 format specifiers, one for each object provided.\n\nEach format specifier is represented by a single letter, and\nyou provide this format specifier inside a pair of curly braces. So, if you want to format\nyour object using the string specifier (`s`), then, you can insert the text `{s}` in your template string.\nHere is a quick list of the most used format specifiers:\n\n- `d`: for printing integers and floating-point numbers.\n- `c`: for printing characters.\n- `s`: for printing strings.\n- `p`: for printing memory addresses.\n- `x`: for printing hexadecimal values.\n- `any`: use any compatible format specifier (i.e. it automatically selects a format specifier for you).\n\nThe code example below gives you an example of use of this `print()` method\nwith the `d` format specifier.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn add(x: u8, y: u8) u8 {\n return x + y;\n}\n\npub fn main() !void {\n const result = add(34, 16);\n _ = try stdout.print(\"Result: {d}\", .{result});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 50\n```\n\n\n:::\n:::\n\n\n\n\nIt is important to emphasize that, the `stdout.print()` method, as you would expect,\nprints your template string into the `stdout` stream of your system.\nHowever, you can also print your template string into the `stderr` stream\nif your prefer. All you need to do, is to replace the `stdout.print()`\ncall with the function `std.debug.print()`. Like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add(x: u8, y: u8) u8 {\n return x + y;\n}\n\npub fn main() !void {\n const result = add(34, 16);\n std.debug.print(\"Result: {d}\\n\", .{result});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 50\n```\n\n\n:::\n:::\n\n\n\n\n\nYou could also achieve the exact same result by getting a file descriptor object to `stderr`,\nthen, creating a *writer* object to `stderr`, then, using the `print()` method of this\n*writer* object, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stderr = std.io.getStdErr().writer();\n// some more lines ...\n_ = try stderr.print(\"Result: {d}\", .{result});\n```\n:::\n\n\n\n\n\n\n## Debugging through debuggers\n\nAlthough *print debugging* is a valid and very useful strategy,\nmost programmers prefer to use a debugger to debug their programs.\nSince Zig is a low-level language, you can use either GDB (GNU Debugger),\nor LLDB (LLVM Project Debugger) as your debugger.\n\nBoth debuggers can work with Zig code, and it's a matter of taste here.\nYou choose the debugger of your preference, and you work with it.\nIn this book, I will use LLDB as my debugger on the examples.\n\n\n### Compile your source code in debug mode {#sec-compile-debug-mode}\n\nIn order to debug your program through a debugger, you must compile\nyour source code in `Debug` mode. Because when you compile your\nsource code in other modes (such as `Release`), the compiler usually\nstrips out some essential information that is used by the debugger\nto read and track your program, like PDB (*Program Database*) files.\n\nBy compiling your source code in `Debug` mode, you ensure that the debugger\nwill find the necessary information in your program to debug it.\nBy default, the compiler uses the `Debug` mode when compiling your code.\nHaving this in mind, when you compile your program with the `build-exe`\ncommand (which was described at @sec-compile-code), if you don't specify\nan explicit mode through the `-O` command-line [^oargument]\nargument, then, the compiler will compile your code in `Debug` mode.\n\n[^oargument]: See .\n\n\n### Let's debug a program\n\nAs an example, let's use LLDB to navigate and investigate the following\npiece of Zig code:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\nfn add_and_increment(a: u8, b: u8) u8 {\n const sum = a + b;\n const incremented = sum + 1;\n return incremented;\n}\n\npub fn main() !void {\n var n = add_and_increment(2, 3);\n n = add_and_increment(n, n);\n _ = try stdout.print(\"Result: {d}!\\n\", .{n});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 13!\n```\n\n\n:::\n:::\n\n\n\n\nThere is nothing wrong with this program. But it is\na good start for us. First, we need to compile\nthis program with the `zig build-exe` command.\nFor this example, suppose that I have compiled the above\nZig code into a binary executable called `add_program`.\n\n```bash\nzig build-exe add_program.zig\n```\n\nNow, we can start LLDB with `add_program`, like this:\n\n```bash\nlldb add_program\n```\n\nFrom now on, LLDB is started, and you can know that I'm\nexecuting LLDB commands by looking at the prefix `(lldb)`.\nIf something is prefixed with `(lldb)`, then you know\nthat it is a LLDB command.\n\nThe first thing I will do, is to set a breakpoint at\nthe `main()` function, by executing `b main`.\nAfter that, I just start the execution of the program\nwith `run`.\nYou can see in the output below, that the execution\nstopped at the first line in the function `main()`, as we expected.\n\n```bash\n(lldb) b main\nBreakpoint 1: where = debugging`debug1.main + 22\n at debug1.zig:11:30, address = 0x00000000010341a6\n(lldb) run\nProcess 8654 launched: 'add_program' (x86_64)\nProcess 8654 stopped\n* thread #1, name = 'add_program',\n stop reason = breakpoint 1.1 frame #0: 0x10341a6\n add_program`debug1.main at add_program.zig:11:30\n 8 \t}\n 9 \t\n 10 \tpub fn main() !void {\n-> 11 \t var n = add_and_increment(2, 3);\n 12 \t n = add_and_increment(n, n);\n 13 \t try stdout.print(\"Result: {d}!\\n\", .{n});\n 14 \t}\n```\n\nI can start navigating through the code, and checking the objects\nthat are being generated. If you are not familiar with the commands\navailable in LLDB, I recommend you to read the official documentation\nof the project[^lldb].\nYou can also look for cheat sheets, which quickly describes all commands\navailable for you[^lldb-quick-list].\n\n[^lldb]: \n[^lldb-quick-list]: .\n\nCurrently, we are in the first line at the `main()` function. In this line, we create\nthe `n` object, by executing the `add_and_increment()` function.\nTo execute the current line of code, and go to the next line, we can\nrun the `n` LLDB command. Let's execute this command.\n\nAfter we executed this line, we can also look at the value stored inside this `n` object\nby using the `p` LLDB command. The syntax for this command is `p `.\n\nIf we take a look at the value stored in the `n` object (`p n`),\nnotice that it stores the hexadecimal value `0x06`, which\nis the number 6 in decimal. We can also see that this value has a type of `unsigned char`,\nwhich is an unsigned 8-bit integer.\nWe have talked already about this at @sec-zig-strings, that `u8` integers in Zig are equivalent\nto the C data type `unsigned char`.\n\n\n\n```bash\n(lldb) n\nProcess 4798 stopped\n* thread #1, name = 'debugging',\n stop reason = step over frame #0: 0x10341ae\n debugging`debug1.main at debug1.zig:12:26\n 9 \t\n 10 \tpub fn main() !void {\n 11 \t var n = add_and_increment(2, 3);\n-> 12 \t n = add_and_increment(n, n);\n 13 \t try stdout.print(\"Result: {d}!\\n\", .{n});\n 14 \t}\n(lldb) p n\n(unsigned char) $1 = '\\x06'\n```\n\nNow, on the next line of code, we are executing the `add_and_increment()` function once again.\nWhy not step inside this function? Shall we? We can do that, by executing the `s` LLDB command.\nNotice in the example below that, after executing this command, we have entered into the context of the\n`add_and_increment()` function.\n\nAlso notice in the example below that, I have walked two more lines in the function's body, then,\nI execute the `frame variable` LLDB command, to see at once, the value stored in each of the variables\nthat were created inside the current scope.\n\nYou can see in the output below that, the object `sum` stores the value `\\f`,\nwhich represents the *form feed* character. This character in the ASCII table,\ncorresponds to the hexadecimal value `0x0C`, or, in decimal, the number 12.\nSo, this means that the result of the expression `a + b` executed at line\n5, resulted in the number 12.\n\n```bash\n(lldb) s\nProcess 4798 stopped\n* thread #1, name = 'debugging',\n stop reason = step in frame #0: 0x10342de\n debugging`debug1.add_and_increment(a='\\x02', b='\\x03')\n at debug1.zig:4:39\n-> 4 \tfn add_and_increment(a: u8, b: u8) u8 {\n 5 \t const sum = a + b;\n 6 \t const incremented = sum + 1;\n 7 \t return incremented;\n(lldb) n\n(lldb) n\n(lldb) frame variable\n(unsigned char) a = '\\x06'\n(unsigned char) b = '\\x06'\n(unsigned char) sum = '\\f'\n(unsigned char) incremented = '\\x06'\n```\n\n\n\n## How to investigate the data type of your objects\n\nSince Zig is a strongly-typed language, the data types associated with your objects\nare very important for your program. So, debugging the data types associated\nwith your objects might be important to understand bugs and errors in your program.\n\nWhen you walk through your program with a debugger, you can inspect the types of\nyour objects by simply printing them to the console, with the LLDB `p` command.\nBut you also have alternatives embedded in the language itself to access the data\ntypes of your objects.\n\nIn Zig, you can retrieve the data type of an object, by using the built-in function\n`@TypeOf()`. Just apply this function over the object, and you get access to \nthe data type of the object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst expect = std.testing.expect;\n\npub fn main() !void {\n const number: i32 = 5;\n try expect(@TypeOf(number) == i32);\n try stdout.print(\"{any}\\n\", .{@TypeOf(number)});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ni32\n```\n\n\n:::\n:::\n\n\n\n\nThis function is similar to the `type()` built-in function from Python,\nor, the `typeof` operator in Javascript.\n\n", "supporting": [ "02-debugging_files" ], diff --git a/_freeze/Chapters/03-structs/execute-results/html.json b/_freeze/Chapters/03-structs/execute-results/html.json index fb55828f..543363c1 100644 --- a/_freeze/Chapters/03-structs/execute-results/html.json +++ b/_freeze/Chapters/03-structs/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "75a34188e80fdc2dce5441514f1bc59a", + "hash": "ddf3054f897e82f090f3aa7c5890ec78", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `role`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object has type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e. four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n```\n:::\n\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It is important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n else => {\n try stdout.print(\n \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n );\n },\n}\n```\n:::\n\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n```\n:::\n\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function get's executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, is worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression get's executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that get's printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n // code to execute\n}\n```\n:::\n\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It is the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e. the logical test is equal to false), the function raises an assertion error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e. constant) object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n x = x + 2;\n return x;\n}\n\npub fn main() !void {\n const y = add2(4);\n std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n x = x + 2;\n ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e. `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n const d: u32 = 2;\n x.* = x.* + d;\n}\n\npub fn main() !void {\n var x: u32 = 4;\n add2(&x);\n std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n pub fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n pub fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nEvery method that you declare in your struct that is marked with the keyword `pub`,\nbecomes a public method of this particular struct.\n\nSo every method that you create inside your struct, is, at first, a private method\nof that struct. Meaning that, this method can only be called from within this\nstruct. But, if you mark this method as public, with the keyword `pub`, then,\nyou can call the method directly from an instance of the `User` struct.\n\nIn other words, the functions marked by the keyword `pub`\nare members of the public API of that struct.\nFor example, if I did not mark the `print_name()` method as public,\nthen, I could not execute the line `u.print_name()`. Because I would\nnot be authorized to call this method directly in my code.\n\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n```\n:::\n\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt is not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n```\n:::\n\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods is affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e. change the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n```\n:::\n\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it is not about the input object, it is about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special party in this place. More specifically, it is\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and it is\ntrying to infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n```\n:::\n\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e. we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it is explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filecdc41797a754.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe, and there are situations where these assumptions do not hold. For example,\nwhen casting an integer value into a float value, or vice-versa, it is not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filecdc428638149.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e. they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filecdc46f71cc03.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e. a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" get's executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object get's saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n .{ .max_threads = num_threads }\n);\n```\n:::\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `role`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object has type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e. four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n```\n:::\n\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It is important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n else => {\n try stdout.print(\n \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n );\n },\n}\n```\n:::\n\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n```\n:::\n\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function gets executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, is worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression get's executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that get's printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n // code to execute\n}\n```\n:::\n\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It is the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e. the logical test is equal to false), the function raises an assertion error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e. constant) object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n x = x + 2;\n return x;\n}\n\npub fn main() !void {\n const y = add2(4);\n std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n x = x + 2;\n ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e. `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n const d: u32 = 2;\n x.* = x.* + d;\n}\n\npub fn main() !void {\n var x: u32 = 4;\n add2(&x);\n std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n pub fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n pub fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nEvery method that you declare in your struct that is marked with the keyword `pub`,\nbecomes a public method of this particular struct.\n\nSo every method that you create inside your struct, is, at first, a private method\nof that struct. Meaning that, this method can only be called from within this\nstruct. But, if you mark this method as public, with the keyword `pub`, then,\nyou can call the method directly from an instance of the `User` struct.\n\nIn other words, the functions marked by the keyword `pub`\nare members of the public API of that struct.\nFor example, if I did not mark the `print_name()` method as public,\nthen, I could not execute the line `u.print_name()`. Because I would\nnot be authorized to call this method directly in my code.\n\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n```\n:::\n\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt is not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n```\n:::\n\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods are affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e. changes the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n```\n:::\n\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it is not about the input object, it is about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special part in this place. More specifically, it is\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and it is\ntrying to infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n```\n:::\n\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e. we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it is explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file2ed34a8fc96.test_0...OKAll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe, and there are situations where these assumptions do not hold. For example,\nwhen casting an integer value into a float value, or vice-versa, it is not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file2ed34bfb9fa5.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e. they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file2ed324328e1f.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e. a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" get's executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object get's saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n .{ .max_threads = num_threads }\n);\n```\n:::\n", "supporting": [ "03-structs_files" ], diff --git a/_freeze/index/execute-results/html.json b/_freeze/index/execute-results/html.json index 45e16fd5..2f1af68f 100644 --- a/_freeze/index/execute-results/html.json +++ b/_freeze/index/execute-results/html.json @@ -2,7 +2,7 @@ "hash": "7eedbe34469c0f2c200651bc420da095", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy an eBook or a physical copy\nof the book on Amazon:\n\n\n\n\n\n\n \n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.2371+c013f45ad.\n- Quarto version: 1.5.57.\n\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur)\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy an eBook or a physical copy\nof the book on Amazon:\n\n\n\n\n\n\n \n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m)\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/contributors.txt b/contributors.txt index 6bcf75bc..1c2abddf 100644 --- a/contributors.txt +++ b/contributors.txt @@ -17,3 +17,5 @@ Primo Sabatini,@primos63 Santiago Fernandez,@santif Hamza Wahed,@HamzaWahed mwilbur,@mwilbur +Dima Budaragin,@dbud +Jorge Jímenez,@jorge-j1m diff --git a/docs/Chapters/01-memory.html b/docs/Chapters/01-memory.html index 0e748f6f..12fad0b6 100644 --- a/docs/Chapters/01-memory.html +++ b/docs/Chapters/01-memory.html @@ -380,7 +380,7 @@

      The other side of the spectrum are objects whose values are not known at compile time. Function arguments are a classic example of this. Because the value of each function argument depends on the value that you assign to this particular argument, when you call the function.

      For example, the function input_length() contains an argument named input, which is an array of constant u8 integers ([]const u8). It is impossible to know the value of this particular argument at compile time. And it also is impossible to know the size/length of this particular argument. Because it is an array that do not have a fixed size specified explicitly in the argument type annotation.

      -

      So, we know that this input argument will be an array of u8 integers. But we do not know at compile-time, its value, and neither his size. This information is known only at runtime, which is the period of time when you program is executed. As a consequence, the value of the expression input.len is also known only at runtime. This is an intrinsic characteristic of any function. Just remember that the value of function arguments is usually not “compile-time known”.

      +

      So, we know that this input argument will be an array of u8 integers. But we do not know at compile-time, its value, and neither its size. This information is known only at runtime, which is the period of time when you program is executed. As a consequence, the value of the expression input.len is also known only at runtime. This is an intrinsic characteristic of any function. Just remember that the value of function arguments is usually not “compile-time known”.

      However, as I mentioned earlier, what really matters to the compiler is to know the size of the object at compile-time, and not necessarily its value. So, although we don’t know the value of the object n, which is the result of the expression input.len, at compile-time, we do know its size. Because the expression input.len always returns a value of type usize, and the type usize has a known fixed size.

    @@ -391,7 +391,7 @@

    <

    3.1.3 Stack vs Heap

    -

    If you are familiar with system’s programming, or just low-level programming in general, you probably have heard of the “duel” between Stack vs Heap. These are two different types of memory, or different memory spaces, which are both available in Zig.

    +

    If you are familiar with systems programming, or just low-level programming in general, you probably have heard of the “duel” between Stack vs Heap. These are two different types of memory, or different memory spaces, which are both available in Zig.

    These two types of memory don’t actually duel with each other. This is a common mistake that beginners have, when seeing “x vs y” styles of tabloid headlines. These two types of memory are actually complementary to each other. So, in almost every Zig program that you ever write, you will likely use a combination of both. I will describe each memory space in detail over the next sections. But for now, I just want to stablish the main difference between these two types of memory.

    In essence, the stack memory is normally used to store values whose length is fixed and known at compile time. In contrast, the heap memory is a dynamic type of memory space, meaning that, it is used to store values whose length might grow during the execution (runtime) of your program (Chen and Guo 2022).

    Lengths that grow during runtime are intrinsically associated with “runtime known” type of values. In other words, if you have an object whose length might grow during runtime, then, the length of this object becomes not known at compile time. If the length is not known at compile-time, the value of this object also becomes not known at compile-time. These types of objects should be stored in the heap memory space, which is a dynamic memory space, which can grow or shrink to fit the size of your objects.

    @@ -429,7 +429,7 @@

    Local objects that are stored in the stack space of a function are automatically freed/destroyed at the end of the function scope.

    -

    This same logic applies to any other special structure in Zig that have its own scope by surrounding it with curly braces ({}). For loops, while loops, if else statements, etc. For example, if you declare any local object in the scope of a for loop, this local object is accessible only within the scope of this particular for loop. Because once the scope of this for loop ends, the space in the stack reserved for this for loop is freed. The example below demonstrates this idea.

    +

    This same logic applies to any other special structure in Zig that has its own scope by surrounding it with curly braces ({}). For loops, while loops, if else statements, etc. For example, if you declare any local object in the scope of a for loop, this local object is accessible only within the scope of this particular for loop. Because once the scope of this for loop ends, the space in the stack reserved for this for loop is freed. The example below demonstrates this idea.

    // This does not compile successfully!
     const a = [_]u8{0, 1, 2, 3, 4};
    @@ -460,7 +460,7 @@ 

    const r = add(5, 27); _ = r; }

    -

    This “invalid pointer to stack variable” problem is very known across many programming language communities. If you try to do the same thing, for example, in a C or C++ program (i.e. returning an address to a local object stored in the stack), you would also get undefined behaviour in the program.

    +

    This “invalid pointer to stack variable” problem is well known across many programming language communities. If you try to do the same thing, for example, in a C or C++ program (i.e. returning an address to a local object stored in the stack), you would also get undefined behaviour in the program.

    @@ -474,13 +474,13 @@

    If a local object in your function is stored in the stack, you should never return a pointer to this local object from the function. Because this pointer will always become undefined after the function returns, since the stack space of the function is destroyed at the end of its scope.

    -

    But what if you really need to use this local object in some way after your function returns? How can you do this? The answer is: “in the same you would do if this was a C or C++ program. By returning an address to an object stored in the heap”. The heap memory has a much more flexible lifecycle, and allows you to get a valid pointer to a local object of a function that already returned from its scope.

    +

    But what if you really need to use this local object in some way after your function returns? How can you do this? The answer is: “in the same way you would do if this were a C or C++ program. By returning an address to an object stored in the heap”. The heap memory has a much more flexible lifecycle, and allows you to get a valid pointer to a local object of a function that already returned from its scope.

    3.1.5 Heap

    One important limitation of the stack, is that, only objects whose length/size is known at compile-time can be stored in it. In contrast, the heap is a much more dynamic (and flexible) type of memory. It is the perfect type of memory to use for objects whose size/length might grow during the execution of your program.

    Virtually any application that behaves as a server is a classic use case of the heap. A HTTP server, a SSH server, a DNS server, a LSP server, … any type of server. In summary, a server is a type of application that runs for long periods of time, and that serves (or “deals with”) any incoming request that reaches this particular server.

    -

    The heap is a good choice for this type of system, mainly because the server does not know upfront how many requests it will receive from users, while it is active. It could be one single request, or, 5 thousand requests, or, it could also be zero requests. The server needs to have the ability to allocate and manage its memory according to how many requests it receives.

    +

    The heap is a good choice for this type of system, mainly because the server does not know upfront how many requests it will receive from users, while it is active. It could be a single request, 5 thousand requests, or even zero requests. The server needs to have the ability to allocate and manage its memory according to how many requests it receives.

    Another key difference between the stack and the heap, is that the heap is a type of memory that you, the programmer, have complete control over. This makes the heap a more flexible type of memory, but it also makes it harder to work with. Because you, the programmer, is responsible for managing everything related to it. Including where the memory is allocated, how much memory is allocated, and where this memory is freed.

    Unlike stack memory, heap memory is allocated explicitly by programmers and it won’t be deallocated until it is explicitly freed (Chen and Guo 2022).

    @@ -509,7 +509,7 @@

    Allocating memory on the stack is generally faster than allocating it on the heap. But this better performance comes with many restrictions. We have already discussed many of these restrictions of the stack at Section 3.1.4. But there is one more important limitation that I want to talk about, which is the size of the stack itself.

    The stack is limited in size. This size varies from computer to computer, and it depends on a lot of things (the computer architecture, the operating system, etc.). Nevertheless, this size is usually not that big. This is why we normally use the stack to store only temporary and small objects in memory.

    In essence, if you try to make an allocation on the stack, that is so big that exceeds the stack size limit, a stack overflow happens, and your program just crashes as a result of that. In other words, a stack overflow happens when you attempt to use more space than is available on the stack.

    -

    This type of problem is very similar to a buffer overflow, i.e. you are trying to use more space than is available in the “buffer object”. However, a stack overflow always cause your program to crash, while a buffer overflow not always cause your program to crash (although it often does).

    -

    You can see an example of a stack overflow in the example below. We are trying to allocate a very big array of u64 values on the stack. You can see below that this program does not run succesfully, because it crashed with a “segmentation fault” error message.

    +

    This type of problem is very similar to a buffer overflow, i.e. you are trying to use more space than is available in the “buffer object”. However, a stack overflow always causes your program to crash, while a buffer overflow does not always cause your program to crash (although it often does).

    +

    You can see an example of a stack overflow in the example below. We are trying to allocate a very big array of u64 values on the stack. You can see below that this program does not run successfully, because it crashed with a “segmentation fault” error message.

    var very_big_alloc: [1000 * 1000 * 24]u64 = undefined;
     @memset(very_big_alloc[0..], 0);
    @@ -533,7 +533,7 @@

    This is a known problem, especially in C++. Because in C++, there are some operators that do allocate memory behind the scene, and there is no way for you to know that, until you actually read the source code of these operators, and find the memory allocation calls. Many programmers find this behaviour annoying and hard to keep track of.

    But, in Zig, if a function, an operator, or anything from the standard library needs to allocate some memory during its execution, then, this function/operator needs to receive (as input) an allocator provided by the user, to actually be able to allocate the memory it needs.

    This creates a clear distinction between functions that “do not” from those that “actually do” allocate memory. Just look at the arguments of this function. If a function, or operator, has an allocator object as one of its inputs/arguments, then, you know for sure that this function/operator will allocate some memory during its execution.

    -

    An example is the allocPrint() function from the Zig Standard Library. With this function, you can write a new string using format specifiers. So, this function is, for example, very similar to the function sprintf() in C. In order to write such new string, the allocPrint() function needs to allocate some memory to store the output string.

    +

    An example is the allocPrint() function from the Zig Standard Library. With this function, you can write a new string using format specifiers. So, this function is, for example, very similar to the function sprintf() in C. In order to write such a new string, the allocPrint() function needs to allocate some memory to store the output string.

    That is why, the first argument of this function is an allocator object that you, the user/programmer, gives as input to the function. In the example below, I am using the GeneralPurposeAllocator() as my allocator object. But I could easily use any other type of allocator object from the Zig Standard Library.

    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    @@ -558,14 +558,14 @@ 

    3.3.2 Why you need an allocator?

    -

    As we described at Section 3.1.4, everytime you make a function call in Zig, a space in the stack is reserved for this function call. But the stack has a key limitation which is: every object stored in the stack have a known fixed length.

    +

    As we described at Section 3.1.4, everytime you make a function call in Zig, a space in the stack is reserved for this function call. But the stack has a key limitation which is: every object stored in the stack has a known fixed length.

    But in reality, there are two very common instances where this “fixed length limitation” of the stack is a deal braker:

    1. the objects that you create inside your function might grow in size during the execution of the function.
    2. sometimes, it is impossible to know upfront how many inputs you will receive, or how big this input will be.

    Also, there is another instance where you might want to use an allocator, which is when you want to write a function that returns a pointer to a local object. As I described at Section 3.1.4, you cannot do that if this local object is stored in the stack. However, if this object is stored in the heap, then, you can return a pointer to this object at the end of the function. Because you (the programmer) control the lifetime of any heap memory that you allocate. You decide when this memory gets destroyed/freed.

    -

    These are common situations where the stack is not good for. That is why you need a different memory management strategy to store these objects inside your function. You need to use a memory type that can grow together with your objects, or that you can control the lifetime of this memory. The heap fits this description.

    +

    These are common situations for which the stack is not good. That is why you need a different memory management strategy to store these objects inside your function. You need to use a memory type that can grow together with your objects, or that you can control the lifetime of this memory. The heap fits this description.

    Allocating memory on the heap is commonly known as dynamic memory management. As the objects you create grow in size during the execution of your program, you grow the amount of memory you have by allocating more memory in the heap to store these objects. And you do that in Zig, by using an allocator object.

    @@ -688,7 +688,7 @@

    const std = @import("std");
     const User = struct {
    diff --git a/docs/Chapters/02-debugging.html b/docs/Chapters/02-debugging.html
    index d6ff110e..c79707b7 100644
    --- a/docs/Chapters/02-debugging.html
    +++ b/docs/Chapters/02-debugging.html
    @@ -317,7 +317,7 @@ 

    That is the essence of print debugging. Is to use print expressions to see the values that are being generated by your program, and, as a result, get a much better understanding of how your program is behaving.

    Many programmers often resort to the print functions in Zig, such as the stdout.print(), or, the std.debug.print(), to get a better understanding of their programs. This is a known and old strategy that is very simple and effective, and it is better known within the programming community as print debugging. In Zig, you can print information to the stdout or stderr streams of your system.

    Let’s begin with stdout. First, you need to get access to the stdout, by calling the getStdOut() method, from the Zig Standard Library. This method returns a file descriptor object, and, through this object you can read/write to the stdout. I recommend you to check out all methods available in this object, by checking the page in the Zig Standard Library Official Reference for the type File1.

    -

    For our purpose here, which is to write something to the stdout, especially to debug our program, I recommend you to use the writer() method, which gives your a writer object. This writer object offers some helper methods to write stuff into the file descriptor object that represents the stdout stream. In special, the print() method.

    +

    For our purpose here, which is to write something to the stdout, especially to debug our program, I recommend you to use the writer() method, which gives you a writer object. This writer object offers some helper methods to write stuff into the file descriptor object that represents the stdout stream. In special, the print() method.

    The print() method from this writer object is a “print formatter” type of a function. In other words, this method works exactly like the printf() function from C, or, like println!() from Rust. In the first argument of the function, you specify a template string, and, in the second argument, you provide a list of values (or objects) that you want to insert into your template message.

    Ideally, the template string in the first argument should contain some format specifier. Each format specifier is matched to a value (or object) that you have listed in the second argument. So, if you provided 5 different objects in the second argument, then, the template string should contain 5 format specifiers, one for each object provided.

    Each format specifier is represented by a single letter, and you provide this format specifier inside a pair of curly braces. So, if you want to format your object using the string specifier (s), then, you can insert the text {s} in your template string. Here is a quick list of the most used format specifiers:

    @@ -345,7 +345,7 @@

    Result: 50

    -

    Is important to emphasize that, the stdout.print() method, as you would expect, print your template string into the stdout stream of your system. However, you can also print your template string into the stderr stream if your prefer. All you need to do, is to replace the stdout.print() call with the function std.debug.print(). Like this:

    +

    It is important to emphasize that, the stdout.print() method, as you would expect, prints your template string into the stdout stream of your system. However, you can also print your template string into the stderr stream if your prefer. All you need to do, is to replace the stdout.print() call with the function std.debug.print(). Like this:

    const std = @import("std");
     fn add(x: u8, y: u8) u8 {
    @@ -370,7 +370,7 @@ 

    5.2 Debugging through debuggers

    -

    Although print debugging being a valid and very useful strategy, most programmers prefer to use a debugger to debug their programs. Since Zig is a low-level language, you can use either GDB (GNU Debugger), or LLDB (LLVM Project Debugger) as your debugger.

    +

    Although print debugging is a valid and very useful strategy, most programmers prefer to use a debugger to debug their programs. Since Zig is a low-level language, you can use either GDB (GNU Debugger), or LLDB (LLVM Project Debugger) as your debugger.

    Both debuggers can work with Zig code, and it’s a matter of taste here. You choose the debugger of your preference, and you work with it. In this book, I will use LLDB as my debugger on the examples.

    5.2.1 Compile your source code in debug mode

    @@ -424,7 +424,7 @@

    <

    I can start navigating through the code, and checking the objects that are being generated. If you are not familiar with the commands available in LLDB, I recommend you to read the official documentation of the project3. You can also look for cheat sheets, which quickly describes all commands available for you4.

    Currently, we are in the first line at the main() function. In this line, we create the n object, by executing the add_and_increment() function. To execute the current line of code, and go to the next line, we can run the n LLDB command. Let’s execute this command.

    After we executed this line, we can also look at the value stored inside this n object by using the p LLDB command. The syntax for this command is p <name-of-object>.

    -

    If we take a look at the value stored in the n object (p n), notice that it stores the hexadecimal value 0x06, which is the number 6 in decimal. We can also see that, this value have a type unsigned char, which is an unsigned 8-bit integer. We have talked already about this at Section 1.8, that u8 integers in Zig are equivalent to the C data type unsigned char.

    +

    If we take a look at the value stored in the n object (p n), notice that it stores the hexadecimal value 0x06, which is the number 6 in decimal. We can also see that this value has a type of unsigned char, which is an unsigned 8-bit integer. We have talked already about this at Section 1.8, that u8 integers in Zig are equivalent to the C data type unsigned char.

    (lldb) n
     Process 4798 stopped
     * thread #1, name = 'debugging',
    diff --git a/docs/Chapters/03-structs.html b/docs/Chapters/03-structs.html
    index bcf6dd8f..69a800e7 100644
    --- a/docs/Chapters/03-structs.html
    +++ b/docs/Chapters/03-structs.html
    @@ -497,7 +497,7 @@ 

    Therefore, we can use defer to declare an expression that is going to be executed when your code exits the current scope. Some programmers like to interpret the phrase “exit of the current scope” as “the end of the current scope”. But this interpretation might not be entirely correct, depending on what you consider as “the end of the current scope”.

    -

    I mean, what do you consider as the end of the current scope? Is it the closing curly bracket (}) of the scope? Is it when the last expression in the function get’s executed? Is it when the function returns to the previous scope? Etc. For example, it would not be correct to interpret the “exit of the current scope” as the closing curly bracket of the scope. Because the function might exit from an earlier position than this closing curly bracket (e.g. an error value was generated at a previous line inside the function; the function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.

    +

    I mean, what do you consider as the end of the current scope? Is it the closing curly bracket (}) of the scope? Is it when the last expression in the function gets executed? Is it when the function returns to the previous scope? Etc. For example, it would not be correct to interpret the “exit of the current scope” as the closing curly bracket of the scope. Because the function might exit from an earlier position than this closing curly bracket (e.g. an error value was generated at a previous line inside the function; the function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.

    Now, if you remember of what we have discussed in Section 1.7, there are multiple structures in the language that create their own separate scopes. For/while loops, if/else statements, functions, normal blocks, etc. This also affects the interpretation of defer. For example, if you use defer inside a for loop, then, the given expression will be executed everytime this specific for loop exits its own scope.

    Before we continue, is worth emphasizing that the defer keyword is an “unconditional defer”. Which means that the given expression will be executed no matter how the code exits the current scope. For example, your code might exit the current scope because of an error value being generated, or, because of a return statement, or, a break statement, etc.

    @@ -809,7 +809,7 @@

    Sometimes you don’t need to care about the state of your struct object. Sometimes, you just need to instantiate and use the objects, without altering their state. You can notice that when you have methods inside your struct declaration that might use the values that are present in the data members, but they do not alter the values in these data members of the struct in anyway.

    The Vec3 struct that was presented in Section 2.3.3 is an example of that. This struct have a single method named distance(), and this method does use the values present in all three data members of the struct (x, y and z). But at the same time, this method does not change the values of these data members at any point.

    As a result of that, when we create Vec3 objects we usually create them as constant objects, like the v1 and v2 objects presented in Section 2.3.3. We can create them as variable objects with the var keyword, if we want to. But because the methods of this Vec3 struct do not change the state of the objects in any point, it’s unnecessary to mark them as variable objects.

    -

    But why? Why am I talking about this here? It’s because the self argument in the methods is affected depending on whether the methods present in a struct change or don’t change the state of the object itself. More specifically, when you have a method in a struct that changes the state of the object (i.e. change the value of a data member), the self argument in this method must be annotated in a different manner.

    +

    But why? Why am I talking about this here? It’s because the self argument in the methods are affected depending on whether the methods present in a struct change or don’t change the state of the object itself. More specifically, when you have a method in a struct that changes the state of the object (i.e. changes the value of a data member), the self argument in this method must be annotated in a different manner.

    As I described in Section 2.3.3, the self argument in methods of a struct is the argument that receives as input the object from which the method was called from. We usually annotate this argument in the methods by writing self, followed by the colon character (:), and the data type of the struct to which the method belongs to (e.g. User, Vec3, etc.).

    If we take the Vec3 struct that we defined in the previous section as an example, we can see in the distance() method that this self argument is annotated as self: Vec3. Because the state of the Vec3 object is never altered by this method.

    But what if we do have a method that alters the state of the object, by altering the values of its data members, how should we annotate self in this instance? The answer is: “we should annotate self as a pointer of x, instead of just x”. In other words, you should annotate self as self: *x, instead of annotating it as self: x.

    @@ -877,7 +877,7 @@

    2.4 Type inference

    Zig is a strongly typed language. But, there are some situations where you don’t have to explicitly write the type of every single object in your source code, as you would expect from a traditional strongly typed language, such as C and C++.

    In some situations, the zig compiler can use type inference to solve the data types for you, easing some of the burden that you carry as a developer. The most common way this happens is through function arguments that receive struct objects as input.

    -

    In general, type inference in Zig is done by using the dot character (.). Everytime you see a dot character written before a struct literal, or before an enum value, or something like that, you know that this dot character is playing a special party in this place. More specifically, it is telling the zig compiler something along the lines of: “Hey! Can you infer the type of this value for me? Please!”. In other words, this dot character is playing a similar role as the auto keyword in C++.

    +

    In general, type inference in Zig is done by using the dot character (.). Everytime you see a dot character written before a struct literal, or before an enum value, or something like that, you know that this dot character is playing a special part in this place. More specifically, it is telling the zig compiler something along the lines of: “Hey! Can you infer the type of this value for me? Please!”. In other words, this dot character is playing a similar role as the auto keyword in C++.

    I gave you some examples of this in Section 2.3.1, where we used anonymous struct literals. Anonymous struct literals are, struct literals that use type inference to infer the exact type of this particular struct literal. This type inference is done by looking for some minimal hint of the correct data type to be used. You could say that the zig compiler looks for any neighbouring type annotation that might tell it what the correct type would be.

    Another common place where we use type inference in Zig is at switch statements (which we talked about in Section 2.1.2). I also gave some other examples of type inference in Section 2.1.2, where we were inferring the data types of enum values listed inside of switch statements (e.g. .DE). But as another example, take a look at this fence() function reproduced below, which comes from the atomic.zig module2 of the Zig Standard Library.

    There are a lot of things in this function that we haven’t talked about yet, such as: what comptime means? inline? extern? Let’s just ignore all of these things, and focus solely on the switch statement that is inside this function.

    @@ -927,8 +927,7 @@

    try expect(@TypeOf(y) == u32); }

    -
    1/1 filecdc41797a754.test_0...OKAll 1 tests passed
    -  d.
    +
    1/1 file2ed34a8fc96.test_0...OKAll 1 tests passed.

    This is the general way to perform type casting in Zig. But remember, @as() works only when casting is unambiguous and safe, and there are situations where these assumptions do not hold. For example, when casting an integer value into a float value, or vice-versa, it is not clear to the compiler how to perform this conversion safely.

    @@ -943,7 +942,7 @@

    try expect(@TypeOf(y) == f32); }

    -
    1/1 filecdc428638149.test_0...OKAll 1 tests passed
    +
    1/1 file2ed34bfb9fa5.test_0...OKAll 1 tests passed
       d.

    @@ -960,7 +959,7 @@

    try expect(@TypeOf(u32_ptr) == *const u32); }

    -
    1/1 filecdc46f71cc03.test_0...OKAll 1 tests passed
    +
    1/1 file2ed324328e1f.test_0...OKAll 1 tests passed
       d.
    diff --git a/docs/index.html b/docs/index.html index bb4d7134..de82ec20 100644 --- a/docs/index.html +++ b/docs/index.html @@ -7,7 +7,7 @@ - + Introduction to Zig \n\n\n\n \n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m)\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy an eBook or a physical copy\nof the book on Amazon:\n\n\n\n\n\n\n \n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy)\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/contributors.txt b/contributors.txt index 1c2abddf..80300af6 100644 --- a/contributors.txt +++ b/contributors.txt @@ -19,3 +19,4 @@ Hamza Wahed,@HamzaWahed mwilbur,@mwilbur Dima Budaragin,@dbud Jorge Jímenez,@jorge-j1m +Alexander,@alexwheezy diff --git a/docs/index.html b/docs/index.html index de82ec20..f53295df 100644 --- a/docs/index.html +++ b/docs/index.html @@ -439,7 +439,7 @@

    Acknowledgments

    This book is also a product of many conversations and exchanges that we had with different people from the Zig community. I (Pedro Duarte Faria) am incredibly grateful for these conversations, and also, for some direct contributions that we had. Below we have a list of the people involved (name of the person with their usename in GitHub):

    -

    Calin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m)

    +

    Calin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m), Alexander (@alexwheezy)

    diff --git a/docs/search.json b/docs/search.json index 3c57d704..1999409e 100644 --- a/docs/search.json +++ b/docs/search.json @@ -84,7 +84,7 @@ "href": "index.html#acknowledgments", "title": "Introduction to Zig", "section": "Acknowledgments", - "text": "Acknowledgments\nThis book is also a product of many conversations and exchanges that we had with different people from the Zig community. I (Pedro Duarte Faria) am incredibly grateful for these conversations, and also, for some direct contributions that we had. Below we have a list of the people involved (name of the person with their usename in GitHub):\nCalin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m)", + "text": "Acknowledgments\nThis book is also a product of many conversations and exchanges that we had with different people from the Zig community. I (Pedro Duarte Faria) am incredibly grateful for these conversations, and also, for some direct contributions that we had. Below we have a list of the people involved (name of the person with their usename in GitHub):\nCalin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m), Alexander (@alexwheezy)", "crumbs": [ "Welcome" ] From 9ea48cdba5768a585cf83adf2fdad249fdaa2a92 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 9 Feb 2025 12:05:24 -0300 Subject: [PATCH 064/151] Fix code example --- Chapters/05-pointers.qmd | 15 +++++++++------ .../05-pointers/execute-results/html.json | 8 +++----- docs/Chapters/05-pointers.html | 10 +++++----- docs/search.json | 2 +- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/Chapters/05-pointers.qmd b/Chapters/05-pointers.qmd index 5658c4fc..3e2d8dc1 100644 --- a/Chapters/05-pointers.qmd +++ b/Chapters/05-pointers.qmd @@ -249,14 +249,17 @@ to the first element in the array `ar`. But then, I started to walk through the the pointer with simple pointer arithmetic. ```{zig} -#| eval: false -const ar = [_]i32{1,2,3,4}; -var ptr = &ar; -try stdout.print("{d}\n", .{ptr.*}); +#| eval: true +#| auto_main: true +#| build_type: "run" +#| results: "hide" +const ar = [_]i32{ 1, 2, 3, 4 }; +var ptr: [*]const i32 = &ar; +try stdout.print("{d}\n", .{ptr[0]}); ptr += 1; -try stdout.print("{d}\n", .{ptr.*}); +try stdout.print("{d}\n", .{ptr[0]}); ptr += 1; -try stdout.print("{d}\n", .{ptr.*}); +try stdout.print("{d}\n", .{ptr[0]}); ``` ``` diff --git a/_freeze/Chapters/05-pointers/execute-results/html.json b/_freeze/Chapters/05-pointers/execute-results/html.json index 0cdd4021..bce4789c 100644 --- a/_freeze/Chapters/05-pointers/execute-results/html.json +++ b/_freeze/Chapters/05-pointers/execute-results/html.json @@ -1,11 +1,9 @@ { - "hash": "9520ae65eeada418ccd4d4ca5f8b6f7a", + "hash": "8fdb1694a88afd9b81c337b29ec84c86", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Pointers and Optionals {#sec-pointer}\n\nOn our next project we are going to build a HTTP server from scratch.\nBut in order to do that, we need to learn more about pointers and how they work in Zig.\nPointers in Zig are similar to pointers in C. But they come with some extra advantages in Zig.\n\nA pointer is an object that contains a memory address. This memory address is the address where\na particular value is stored in memory. It can be any value. Most of the times,\nit is a value that comes from another object (or variable) present in our code.\n\nIn the example below, I'm creating two objects (`number` and `pointer`).\nThe `pointer` object contains the memory address where the value of the `number` object\n(the number 5) is stored. So, that is a pointer in a nutshell. It is a memory\naddress that points to a particular existing value in the memory. You could\nalso say, that, the `pointer` object points to the memory address where the `number` object is\nstored.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\n_ = pointer;\n```\n:::\n\n\n\n\nWe create a pointer object in Zig by using the `&` operator. When you put this operator\nbefore the name of an existing object, you get the memory address of this object as result.\nWhen you store this memory address inside a new object, this new object becomes a pointer object.\nBecause it stores a memory address.\n\nPeople mostly use pointers as an alternative way to access a particular value.\nFor example, I can use the `pointer` object to access the value stored by\nthe `number` object. This operation of accessing the value that the\npointer \"points to\" is normally called of *dereferencing the pointer*.\nWe can dereference a pointer in Zig by using the `*` method of the pointer object. Like in the example\nbelow, where we take the number 5 pointed by the `pointer` object,\nand double it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\nconst doubled = 2 * pointer.*;\nstd.debug.print(\"{d}\\n\", .{doubled});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n10\n```\n\n\n:::\n:::\n\n\n\n\n\nThis syntax to dereference the pointer is nice. Because we can easily chain it with\nmethods of the value pointed by the pointer. We can use the `User` struct that we have\ncreated at @sec-structs-and-oop as an example. If you comeback to that section,\nyou will see that this struct have a method named `print_name()`.\n\nSo, for example, if we have an user object, and a pointer that points to this user object,\nwe can use the pointer to access this user object, and, at the same time, call the method `print_name()`\non it, by chaining the dereference method (`*`) with the `print_name()` method. Like in the\nexample below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst u = User.init(1, \"pedro\", \"email@gmail.com\");\nconst pointer = &u;\ntry pointer.*.print_name();\n```\n:::\n\n\n\n\n```\npedro\n```\n\nWe can also use pointers to effectively alter the value of an object.\nFor example, I could use the `pointer` object to set\nthe value of the object `number` to 6, like in the example below.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\n\n\n\nTherefore, as I mentioned earlier, people use pointers as an alternative way to access a particular value.\nAnd they use it especially when they do not want to \"move\" these values around. There are situations where,\nyou want to access a particular value in a different scope (i.e. a different location) of your code,\nbut you do not want to \"move\" this value to this new scope (or location) that you are in.\n\nThis matters especially if this value is big in size. Because if it is, then,\nmoving this value becomes an expensive operation to do.\nThe computer will have to spend a considerable amount of time\ncopying this value to this new location.\n\nTherefore, many programmers prefer to avoid this heavy operation of copying the value\nto the new location, by accessing this value through pointers.\nWe are going to talk more about this \"moving operation\" over the next sections.\nFor now, just keep in mind that avoiding this \"move operation\" is\none of main reasons why pointers are used in programming languages.\n\n\n\n\n\n## Constant objects vs variable objects {#sec-pointer-var}\n\nYou can have a pointer that points to a constant object, or, a pointer that points to a variable object.\nBut regardless of who this pointer is, a pointer **must always respect the characteristics of the object that it points to**.\nAs a consequence, if the pointer points to a constant object, then, you cannot use this pointer\nto change the value that it points to. Because it points to a value that is constant. As we discussed at @sec-assignments, you cannot\nchange a value that is constant.\n\nFor example, if I have a `number` object, which is constant, I cannot execute\nthe expression below where I'm trying to change the value of `number` to 6 through\nthe `pointer` object. As demonstrated below, when you try to do something\nlike that, you get a compile time error:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number = 5;\nconst pointer = &number;\npointer.* = 6;\n```\n:::\n\n\n\n\n```\np.zig:6:12: error: cannot assign to constant\n pointer.* = 6;\n```\n\nIf I change the `number` object to be a variable object, by introducing the `var` keyword,\nthen, I can successfully change the value of this object through a pointer, as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\n\n\nYou can see this relationship between \"constant versus variable\" on the data type of\nyour pointer object. In other words, the data type of a pointer object already gives you\nsome clues about whether the value that it points to is constant or not.\n\nWhen a pointer object points to a constant value, then, this pointer have a data type `*const T`,\nwhich means \"a pointer to a constant value of type `T`\".\nIn contrast, if the pointer points to a variable value, then, the type of the pointer is usually `*T`, which is\nsimply \"a pointer to a value of type `T`\".\nHence, whenever you see a pointer object whose data type is in the format `*const T`, then,\nyou know that you cannot use this pointer to change the value that it points to.\nBecause this pointer points to a constant value of type `T`.\n\n\nWe have talked about the value pointed by the pointer being constant or not,\nand the consequences that arises from it. But, what about the pointer object itself? I mean, what happens\nif the pointer object itself is constant or not? Think about it.\nWe can have a constant pointer that points to a constant value.\nBut we can also have a variable pointer that points to a constant value. And vice-versa.\n\nUntil this point, the `pointer` object was always constant,\nbut what this means for us? What is the consequence of the\n`pointer` object being constant? The consequence is that\nwe cannot change the pointer object, because it is constant. We can use the\npointer object in multiple ways, but we cannot change the\nmemory address that is inside this pointer object.\n\nHowever, if we mark the `pointer` object as a variable object,\nthen, we can change the memory address pointed by this `pointer` object.\nThe example below demonstrates that. Notice that the object pointed\nby the `pointer` object changes from `c1` to `c2`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c1: u8 = 5;\nconst c2: u8 = 6;\nvar pointer = &c1;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\npointer = &c2;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\n```\n:::\n\n\n\n\n```\n5\n6\n```\n\nThus, by setting the `pointer` object to a `var` or `const` object,\nyou specify if the memory address contained in this pointer object can change or not\nin your program. On the other side, you can change the value pointed by the pointer,\nif, and only if this value is stored in a variable object. If this value\nis in a constant object, then, you cannot change this value through a pointer.\n\n\n## Types of pointer\n\nIn Zig, there are two types of pointers [@zigdocs], which are:\n\n- single-item pointer (`*`);\n- many-item pointer (`[*]`);\n\n\nSingle-item pointer objects are objects whose data types are in the format `*T`.\nSo, for example, if an object have a data type `*u32`, it means that, this\nobject contains a single-item pointer that points to an unsigned 32-bit integer value.\nAs another example, if an object have type `*User`, then, it contains\na single-item pointer to an `User` value.\n\nIn contrast, many-item pointers are objects whose data types are in the format `[*]T`.\nNotice that the star symbol (`*`) is now inside a pair of brackets (`[]`). If the star\nsymbol is inside a pair of brackets, you know that this object is a many-item pointer.\n\nWhen you apply the `&` operator over an object, you will always get a single-item pointer.\nMany-item pointers are more of a \"internal type\" of the language, more closely\nrelated to slices. So, when you deliberately create a pointer with the `&` operator,\nyou always get a single-item pointer as result.\n\n\n\n## Pointer arithmetic\n\nPointer arithmetic is available in Zig, and they work the same way they work in C.\nWhen you have a pointer that points to an array, the pointer usually points to\nthe first element in the array, and you can use pointer arithmetic to\nadvance this pointer and access the other elements in the array.\n\n\nNotice in the example below, that initially, the `ptr` object was pointing\nto the first element in the array `ar`. But then, I started to walk through the array, by advancing\nthe pointer with simple pointer arithmetic.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{1,2,3,4};\nvar ptr = &ar;\ntry stdout.print(\"{d}\\n\", .{ptr.*});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr.*});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr.*});\n```\n:::\n\n\n\n\n```\n1\n2\n3\n```\n\nAlthough you can create a pointer to an array like that, and\nstart to walk through this array by using pointer arithmetic,\nin Zig, we prefer to use slices, which were presented at @sec-arrays.\n\nBehind the hood, slices already are pointers,\nand they also come with the `len` property, which indicates\nhow many elements are in the slice. This is good because the `zig` compiler\ncan use it to check for potential buffer overflows, and other problems like that.\n\nAlso, you don't need to use pointer arithmetic to walk through the elements\nof a slice. You can simply use the `slice[index]` syntax to directly access\nany element you want in the slice.\nAs I mentioned at @sec-arrays, you can get a slice from an array by using\na range selector inside brackets. In the example below, I'm creating\na slice (`sl`) that covers the entire `ar` array. I can access any\nelement of `ar` from this slice, and, the slice itself already is a pointer\nbehind the hood.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{1,2,3,4};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\n\n## Optionals and Optional Pointers\n\nLet's talk about optionals and how they relate to pointers in Zig.\nBy default, objects in Zig are **non-nullable**. This means that, in Zig,\nyou can safely assume that any object in your source code is not null.\n\nThis is a powerful feature of Zig when you compare it to the developer experience in C.\nBecause in C, any object can be null at any point, and, as consequence, a pointer in C\nmight point to a null value. This is a common source of undefined behaviour in C.\nWhen programmers work with pointers in C, they have to constantly check if\ntheir pointers are pointing to null values or not.\n\nIf for some reason, your Zig code produces a null value somewhere, and, this null\nvalue ends up in an object that is non-nullable, a runtime error is always\nraised by your Zig program. Take the program below as an example.\nThe `zig` compiler can see the `null` value at compile time, and, as result,\nit raises a compile time error. But, if a `null` value is raised during\nruntime, a runtime error is also raised by the Zig program, with a\n\"attempt to use null value\" message.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nnumber = null;\n```\n:::\n\n\n\n```\np5.zig:5:14: error: expected type 'u8',\n found '@TypeOf(null)'\n number = null;\n ^~~~\n```\n\n\nYou don't get this type of safety in C.\nIn C, you don't get warnings or errors about null values being produced in your program.\nIf for some reason, your code produces a null value in C, most of the times, you end up getting a segmentation fault error\nas result, which can mean many things.\nThat is why programmers have to constantly check for null values in C.\n\nPointers in Zig are also, by default, **non-nullable**. This is another amazing\nfeature in Zig. So, you can safely assume that any pointer that you create in\nyour Zig code is pointing to a non-null value.\nTherefore, you don't have this heavy work of checking if the pointers you create\nin Zig are pointing to a null value.\n\n\n### What are optionals?\n\nOk, we know now that all objects are non-nullable by default in Zig.\nBut what if we actually need to use an object that might receive a null value?\nHere is where optionals come in.\n\nAn optional object in Zig is an object that can be null.\nTo mark an object as optional, we use the `?` operator. When you put\nthis `?` operator right before the data type of an object, you transform\nthis data type into an optional data type, and the object becomes an optional object.\n\nTake the snippet below as an example. We are creating a new variable object\ncalled `num`. This object have the data type `?i32`, which means that,\nthis object contains either a signed 32-bit integer (`i32`), or, a null value.\nBoth alternatives are valid values to the `num` object.\nThat is why, I can actually change the value of this object to null, and,\nno errors are raised by the `zig` compiler, as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\nnum = null;\n```\n:::\n\n\n\n\n### Optional pointers\n\nYou can also mark a pointer object as an optional pointer, meaning that,\nthis object contains either a null value, or, a pointer that points to a value.\nWhen you mark a pointer as optional, the data type of this pointer object\nbecomes `?*const T` or `?*T`, depending if the value pointed by the pointer\nis a constant value or not. The `?` identifies the object as optional, while\nthe `*` identifies it as a pointer object.\n\nIn the example below, we are creating a variable object named `num`, and an\noptional pointer object named `ptr`. Notice that the data type of the object\n`ptr` indicates that it is either a null value, or a pointer to an `i32` value.\nAlso, notice that the pointer object (`ptr`) can be marked as optional, even if\nthe object `num` is not optional.\n\nWhat this code tells us is that, the `num` variable will never contain a null value.\nThis variable will always contain a valid `i32` value. But in contrast, the `ptr` object might contain either a null\nvalue, or, a pointer to an `i32` value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: i32 = 5;\nvar ptr: ?*i32 = #\nptr = null;\nnum = 6;\n```\n:::\n\n\n\n\nBut what happens if we turn the table, and mark the `num` object as optional,\ninstead of the pointer object. If we do that, then, the pointer object is\nnot optional anymore. It would be a similar (although different) result. Because then, we would have\na pointer to an optional value. In other words, a pointer to a value that is either a\nnull value, or, a not-null value.\n\nIn the example below, we are recreating this idea. Now, the `ptr` object\nhave a data type of `*?i32`, instead of `?*i32`. Notice that the `*` symbol comes before of `?`\nthis time. So now, we have a pointer that points to a value that is either null\n, or, a signed 32-bit integer.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\n// ptr have type `*?i32`, instead of `?*i32`.\nconst ptr = #\n_ = ptr;\n```\n:::\n\n\n\n\n\n### Null handling in optionals {#sec-null-handling}\n\nWhen you have an optional object in your Zig code, you have to explicitly handle\nthe possibility of this object being null. It is like error-handling with `try` and `catch`.\nIn Zig you also have to handle null values like if they were a type of error.\n\nWe can do that, by using either:\n\n- an if statement, like you would do in C.\n- the `orelse` keyword.\n- unwrap the optional value with the `?` method.\n\nWhen you use an if statement, you use a pair of pipes\nto unwrap the optional value, and use this \"unwrapped object\"\ninside the if block.\nUsing the example below as a reference, if the object `num` is null,\nthen, the code inside the if statement is not executed. Otherwise,\nthe if statement will unwrap the object `num` into the `not_null_num`\nobject. This `not_null_num` object is guaranteed to be not null inside\nthe scope of the if statement.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst num: ?i32 = 5;\nif (num) |not_null_num| {\n try stdout.print(\"{d}\\n\", .{not_null_num});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n5\n```\n\n\n:::\n:::\n\n\n\n\nNow, the `orelse` keyword behaves like a binary operator. You connect two expressions with this keyword.\nOn the left side of `orelse`, you provide the expression that might result\nin a null value, and on the right side of `orelse`, you provide another expression\nthat will not result in a null value.\n\nThe idea behind the `orelse` keyword is: if the expression on the left side\nresult in a not-null value, then, this not-null value is used. However,\nif this expression on the left side result in a null value, then, the value\nof the expression on the right side is used instead.\n\nLooking at the example below, since the `x` object is currently null, the\n`orelse` decided to use the alternative value, which is the number 15.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x: ?i32 = null;\nconst dbl = (x orelse 15) * 2;\ntry stdout.print(\"{d}\\n\", .{dbl});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n30\n```\n\n\n:::\n:::\n\n\n\n\nYou can use the if statement or the `orelse` keyword, when you want to\nsolve (or deal with) this null value. However, if there is no clear solution\nto this null value, and the most logic and sane path is to simply panic\nand raise a loud error in your program when this null value is encountered,\nyou can use the `?` method of your optional object.\n\nIn essence, when you use this `?` method, the optional object is unwrapped.\nIf a not-null value is found in the optional object, then, this not-null value is used.\nOtherwise, the `unreachable` keyword is used. You can read more about this\n[`unreacheable` keyword at the official documentation](https://ziglang.org/documentation/master/#unreachable)[^un-docs].\nBut in essence, when you build your Zig source code using the build modes `ReleaseSafe` or `Debug`, this\n`unreacheable` keyword causes the program to panic and raise an error during runtime,\nlike in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn return_null(n: i32) ?i32 {\n if (n == 5) return null;\n return n;\n}\n\npub fn main() !void {\n const x: i32 = 5;\n const y: ?i32 = return_null(x);\n try stdout.print(\"{d}\\n\", .{y.?});\n}\n```\n:::\n\n\n\n\n```\nthread 12767 panic: attempt to use null value\np7.zig:12:34: 0x103419d in main (p7):\n try stdout.print(\"{d}\\n\", .{y.?});\n ^\n```\n\n\n[^un-docs]: .\n\n\n", - "supporting": [ - "05-pointers_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Pointers and Optionals {#sec-pointer}\n\nOn our next project we are going to build a HTTP server from scratch.\nBut in order to do that, we need to learn more about pointers and how they work in Zig.\nPointers in Zig are similar to pointers in C. But they come with some extra advantages in Zig.\n\nA pointer is an object that contains a memory address. This memory address is the address where\na particular value is stored in memory. It can be any value. Most of the times,\nit is a value that comes from another object (or variable) present in our code.\n\nIn the example below, I'm creating two objects (`number` and `pointer`).\nThe `pointer` object contains the memory address where the value of the `number` object\n(the number 5) is stored. So, that is a pointer in a nutshell. It is a memory\naddress that points to a particular existing value in the memory. You could\nalso say, that, the `pointer` object points to the memory address where the `number` object is\nstored.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\n_ = pointer;\n```\n:::\n\n\n\n\n\nWe create a pointer object in Zig by using the `&` operator. When you put this operator\nbefore the name of an existing object, you get the memory address of this object as result.\nWhen you store this memory address inside a new object, this new object becomes a pointer object.\nBecause it stores a memory address.\n\nPeople mostly use pointers as an alternative way to access a particular value.\nFor example, I can use the `pointer` object to access the value stored by\nthe `number` object. This operation of accessing the value that the\npointer \"points to\" is normally called of *dereferencing the pointer*.\nWe can dereference a pointer in Zig by using the `*` method of the pointer object. Like in the example\nbelow, where we take the number 5 pointed by the `pointer` object,\nand double it.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\nconst doubled = 2 * pointer.*;\nstd.debug.print(\"{d}\\n\", .{doubled});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n10\n```\n\n\n:::\n:::\n\n\n\n\n\n\nThis syntax to dereference the pointer is nice. Because we can easily chain it with\nmethods of the value pointed by the pointer. We can use the `User` struct that we have\ncreated at @sec-structs-and-oop as an example. If you comeback to that section,\nyou will see that this struct have a method named `print_name()`.\n\nSo, for example, if we have an user object, and a pointer that points to this user object,\nwe can use the pointer to access this user object, and, at the same time, call the method `print_name()`\non it, by chaining the dereference method (`*`) with the `print_name()` method. Like in the\nexample below:\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst u = User.init(1, \"pedro\", \"email@gmail.com\");\nconst pointer = &u;\ntry pointer.*.print_name();\n```\n:::\n\n\n\n\n\n```\npedro\n```\n\nWe can also use pointers to effectively alter the value of an object.\nFor example, I could use the `pointer` object to set\nthe value of the object `number` to 6, like in the example below.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\n\n\n\n\nTherefore, as I mentioned earlier, people use pointers as an alternative way to access a particular value.\nAnd they use it especially when they do not want to \"move\" these values around. There are situations where,\nyou want to access a particular value in a different scope (i.e. a different location) of your code,\nbut you do not want to \"move\" this value to this new scope (or location) that you are in.\n\nThis matters especially if this value is big in size. Because if it is, then,\nmoving this value becomes an expensive operation to do.\nThe computer will have to spend a considerable amount of time\ncopying this value to this new location.\n\nTherefore, many programmers prefer to avoid this heavy operation of copying the value\nto the new location, by accessing this value through pointers.\nWe are going to talk more about this \"moving operation\" over the next sections.\nFor now, just keep in mind that avoiding this \"move operation\" is\none of main reasons why pointers are used in programming languages.\n\n\n\n\n\n## Constant objects vs variable objects {#sec-pointer-var}\n\nYou can have a pointer that points to a constant object, or, a pointer that points to a variable object.\nBut regardless of who this pointer is, a pointer **must always respect the characteristics of the object that it points to**.\nAs a consequence, if the pointer points to a constant object, then, you cannot use this pointer\nto change the value that it points to. Because it points to a value that is constant. As we discussed at @sec-assignments, you cannot\nchange a value that is constant.\n\nFor example, if I have a `number` object, which is constant, I cannot execute\nthe expression below where I'm trying to change the value of `number` to 6 through\nthe `pointer` object. As demonstrated below, when you try to do something\nlike that, you get a compile time error:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number = 5;\nconst pointer = &number;\npointer.* = 6;\n```\n:::\n\n\n\n\n\n```\np.zig:6:12: error: cannot assign to constant\n pointer.* = 6;\n```\n\nIf I change the `number` object to be a variable object, by introducing the `var` keyword,\nthen, I can successfully change the value of this object through a pointer, as demonstrated below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\n\n\n\nYou can see this relationship between \"constant versus variable\" on the data type of\nyour pointer object. In other words, the data type of a pointer object already gives you\nsome clues about whether the value that it points to is constant or not.\n\nWhen a pointer object points to a constant value, then, this pointer have a data type `*const T`,\nwhich means \"a pointer to a constant value of type `T`\".\nIn contrast, if the pointer points to a variable value, then, the type of the pointer is usually `*T`, which is\nsimply \"a pointer to a value of type `T`\".\nHence, whenever you see a pointer object whose data type is in the format `*const T`, then,\nyou know that you cannot use this pointer to change the value that it points to.\nBecause this pointer points to a constant value of type `T`.\n\n\nWe have talked about the value pointed by the pointer being constant or not,\nand the consequences that arises from it. But, what about the pointer object itself? I mean, what happens\nif the pointer object itself is constant or not? Think about it.\nWe can have a constant pointer that points to a constant value.\nBut we can also have a variable pointer that points to a constant value. And vice-versa.\n\nUntil this point, the `pointer` object was always constant,\nbut what this means for us? What is the consequence of the\n`pointer` object being constant? The consequence is that\nwe cannot change the pointer object, because it is constant. We can use the\npointer object in multiple ways, but we cannot change the\nmemory address that is inside this pointer object.\n\nHowever, if we mark the `pointer` object as a variable object,\nthen, we can change the memory address pointed by this `pointer` object.\nThe example below demonstrates that. Notice that the object pointed\nby the `pointer` object changes from `c1` to `c2`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c1: u8 = 5;\nconst c2: u8 = 6;\nvar pointer = &c1;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\npointer = &c2;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\n```\n:::\n\n\n\n\n\n```\n5\n6\n```\n\nThus, by setting the `pointer` object to a `var` or `const` object,\nyou specify if the memory address contained in this pointer object can change or not\nin your program. On the other side, you can change the value pointed by the pointer,\nif, and only if this value is stored in a variable object. If this value\nis in a constant object, then, you cannot change this value through a pointer.\n\n\n## Types of pointer\n\nIn Zig, there are two types of pointers [@zigdocs], which are:\n\n- single-item pointer (`*`);\n- many-item pointer (`[*]`);\n\n\nSingle-item pointer objects are objects whose data types are in the format `*T`.\nSo, for example, if an object have a data type `*u32`, it means that, this\nobject contains a single-item pointer that points to an unsigned 32-bit integer value.\nAs another example, if an object have type `*User`, then, it contains\na single-item pointer to an `User` value.\n\nIn contrast, many-item pointers are objects whose data types are in the format `[*]T`.\nNotice that the star symbol (`*`) is now inside a pair of brackets (`[]`). If the star\nsymbol is inside a pair of brackets, you know that this object is a many-item pointer.\n\nWhen you apply the `&` operator over an object, you will always get a single-item pointer.\nMany-item pointers are more of a \"internal type\" of the language, more closely\nrelated to slices. So, when you deliberately create a pointer with the `&` operator,\nyou always get a single-item pointer as result.\n\n\n\n## Pointer arithmetic\n\nPointer arithmetic is available in Zig, and they work the same way they work in C.\nWhen you have a pointer that points to an array, the pointer usually points to\nthe first element in the array, and you can use pointer arithmetic to\nadvance this pointer and access the other elements in the array.\n\n\nNotice in the example below, that initially, the `ptr` object was pointing\nto the first element in the array `ar`. But then, I started to walk through the array, by advancing\nthe pointer with simple pointer arithmetic.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{ 1, 2, 3, 4 };\nvar ptr: [*]const i32 = &ar;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\n```\n:::\n\n\n\n\n\n```\n1\n2\n3\n```\n\nAlthough you can create a pointer to an array like that, and\nstart to walk through this array by using pointer arithmetic,\nin Zig, we prefer to use slices, which were presented at @sec-arrays.\n\nBehind the hood, slices already are pointers,\nand they also come with the `len` property, which indicates\nhow many elements are in the slice. This is good because the `zig` compiler\ncan use it to check for potential buffer overflows, and other problems like that.\n\nAlso, you don't need to use pointer arithmetic to walk through the elements\nof a slice. You can simply use the `slice[index]` syntax to directly access\nany element you want in the slice.\nAs I mentioned at @sec-arrays, you can get a slice from an array by using\na range selector inside brackets. In the example below, I'm creating\na slice (`sl`) that covers the entire `ar` array. I can access any\nelement of `ar` from this slice, and, the slice itself already is a pointer\nbehind the hood.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{1,2,3,4};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\n\n\n## Optionals and Optional Pointers\n\nLet's talk about optionals and how they relate to pointers in Zig.\nBy default, objects in Zig are **non-nullable**. This means that, in Zig,\nyou can safely assume that any object in your source code is not null.\n\nThis is a powerful feature of Zig when you compare it to the developer experience in C.\nBecause in C, any object can be null at any point, and, as consequence, a pointer in C\nmight point to a null value. This is a common source of undefined behaviour in C.\nWhen programmers work with pointers in C, they have to constantly check if\ntheir pointers are pointing to null values or not.\n\nIf for some reason, your Zig code produces a null value somewhere, and, this null\nvalue ends up in an object that is non-nullable, a runtime error is always\nraised by your Zig program. Take the program below as an example.\nThe `zig` compiler can see the `null` value at compile time, and, as result,\nit raises a compile time error. But, if a `null` value is raised during\nruntime, a runtime error is also raised by the Zig program, with a\n\"attempt to use null value\" message.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nnumber = null;\n```\n:::\n\n\n\n\n```\np5.zig:5:14: error: expected type 'u8',\n found '@TypeOf(null)'\n number = null;\n ^~~~\n```\n\n\nYou don't get this type of safety in C.\nIn C, you don't get warnings or errors about null values being produced in your program.\nIf for some reason, your code produces a null value in C, most of the times, you end up getting a segmentation fault error\nas result, which can mean many things.\nThat is why programmers have to constantly check for null values in C.\n\nPointers in Zig are also, by default, **non-nullable**. This is another amazing\nfeature in Zig. So, you can safely assume that any pointer that you create in\nyour Zig code is pointing to a non-null value.\nTherefore, you don't have this heavy work of checking if the pointers you create\nin Zig are pointing to a null value.\n\n\n### What are optionals?\n\nOk, we know now that all objects are non-nullable by default in Zig.\nBut what if we actually need to use an object that might receive a null value?\nHere is where optionals come in.\n\nAn optional object in Zig is an object that can be null.\nTo mark an object as optional, we use the `?` operator. When you put\nthis `?` operator right before the data type of an object, you transform\nthis data type into an optional data type, and the object becomes an optional object.\n\nTake the snippet below as an example. We are creating a new variable object\ncalled `num`. This object have the data type `?i32`, which means that,\nthis object contains either a signed 32-bit integer (`i32`), or, a null value.\nBoth alternatives are valid values to the `num` object.\nThat is why, I can actually change the value of this object to null, and,\nno errors are raised by the `zig` compiler, as demonstrated below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\nnum = null;\n```\n:::\n\n\n\n\n\n### Optional pointers\n\nYou can also mark a pointer object as an optional pointer, meaning that,\nthis object contains either a null value, or, a pointer that points to a value.\nWhen you mark a pointer as optional, the data type of this pointer object\nbecomes `?*const T` or `?*T`, depending if the value pointed by the pointer\nis a constant value or not. The `?` identifies the object as optional, while\nthe `*` identifies it as a pointer object.\n\nIn the example below, we are creating a variable object named `num`, and an\noptional pointer object named `ptr`. Notice that the data type of the object\n`ptr` indicates that it is either a null value, or a pointer to an `i32` value.\nAlso, notice that the pointer object (`ptr`) can be marked as optional, even if\nthe object `num` is not optional.\n\nWhat this code tells us is that, the `num` variable will never contain a null value.\nThis variable will always contain a valid `i32` value. But in contrast, the `ptr` object might contain either a null\nvalue, or, a pointer to an `i32` value.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: i32 = 5;\nvar ptr: ?*i32 = #\nptr = null;\nnum = 6;\n```\n:::\n\n\n\n\n\nBut what happens if we turn the table, and mark the `num` object as optional,\ninstead of the pointer object. If we do that, then, the pointer object is\nnot optional anymore. It would be a similar (although different) result. Because then, we would have\na pointer to an optional value. In other words, a pointer to a value that is either a\nnull value, or, a not-null value.\n\nIn the example below, we are recreating this idea. Now, the `ptr` object\nhave a data type of `*?i32`, instead of `?*i32`. Notice that the `*` symbol comes before of `?`\nthis time. So now, we have a pointer that points to a value that is either null\n, or, a signed 32-bit integer.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\n// ptr have type `*?i32`, instead of `?*i32`.\nconst ptr = #\n_ = ptr;\n```\n:::\n\n\n\n\n\n\n### Null handling in optionals {#sec-null-handling}\n\nWhen you have an optional object in your Zig code, you have to explicitly handle\nthe possibility of this object being null. It is like error-handling with `try` and `catch`.\nIn Zig you also have to handle null values like if they were a type of error.\n\nWe can do that, by using either:\n\n- an if statement, like you would do in C.\n- the `orelse` keyword.\n- unwrap the optional value with the `?` method.\n\nWhen you use an if statement, you use a pair of pipes\nto unwrap the optional value, and use this \"unwrapped object\"\ninside the if block.\nUsing the example below as a reference, if the object `num` is null,\nthen, the code inside the if statement is not executed. Otherwise,\nthe if statement will unwrap the object `num` into the `not_null_num`\nobject. This `not_null_num` object is guaranteed to be not null inside\nthe scope of the if statement.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst num: ?i32 = 5;\nif (num) |not_null_num| {\n try stdout.print(\"{d}\\n\", .{not_null_num});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n5\n```\n\n\n:::\n:::\n\n\n\n\n\nNow, the `orelse` keyword behaves like a binary operator. You connect two expressions with this keyword.\nOn the left side of `orelse`, you provide the expression that might result\nin a null value, and on the right side of `orelse`, you provide another expression\nthat will not result in a null value.\n\nThe idea behind the `orelse` keyword is: if the expression on the left side\nresult in a not-null value, then, this not-null value is used. However,\nif this expression on the left side result in a null value, then, the value\nof the expression on the right side is used instead.\n\nLooking at the example below, since the `x` object is currently null, the\n`orelse` decided to use the alternative value, which is the number 15.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x: ?i32 = null;\nconst dbl = (x orelse 15) * 2;\ntry stdout.print(\"{d}\\n\", .{dbl});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n30\n```\n\n\n:::\n:::\n\n\n\n\n\nYou can use the if statement or the `orelse` keyword, when you want to\nsolve (or deal with) this null value. However, if there is no clear solution\nto this null value, and the most logic and sane path is to simply panic\nand raise a loud error in your program when this null value is encountered,\nyou can use the `?` method of your optional object.\n\nIn essence, when you use this `?` method, the optional object is unwrapped.\nIf a not-null value is found in the optional object, then, this not-null value is used.\nOtherwise, the `unreachable` keyword is used. You can read more about this\n[`unreacheable` keyword at the official documentation](https://ziglang.org/documentation/master/#unreachable)[^un-docs].\nBut in essence, when you build your Zig source code using the build modes `ReleaseSafe` or `Debug`, this\n`unreacheable` keyword causes the program to panic and raise an error during runtime,\nlike in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn return_null(n: i32) ?i32 {\n if (n == 5) return null;\n return n;\n}\n\npub fn main() !void {\n const x: i32 = 5;\n const y: ?i32 = return_null(x);\n try stdout.print(\"{d}\\n\", .{y.?});\n}\n```\n:::\n\n\n\n\n\n```\nthread 12767 panic: attempt to use null value\np7.zig:12:34: 0x103419d in main (p7):\n try stdout.print(\"{d}\\n\", .{y.?});\n ^\n```\n\n\n[^un-docs]: .\n\n\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/docs/Chapters/05-pointers.html b/docs/Chapters/05-pointers.html index d14f04a5..1bc398f2 100644 --- a/docs/Chapters/05-pointers.html +++ b/docs/Chapters/05-pointers.html @@ -426,13 +426,13 @@

    Pointer arithmetic is available in Zig, and they work the same way they work in C. When you have a pointer that points to an array, the pointer usually points to the first element in the array, and you can use pointer arithmetic to advance this pointer and access the other elements in the array.

    Notice in the example below, that initially, the ptr object was pointing to the first element in the array ar. But then, I started to walk through the array, by advancing the pointer with simple pointer arithmetic.

    -
    const ar = [_]i32{1,2,3,4};
    -var ptr = &ar;
    -try stdout.print("{d}\n", .{ptr.*});
    +
    const ar = [_]i32{ 1, 2, 3, 4 };
    +var ptr: [*]const i32 = &ar;
    +try stdout.print("{d}\n", .{ptr[0]});
     ptr += 1;
    -try stdout.print("{d}\n", .{ptr.*});
    +try stdout.print("{d}\n", .{ptr[0]});
     ptr += 1;
    -try stdout.print("{d}\n", .{ptr.*});
    +try stdout.print("{d}\n", .{ptr[0]});
    1
     2
    diff --git a/docs/search.json b/docs/search.json
    index 1999409e..d9730825 100644
    --- a/docs/search.json
    +++ b/docs/search.json
    @@ -514,7 +514,7 @@
         "href": "Chapters/05-pointers.html#pointer-arithmetic",
         "title": "6  Pointers and Optionals",
         "section": "6.3 Pointer arithmetic",
    -    "text": "6.3 Pointer arithmetic\nPointer arithmetic is available in Zig, and they work the same way they work in C. When you have a pointer that points to an array, the pointer usually points to the first element in the array, and you can use pointer arithmetic to advance this pointer and access the other elements in the array.\nNotice in the example below, that initially, the ptr object was pointing to the first element in the array ar. But then, I started to walk through the array, by advancing the pointer with simple pointer arithmetic.\n\nconst ar = [_]i32{1,2,3,4};\nvar ptr = &ar;\ntry stdout.print(\"{d}\\n\", .{ptr.*});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr.*});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr.*});\n\n1\n2\n3\nAlthough you can create a pointer to an array like that, and start to walk through this array by using pointer arithmetic, in Zig, we prefer to use slices, which were presented at Section 1.6.\nBehind the hood, slices already are pointers, and they also come with the len property, which indicates how many elements are in the slice. This is good because the zig compiler can use it to check for potential buffer overflows, and other problems like that.\nAlso, you don’t need to use pointer arithmetic to walk through the elements of a slice. You can simply use the slice[index] syntax to directly access any element you want in the slice. As I mentioned at Section 1.6, you can get a slice from an array by using a range selector inside brackets. In the example below, I’m creating a slice (sl) that covers the entire ar array. I can access any element of ar from this slice, and, the slice itself already is a pointer behind the hood.\n\nconst ar = [_]i32{1,2,3,4};\nconst sl = ar[0..ar.len];\n_ = sl;",
    +    "text": "6.3 Pointer arithmetic\nPointer arithmetic is available in Zig, and they work the same way they work in C. When you have a pointer that points to an array, the pointer usually points to the first element in the array, and you can use pointer arithmetic to advance this pointer and access the other elements in the array.\nNotice in the example below, that initially, the ptr object was pointing to the first element in the array ar. But then, I started to walk through the array, by advancing the pointer with simple pointer arithmetic.\n\nconst ar = [_]i32{ 1, 2, 3, 4 };\nvar ptr: [*]const i32 = &ar;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\n\n1\n2\n3\nAlthough you can create a pointer to an array like that, and start to walk through this array by using pointer arithmetic, in Zig, we prefer to use slices, which were presented at Section 1.6.\nBehind the hood, slices already are pointers, and they also come with the len property, which indicates how many elements are in the slice. This is good because the zig compiler can use it to check for potential buffer overflows, and other problems like that.\nAlso, you don’t need to use pointer arithmetic to walk through the elements of a slice. You can simply use the slice[index] syntax to directly access any element you want in the slice. As I mentioned at Section 1.6, you can get a slice from an array by using a range selector inside brackets. In the example below, I’m creating a slice (sl) that covers the entire ar array. I can access any element of ar from this slice, and, the slice itself already is a pointer behind the hood.\n\nconst ar = [_]i32{1,2,3,4};\nconst sl = ar[0..ar.len];\n_ = sl;",
         "crumbs": [
           "6  Pointers and Optionals"
         ]
    
    From e2491f6907bf9049a7445eea128d67af10ef0372 Mon Sep 17 00:00:00 2001
    From: Niklas Johansson 
    Date: Fri, 14 Feb 2025 08:41:11 +0100
    Subject: [PATCH 065/151] fix: Remove unnecessary swear word
    
    While reading the physical book I came across an unnecessary swear word.
    Personally, I am not against swear words but this one felt unnecessary
    and makes the book feel less professional.
    
    I updated both the string and base64 encoding.
    
    Thank you for writing this book.
    
    I assign the copyright of this contribution to Pedro Duarte Faria.
    ---
     Chapters/01-base64.qmd | 8 ++++----
     1 file changed, 4 insertions(+), 4 deletions(-)
    
    diff --git a/Chapters/01-base64.qmd b/Chapters/01-base64.qmd
    index fabfc797..962f63bb 100644
    --- a/Chapters/01-base64.qmd
    +++ b/Chapters/01-base64.qmd
    @@ -834,8 +834,8 @@ var fba = std.heap.FixedBufferAllocator.init(
     );
     const allocator = fba.allocator();
     
    -const text = "Testing some more shit";
    -const etext = "VGVzdGluZyBzb21lIG1vcmUgc2hpdA==";
    +const text = "Testing some more stuff";
    +const etext = "VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=";
     const base64 = Base64.init();
     const encoded_text = try base64.encode(
         allocator, text
    @@ -852,8 +852,8 @@ try stdout.print(
     ```
     
     ```
    -Encoded text: VGVzdGluZyBzb21lIG1vcmUgc2hpdA==
    -Decoded text: Testing some more shit
    +Encoded text: VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=
    +Decoded text: Testing some more stuff
     ```
     
     You can also see the full source code at once, by visiting the official repository of this book[^repo].
    
    From 139721f72172e219e769fc9b87bb0f662ca87f22 Mon Sep 17 00:00:00 2001
    From: Maarten Coppens 
    Date: Sat, 15 Feb 2025 11:39:01 +0100
    Subject: [PATCH 066/151] Update 01-zig-weird.qmd
    
    fix typo
    ---
     Chapters/01-zig-weird.qmd | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/Chapters/01-zig-weird.qmd b/Chapters/01-zig-weird.qmd
    index 125bdad3..1a1afa74 100644
    --- a/Chapters/01-zig-weird.qmd
    +++ b/Chapters/01-zig-weird.qmd
    @@ -58,7 +58,7 @@ C are a frequent source of confusion. They really make it sometimes hard to debu
     C programs. Because macros are essentially a second language embedded in C that obscures
     your C code. With macros, you are no longer 100% sure about which pieces
     of the code are being sent to the compiler, i.e.
    -they obscures the actual source code that you wrote.
    +they obscure the actual source code that you wrote.
     
     You don't have macros in Zig. In Zig, the code you write, is the actual code that get's compiled by the compiler.
     You also don't have a hidden control flow happening behind the scenes. And, you also
    
    From 2294c2d9fef7b4d29898c45117b2ea548b00ae52 Mon Sep 17 00:00:00 2001
    From: pedropark99 
    Date: Sat, 15 Feb 2025 20:11:12 -0300
    Subject: [PATCH 067/151] Recompile book with changes
    
    ---
     _freeze/Chapters/01-base64/execute-results/html.json    | 4 ++--
     _freeze/Chapters/01-zig-weird/execute-results/html.json | 8 +++++---
     docs/Chapters/01-base64.html                            | 8 ++++----
     docs/Chapters/01-zig-weird.html                         | 2 +-
     docs/index.html                                         | 4 ++--
     docs/search.json                                        | 4 ++--
     6 files changed, 16 insertions(+), 14 deletions(-)
    
    diff --git a/_freeze/Chapters/01-base64/execute-results/html.json b/_freeze/Chapters/01-base64/execute-results/html.json
    index 0965e634..9eb2b631 100644
    --- a/_freeze/Chapters/01-base64/execute-results/html.json
    +++ b/_freeze/Chapters/01-base64/execute-results/html.json
    @@ -1,8 +1,8 @@
     {
    -  "hash": "225506bc4affdcc5aaf897c63caf73a4",
    +  "hash": "f1304b563ed8036a5bbeaa9b658cfdf0",
       "result": {
         "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 1 - Building a base64 encoder/decoder {#sec-base64}\n\nAs our first small project, I want to implement a base64 encoder/decoder with you.\nBase64 is an encoding system which translates binary data to text.\nA big chunk of the web uses base64 to deliver binary data to systems\nthat can only read text data.\n\nThe most common example of a modern use case for base64 is essentially any email system,\nlike GMail, Outlook, etc. Because email systems normally use\nthe Simple Mail Transfer Protocol (SMTP), which is a web protocol\nthat supports only text data. So, if you need, for any reason, to\nsend a binary file (like for example, a PDF, or an Excel file) as\nan attachment in your email, these binary files are normally\nconverted to base64, before they are included in the SMTP message.\nSo, the base64 encoding is largely used in these email systems to include\nbinary data into the SMTP message.\n\n\n\n\n\n\n## How the base64 algorithm work?\n\nBut how exactly does the algorithm behind the base64 encoding work? Let's discuss that. First, I will\nexplain the base64 scale, which is the 64-character scale that is the basis for\nthe base64 encoding system.\n\nAfter that, I explain the algorithm behind a base64 encoder, which is the part of the algorithm that is responsible for encoding messages\ninto the base64 encoding system. Then, after that, I explain the algorithm behind a base64 decoder, which is\nthe part of the algorithm that is responsible for translating base64 messages back into their original meaning.\n\nIf you are unsure about the differences between an \"encoder\" and a \"decoder\",\ntake a look at @sec-encode-vs-decode.\n\n\n### The base64 scale {#sec-base64-scale}\n\nThe base64 encoding system is based on a scale that goes from 0 to 63 (hence the name).\nEach index in this scale is represented by a character (it is a scale of 64 characters).\nSo, in order to convert some binary data, to the base64 encoding, we need to convert each binary number to the corresponding\ncharacter in this \"scale of 64 characters\".\n\nThe base64 scale starts with all ASCII uppercase letters (A to Z) which represents\nthe first 25 indexes in this scale (0 to 25). After that, we have all ASCII lowercase letters\n(a to z), which represents the range 26 to 51 in the scale. After that, we\nhave the one digit numbers (0 to 9), which represents the indexes from 52 to 61 in the scale.\nFinally, the last two indexes in the scale (62 and 63) are represented by the characters `+` and `/`,\nrespectively.\n\nThese are the 64 characters that compose the base64 scale. The equal sign character (`=`) is not part of the scale itself,\nbut it is a special character in the base64 encoding system. This character is used solely as a suffix, to mark the end of the character sequence,\nor, to mark the end of meaningful characters in the sequence.\n\nThe bullet points below summarises the base64 scale:\n\n- range 0 to 25 is represented by: ASCII uppercase letters `-> [A-Z]`;\n- range 26 to 51 is represented by: ASCII lowercase letters `-> [a-z]`;\n- range 52 to 61 is represented by: one digit numbers `-> [0-9]`;\n- index 62 and 63 are represented by the characters `+` and `/`, respectively;\n- the character `=` represents the end of meaningful characters in the sequence;\n\n\n\n\n### Creating the scale as a lookup table {#sec-base64-table}\n\nThe best way to represent this scale in code, is to represent it as a *lookup table*.\nLookup tables are a classic strategy in computer science to speed up calculations. The basic idea\nis to replace a runtime calculation (which can take a long time to be done) with a basic array indexing\noperation.\n\nInstead of calculating the results everytime you need them, you calculate all possible results at once, and then, you store them in an array\n(which behaves lake a \"table\"). Then, every time you need to use one of the characters in the base64 scale, instead of\nusing many resources to calculate the exact character to be used, you simply retrieve this character\nfrom the array where you stored all the possible characters in the base64 scale.\nWe retrieve the character that we need directly from memory.\n\nWe can start building a Zig struct to store our base64 decoder/encoder logic.\nWe start with the `Base64` struct below. For now, we only have one single data member in this\nstruct, i.e. the member `_table`, which represents our lookup table. We also have an `init()` method,\nto create a new instance of a `Base64` object, and, a `_char_at()` method, which is a\n\"get character at index $x$\" type of function.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Base64 = struct {\n    _table: *const [64]u8,\n\n    pub fn init() Base64 {\n        const upper = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n        const lower = \"abcdefghijklmnopqrstuvwxyz\";\n        const numbers_symb = \"0123456789+/\";\n        return Base64{\n            ._table = upper ++ lower ++ numbers_symb,\n        };\n    }\n\n    pub fn _char_at(self: Base64, index: usize) u8 {\n        return self._table[index];\n    }\n};\n```\n:::\n\n\n\n\n\nIn other words, the `_char_at()` method is responsible for getting the character in the lookup\ntable (i.e. the `_table` struct data member) that corresponds to a particular index in the\n\"base64 scale\". So, in the example below, we know that the character that corresponds to the\nindex 28 in the \"base64 scale\" is the character \"c\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst base64 = Base64.init();\ntry stdout.print(\n    \"Character at index 28: {c}\\n\",\n    .{base64._char_at(28)}\n);\n```\n:::\n\n\n\n\n```\nCharacter at index 28: c\n```\n\n\n\n### A base64 encoder {#sec-base64-encoder-algo}\n\nThe algorithm behind a base64 encoder usually works on a window of 3 bytes. Because each byte has\n8 bits, so, 3 bytes forms a set of $8 \\times 3 = 24$ bits. This is desirable for the base64 algorithm, because\n24 bits is divisible by 6, which forms $24 / 6 = 4$ groups of 6 bits each.\n\nTherefore, the base64 algorithm works by converting 3 bytes at a time\ninto 4 characters from the base64 scale. It keeps iterating through the input string,\n3 bytes at a time, and converting them into the base64 scale, producing 4 characters\nper iteration. It keeps iterating, and producing these \"new characters\"\nuntil it hits the end of the input string.\n\nNow, you may think, what if you have a particular string that have a number of bytes\nthat is not divisible by 3? What happens? For example, if you have a string\nthat contains only two characters/bytes, such as \"Hi\". How the\nalgorithm would behave in such situation? You find the answer at @fig-base64-algo1.\nYou can see at @fig-base64-algo1 that the string \"Hi\", when converted to base64,\nbecomes the string \"SGk=\":\n\n![The logic behind a base64 encoder](./../Figures/base64-encoder-flow.png){#fig-base64-algo1}\n\nTaking the string \"Hi\" as an example, we have 2 bytes, or, 16 bits in total. So, we lack a full byte (8 bits)\nto complete the window of 24 bits that the base64 algorithm likes to work on. The first thing that\nthe algorithm does, is to check how to divide the input bytes into groups of 6 bits.\n\nIf the algorithm notices that there is a group of 6 bits that, have some bits in it, but, at the same time, it is not full\n(in other words, $0 < nbits < 6$, being $nbits$ the number of bits), meaning that, it lacks\nsome bits to fill the 6-bits requirement, the algorithm simply add extra zeros in this group\nto fill the space that it needs. That is why at @fig-base64-algo1, on the third group after the 6-bit transformation,\n2 extra zeros were added to fill the gap in this group.\n\nWhen we have a 6-bit group that is not completely full, like the third group, extra zeros\nare added to fill the gap. But what about when an entire 6-bit group is empty, or, it\nsimply doesn't exist? This is the case of the fourth 6-bit group exposed at\n@fig-base64-algo1.\n\nThis fourth group is necessary, because the algorithm works on 4 groups of 6 bits.\nBut the input string does not have enough bytes to create a fourth 6-bit group.\nEvery time this happens, where an entire group of 6 bits is empty,\nthis group becomes a \"padding group\". Every \"padding group\" is mapped to\nthe character `=` (equal sign), which represents \"null\", or, the end\nof meaningful characters in the sequence. Hence, everytime that the algorithm produces a\n\"padding group\", this group is automatically mapped to `=`.\n\nAs another example, if you give the string \"0\" as input to a base64 encoder, this string is\ntranslated into the base64 sequence \"MA==\".\nThe character \"0\" is, in binary, the sequence `00110000`[^zero-note]. So, with the 6-bit transformation\nexposed at @fig-base64-algo1, this single character would produce these two 6-bit groups: `001100`, `000000`.\nThe remaining two 6-bit groups become \"padding groups\". That is why the last\ntwo characters in the output sequence (MA==) are `==`.\n\n\n[^zero-note]: Notice that, the character \"0\" is different than the actual number 0, which is simply zero in binary.\n\n### A base64 decoder {#sec-base64-decoder-algo}\n\nThe algorithm behind a base64 decoder is essentially the inverse process of a base64 encoder.\nA base64 decoder needs to translate base64 messages back into their original meaning,\ni.e. into the original sequence of binary data.\n\nA base64 decoder usually works on a window of 4 bytes. Because it wants to convert these 4 bytes\nback into the original sequence of 3 bytes, that was converted into 4 groups of 6 bits by the\nbase64 encoder. Remember, in a base64 decoder we are essentially reverting the process made\nby the base64 encoder.\n\nEach byte in the input string (the base64 encoded string) normally contributes to re-create\ntwo different bytes in the output (the original binary data).\nIn other words, each byte that comes out of a base64 decoder is created by transforming merging two different\nbytes in the input together. You can visualize this relationship at @fig-base64-algo2:\n\n![The logic behind a base64 decoder](./../Figures/base64-decoder-flow.png){#fig-base64-algo2}\n\nThe exact transformations, or, the exact steps applied to each byte from the input to transform them\ninto the bytes of the output, are a bit tricky to visualize in a figure like this. Because of that, I have\nsummarized these transformations as \"Some bit shifting and additions ...\" in the figure. These transformations\nwill be described in depth later.\n\nBesides that, if you look again at @fig-base64-algo2, you will notice that the character `=` was completely\nignored by the algorithm. Remember, this is just a special character that marks the end of meaningful characters\nin the base64 sequence. So, every `=` character in a base64 encoded sequence should be ignored by a base64 decoder.\n\n\n## Difference between encode and decode {#sec-encode-vs-decode}\n\nIf you don't have any previous experience with base64, you might not understand the differences\nbetween \"encode\" and \"decode\". Essentially, the terms \"encode\" and \"decode\" here\nhave the exact same meaning as they have in the field of encryption (i.e. they mean the same thing as \"encode\" and \"decode\" in hashing\nalgorithms, like the MD5 algorithm).\n\nThus, \"encode\" means that we want to encode, or, in other words, we want to translate some message into\nthe base64 encoding system. We want to produce the sequence of base64 characters that represent this\noriginal message in the base64 encoding system.\n\nIn contrast, \"decode\" represents the inverse process.\nWe want to decode, or, in other words, translate a base64 message back to its original content.\nSo, in this process we get a sequence of base64 characters as input, and produce as output,\nthe binary data that is represented by this sequence of base64 characters.\n\nAny base64 library is normally composed of these two parts: 1) the encoder, which is a function that encodes\n(i.e. it converts) any sequence of binary data into a sequence of base64 characters; 2) the decoder, which is a function\nthat converts a sequence of base64 characters back into the original sequence of binary data.\n\n\n\n## Calculating the size of the output {#sec-base64-length-out}\n\nOne task that we need to do is to calculate how much space we need to reserve for the\noutput, both of the encoder and decoder. This is simple math, and can be done easily in Zig\nbecause every array has its length (its number of elements) easily accesible by consulting\nthe `.len` property of the array.\n\nFor the encoder, the logic is the following: for each 3 bytes that we find in the input,\n4 new bytes are created in the output. So, we take the number of bytes in the input, divide it\nby 3, use a ceiling function, then, we multiply the result by 4. That way, we get the total\nnumber of bytes that will be produced by the encoder in its output.\n\nThe `_calc_encode_length()` function below encapsulates this logic.\nInside this function, we take the length of the input array,\nwe divide it by 3, and apply a ceil operation over the result by using the\n`divCeil()` function from the Zig Standard Library. Lastly, we multiply\nthe end result by 4 to get the answer we need.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_encode_length(input: []const u8) !usize {\n    if (input.len < 3) {\n        const n_output: usize = 4;\n        return n_output;\n    }\n    const n_output: usize = try std.math.divCeil(\n        usize, input.len, 3\n    );\n    return n_output * 4;\n}\n```\n:::\n\n\n\n\n\nAlso, you might have notice that, if the input length is less than 3 bytes, then, the output length of the encoder is\nalways 4 bytes. This is the case for every input with less than 3 bytes, because, as I described at @sec-base64-encoder-algo,\nthe algorithm always produces enough \"padding-groups\" in the end result, to complete the 4 bytes window.\n\nNow, for the decoder, we just need to apply the inverse logic: for each 4 bytes in the input, 3 bytes\nwill be produced in the output of the decoder. I mean, this is roughly true, because we also need to\ntake the `=` character into account, which is always ignored by the decoder, as we described at @sec-base64-decoder-algo, and,\nat @fig-base64-algo2. But we can ignore this fact for now, just to keep things simple.\n\nThe function `_calc_decode_length()` exposed below summarizes this logic that we described. It is very similar\nto the function `_calc_encode_length()`. Only the division part is twisted, and also, in the special\ncase where we have less than 4 bytes in the input to work on. Also notice that this time, we apply\na floor operation over the output of the division, by using the `divFloor()`\nfunction (instead of a ceiling operation with `divCeil()`).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_decode_length(input: []const u8) !usize {\n    if (input.len < 4) {\n        const n_output: usize = 3;\n        return n_output;\n    }\n    const n_output: usize = try std.math.divFloor(\n        usize, input.len, 4\n    );\n    return n_output * 3;\n}\n```\n:::\n\n\n\n\n\n## Building the encoder logic {#sec-encoder-logic}\n\nIn this section, we can start building the logic behind the `encode()` function, which\nwill be responsible for encoding messages into the base64 encoding system.\nIf you are an anxious person, and you want to see now the full source code of the implementation\nfor this base64 encoder/decoder, you can find it at the `ZigExamples` folder in the official repository of\nthis book[^zig-base64-algo].\n\n[^zig-base64-algo]: .\n\n\n\n### The 6-bit transformation {#sec-6bit-transf}\n\nThe 6-bit transformation presented at @fig-base64-algo1 is the core part of the base64 encoder algorithm.\nBy understanding how this transformation is made in code, the rest of the algorithm becomes much simpler\nto comprehend.\n\nIn essence, this 6-bit transformation is made with the help of bitwise operators.\nBitwise operators are essential to any type of low-level operation that is done at the bit-level. For the specific case of the base64 algorithm,\nthe operators *bif shift to the left* (`<<`), *bit shift to the right* (`>>`), and the *bitwise and* (`&`) are used. They\nare the core solution for the 6-bit transformation.\n\nThere are 3 different scenarios that we need to take into account in this transformation. First, is the perfect scenario,\nwhere we have the perfect window of 3 bytes to work on. Second, we have the scenario where we have a window of only\ntwo bytes to work with. And last, we have the scenario where we have a window of one single byte.\n\nIn each of these 3 scenarios, the 6-bit transformation works a bit differently. To make the explanation\neasier, I will use the variable `output` to refer to the bytes in the output of the base64 encoder,\nand the variable `input` to refer to the bytes in the input of the encoder.\n\n\nSo, if you have the perfect window of 3 bytes, these are steps for the 6-bit transformation:\n\n1. `output[0]` is produced by moving the bits from `input[0]` two positions to the right.\n1. `output[1]` is produced by summing two components. First, take the last two bits from `input[0]`, then, move them four positions to the left. Second, move the bits from `input[1]` four positions to the right. Sum these two components.\n1. `output[2]` is produced by summing two components. First, take the last four bits from `input[1]`, then, move them two positions to the left. Second, move the bits from `input[2]` six positions to the right. Sum these two components.\n1. `output[3]` is produced by taking the last six bits from `input[2]`.\n\n\nThis is the perfect scenario, where we have a full window of 3 bytes to work on.\nJust to make things as clear as possible, the @fig-encoder-bitshift demonstrates visually how\nthe step 2 mentioned above works. So the 2nd byte in the `output` of the encoder, is made by taking the 1st byte (dark purple)\nand the 2nd byte (orange) from the input. You can see that, at the end of the process, we get a new\nbyte that contains the last 2 bits from the 1st byte in the `input`, and the first 4 bits\nfrom the 2nd byte in the `input`.\n\n![How the 2nd byte in the output of the encoder is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input.](../Figures/base64-encoder-bit-shift.png){#fig-encoder-bitshift}\n\nOn the other hand, we must be prepared for the instances where we do not have the perfect window of 3 bytes.\nIf you have a window of 2 bytes, then, the steps 3 and 4, which produces the bytes `output[2]` and `output[3]`, change a little bit,\nand they become:\n\n- `output[2]` is produced by taking the last 4 bits from `input[1]`, then, move them two positions to the left.\n- `output[3]` is the character `'='`.\n\n\nFinally, if you have a window of a single byte, then, the steps 2 to 4, which produces the bytes `output[1]`, `output[2]` and `output[3]` change,\nbecoming:\n\n- `output[1]` is produced by taking the last two bits from `input[0]`, then, move them four positions to the left.\n- `output[2]` and `output[3]` are the character `=`.\n\n\nIf these bullet points were a bit confusing for you, you may find the @tbl-transf-6bit more intuitive.\nThis table unifies all this logic into a simple table. Notice that\nthis table also provides the exact expression in Zig that creates the corresponding\nbyte in the output.\n\n\n::: {#tbl-transf-6bit}\n\n| Number of bytes in the window | Byte index in the output | In code                                    |\n|-------------------------------|--------------------------|--------------------------------------------|\n| 3                             | 0                        | input[0] >> 2                              |\n| 3                             | 1                        | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 3                             | 2                        | ((input[1] & 0x0f) << 2) + (input[2] >> 6) |\n| 3                             | 3                        | input[2] & 0x3f                            |\n| 2                             | 0                        | input[0] >> 2                              |\n| 2                             | 1                        | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 2                             | 2                        | ((input[1] & 0x0f) << 2)                   |\n| 2                             | 3                        | '='                                        |\n| 1                             | 0                        | input[0] >> 2                              |\n| 1                             | 1                        | ((input[0] & 0x03) << 4)                   |\n| 1                             | 2                        | '='                                        |\n| 1                             | 3                        | '='                                        |\n\n: How the 6-bit transformation translates into code in different window settings.\n\n:::\n\n\n\n\n\n\n### Bit-shifting in Zig\n\nBit-shifting in Zig works similarly to bit-shifting in C.\nAll bitwise operators that exist in C are available in Zig.\nHere, in the base64 encoder algorithm, they are essential\nto produce the result we want.\n\nFor those who are not familiar with these operators, they are\noperators that operates at the bit-level of your values.\nThis means that these operators takes the bits that form the value\nyou have, and change them in some way. This ultimately also changes\nthe value itself, because the binary representation of this value\nchanges.\n\nWe have already seen at @fig-encoder-bitshift the effect produced by a bit-shift.\nBut let's use the first byte in the output of the base64 encoder as another example of what\nbit-shifting means. This is the easiest byte of the 4 bytes in the output\nto build. Because we only need to move the bits from the first byte in the input two positions to the right,\nwith the *bit shift to the right* (`>>`) operator.\n\nIf we take the string \"Hi\" that we used at @fig-base64-algo1 as an example, the first byte in\nthis string is \"H\", which is the sequence `01001000` in binary.\nIf we move the bits of this byte, two places to the right, we get the sequence `00010010` as result.\nThis binary sequence is the value `18` in decimal, and also, the value `0x12` in hexadecimal.\nNotice that the first 6 bits of \"H\" were moved to the end of the byte.\nWith this operation, we get the first byte of the output.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const input = \"Hi\";\n    try stdout.print(\"{d}\\n\", .{input[0] >> 2});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n18\n```\n\n\n:::\n:::\n\n\n\n\nIf you recall @fig-base64-algo1, the first byte present in the output should\nbe equivalent to the 6-bit group `010010`. Although being visually different, the\nsequences `010010` and `00010010` are semantically equal. They mean the same thing.\nThey both represent the number 18 in decimal, and the value `0x12` in hexadecimal.\n\nSo, don't take the \"6-bit group\" factor so seriously. We do not need necessarily to\nget a 6-bit sequence as result. As long as the meaning of the 8-bit sequence we get is the same\nof the 6-bit sequence, we are in the clear.\n\n\n\n### Selecting specific bits with the `&` operator\n\nIf you comeback to @sec-6bit-transf, you will see that, in order to produce\nthe second and third bytes in the output, we need to select specific\nbits from the first and second bytes in the input string. But how\ncan we do that? The answer relies on the *bitwise and* (`&`) operator.\n\nThe @fig-encoder-bitshift already showed you what effect this `&` operator\nproduces in the bits of its operands. But let's make a clear description of it.\n\nIn summary, the `&` operator performs a logical conjunction operation\nbetween the bits of its operands. In more details, the operator `&`\ncompares each bit of the first operand to the corresponding bit of the second operand.\nIf both bits are 1, the corresponding result bit is set to 1.\nOtherwise, the corresponding result bit is set to 0 [@microsoftbitwiseand].\n\nSo, if we apply this operator to the binary sequences `1000100` and `00001101`\nthe result of this operation is the binary sequence `00000100`. Because only\nat the sixth position in both binary sequences we had a 1 value. So any\nposition where we do not have both binary sequences setted to 1, we get\na 0 bit in the resulting binary sequence.\n\nWe lose information about the original bit values\nfrom both sequences in this case. Because we no longer know\nif this 0 bit in the resulting binary sequence was produced by\ncombining 0 with 0, or 1 with 0, or 0 with 1.\n\nAs an example, suppose you have the binary sequence `10010111`, which is the number 151 in decimal. How\ncan we get a new binary sequence which contains only the third and\nfourth bits of this sequence?\n\nWe just need to combine this sequence with `00110000` (is `0x30` in hexadecimal) using the `&` operator.\nNotice that only the third and fourth positions in this binary sequence is setted to 1. As a consequence, only the\nthird and fourth values of both binary sequences are potentially preserved in the output. All the remaining positions\nare setted to zero in the output sequence, which is `00010000` (is the number 16 in decimal).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const bits = 0b10010111;\n    try stdout.print(\"{d}\\n\", .{bits & 0b00110000});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n16\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Allocating space for the output\n\nAs I described at @sec-stack, to store an object in the stack,\nthis object needs to have a known and fixed length at compile-time. This is an important\nlimitation for our base64 encoder/decoder case. Because the size of\nthe output (from both the encoder and decoder) depends\ndirectly on the size of the input.\n\nHaving this in mind, we cannot know at compile time which is\nthe size of the output for both the encoder and decoder.\nSo, if we can't know the size of the output at compile time,\nthis means that we cannot store the output for both the encoder\nand decoder in the stack.\n\nConsequently, we need to store this output on the heap,\nand, as I commented at @sec-heap, we can only\nstore objects in the heap by using allocator objects.\nSo, one the arguments to both the `encode()` and `decode()`\nfunctions, needs to be an allocator object, because\nwe know for sure that, at some point inside the body of these\nfunctions, we need to allocate space on the heap to\nstore the output of these functions.\n\nThat is why, both the `encode()` and `decode()` functions that I\npresent in this book, have an argument called `allocator`,\nwhich receives a allocator object as input, identified by\nthe type `std.mem.Allocator` from the Zig Standard Library.\n\n\n\n### Writing the `encode()` function\n\nNow that we have a basic understanding on how the bitwise operators work, and how\nexactly they help us to achieve the result we want to achieve. We can now encapsulate\nall the logic that we have described at @fig-base64-algo1 and @tbl-transf-6bit into a nice\nfunction that we can add to our `Base64` struct definition, that we started at @sec-base64-table.\n\nYou can find the `encode()` function below. Notice that the first argument of this function,\nis the `Base64` struct itself. Therefore, this argument clearly signals\nthat this function is a method from the `Base64` struct.\n\nBecause the `encode()` function itself is fairly long,\nI intentionally omitted the `Base64` struct definition in this source code,\njust for brevity reasons. So, just remember that this function is a public function (or a public method) from the\n`Base64` struct.\n\nFurthermore, this `encode()` function has two other arguments:\n\n1. `input` is the input sequence of characters that you want to encode in base64;\n1. `allocator` is an allocator object to use in the necessary memory allocations.\n\nI described everything you need to know about allocator objects at @sec-allocators.\nSo, if you are not familiar with them, I highly recommend you to comeback to\nthat section, and read it.\nBy looking at the `encode()` function, you will see that we use this\nallocator object to allocate enough memory to store the output of\nthe encoding process.\n\nThe main for loop in the function is responsible for iterating through the entire input string.\nIn every iteration, we use a `count` variable to count how many iterations we had at the\nmoment. When `count` reaches 3, then, we try to encode the 3 characters (or bytes) that we have accumulated\nin the temporary buffer object (`buf`).\n\nAfter encoding these 3 characters and storing the result in the `output` variable, we reset\nthe `count` variable to zero, and start to count again on the next iteration of the loop.\nIf the loop hits the end of the string, and, the `count` variable is less than 3, then, it means that\nthe temporary buffer contains the last 1 or 2 bytes from the input.\nThat is why we have two `if` statements after the for loop. To deal which each possible case.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn encode(self: Base64,\n              allocator: std.mem.Allocator,\n              input: []const u8) ![]u8 {\n\n    if (input.len == 0) {\n        return \"\";\n    }\n\n    const n_out = try _calc_encode_length(input);\n    var out = try allocator.alloc(u8, n_out);\n    var buf = [3]u8{ 0, 0, 0 };\n    var count: u8 = 0;\n    var iout: u64 = 0;\n\n    for (input, 0..) |_, i| {\n        buf[count] = input[i];\n        count += 1;\n        if (count == 3) {\n            out[iout] = self._char_at(buf[0] >> 2);\n            out[iout + 1] = self._char_at(\n                ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n            );\n            out[iout + 2] = self._char_at(\n                ((buf[1] & 0x0f) << 2) + (buf[2] >> 6)\n            );\n            out[iout + 3] = self._char_at(buf[2] & 0x3f);\n            iout += 4;\n            count = 0;\n        }\n    }\n\n    if (count == 1) {\n        out[iout] = self._char_at(buf[0] >> 2);\n        out[iout + 1] = self._char_at(\n            (buf[0] & 0x03) << 4\n        );\n        out[iout + 2] = '=';\n        out[iout + 3] = '=';\n    }\n\n    if (count == 2) {\n        out[iout] = self._char_at(buf[0] >> 2);\n        out[iout + 1] = self._char_at(\n            ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n        );\n        out[iout + 2] = self._char_at(\n            (buf[1] & 0x0f) << 2\n        );\n        out[iout + 3] = '=';\n        iout += 4;\n    }\n\n    return out;\n}\n```\n:::\n\n\n\n\n\n\n## Building the decoder logic {#sec-decoder-logic}\n\nNow, we can focus on writing the base64 decoder logic. Remember from @fig-base64-algo2 that,\na base64 decoder does the inverse process of an encoder. So, all we need to do, is to\nwrite a `decode()` function that performs the inverse process that I exposed at @sec-encoder-logic.\n\n\n### Mapping base64 characters to their indexes {#sec-map-base64-index}\n\nOne thing that we need to do, in order to decode a base64-encoded message, is to calculate\nthe index in the base64 scale of every base64 character that we encounter in the decoder input.\n\nIn other words, the decoder receives as input, a sequence of base64 characters. We need\nto translate this sequence of characters into a sequence of indexes. These indexes\nare the index of each character in the base64 scale. This way, we get the value/byte\nthat was calculated in the 6-bit transformation step of the encoder process.\n\nThere are probably better/faster ways to calculate this, especially using a \"divide and conquer\"\ntype of strategy. But for now, I am satisfied with a simple and \"brute force\" type of strategy.\nThe `_char_index()` function below contains this strategy.\n\nWe are essentially looping through the *lookup table* with the base64 scale,\nand comparing the character we got with each character in the base64 scale.\nIf these characters match, then, we return the index of this character in the\nbase64 scale as the result.\n\nNotice that, if the input character is `'='`, the function returns the index 64, which is\n\"out of range\" in the scale. But, as I described at @sec-base64-scale,\nthe character `'='` does not belong to the base64 scale itself.\nIt is a special and meaningless character in base64.\n\nAlso notice that this `_char_index()` function is a method from our `Base64` struct,\nbecause of the `self` argument. Again, I have omitted the `Base64` struct definition in this example\nfor brevity reasons.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn _char_index(self: Base64, char: u8) u8 {\n    if (char == '=')\n        return 64;\n    var index: u8 = 0;\n    for (0..63) |i| {\n        if (self._char_at(i) == char)\n            break;\n        index += 1;\n    }\n\n    return index;\n}\n```\n:::\n\n\n\n\n\n\n### The 6-bit transformation\n\nOnce again, the core part of the algorithm is the 6-bit transformation.\nIf we understand the necessary steps to perform this transformation, the rest\nof the algorithm becomes much easier.\n\nFirst of all, before we actually go to the 6-bit transformation,\nwe need to make sure that we use `_char_index()` to convert the sequence of base64 characters\ninto a sequence of indexes. So the snippet below is important for the job that will be done.\nThe result of `_char_index()` is stored in a temporary buffer, and this temporary buffer\nis what we are going to use in the 6-bit transformation, instead of the actual `input` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (0..input.len) |i| {\n    buf[i] = self._char_index(input[i]);\n}\n```\n:::\n\n\n\n\nNow, instead of producing 4 bytes (or 4 characters) as output per each window of 3 characters in the input,\na base64 decoder produces 3 bytes (or 3 characters) as output per each window of 4 characters in the input.\nOnce again, is the inverse process.\n\nSo, the steps to produce the 3 bytes in the output are:\n\n1. `output[0]` is produced by summing two components. First, move the bits from `buf[0]` two positions to the left. Second, move the bits from `buf[1]` 4 positions to the right. Then, sum these two components.\n1. `output[1]` is produced by summing two components. First, move the bits from `buf[1]` four positions to the left. Second, move the bits from `buf[2]` 2 positions to the right. Then, sum these two components.\n1. `output[2]` is produced by summing two components. First, move the bits from `buf[2]` six positions to the left. Then, you sum the result with `buf[3]`.\n\n\nBefore we continue, let's try to visualize how these transformations make the original bytes that we had\nbefore the encoding process. First, think back to the 6-bit transformation performed by the encoder exposed at @sec-encoder-logic.\nThe first byte in the output of the encoder is produced by moving the bits in the first byte of the input two positions to the right.\n\nIf for example the first byte in the input of the encoder was the sequence `ABCDEFGH`, then, the first byte in the output of the encoder would be\n`00ABCDEF` (this sequence would be the first byte in the input of the decoder). Now, if the second byte in the input of the encoder was the sequence\n`IJKLMNOP`, then, the second byte in the encoder output would be `00GHIJKL` (as we demonstrated at @fig-encoder-bitshift).\n\nHence, if the sequences `00ABCDEF` and `00GHIJKL` are the first and second bytes, respectively, in the input of the decoder, the\n@fig-decoder-bitshift demonstrates visually how these two bytes are transformed into the first byte of the output of the decoder.\nNotice that the output byte is the sequence `ABCDEFGH`, which is the original byte from the input of the encoder.\n\n![How the 1st byte in the decoder output is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input](../Figures/base64-decoder-bit-shift.png){#fig-decoder-bitshift}\n\nThe @tbl-6bit-decode presents how the three steps described earlier translate into Zig code:\n\n\n\n::: {#tbl-6bit-decode}\n\n| Byte index in the output | In code                       |\n|--------------------------|-------------------------------|\n| 0                        | (buf[0] << 2) + (buf[1] >> 4) |\n| 1                        | (buf[1] << 4) + (buf[2] >> 2) |\n| 2                        | (buf[2] << 6) + buf[3]        |\n\n: The necessary steps for the 6-transformation in the decode process.\n\n\n:::\n\n\n\n\n\n\n\n### Writing the `decode()` function\n\nThe `decode()` function below contains the entire decoding process.\nWe first calculate the size of the output, with\n`_calc_decode_length()`, then, we allocate enough memory for this output with\nthe allocator object.\n\nThree temporary variables are created: 1) `count`, to hold the window count\nin each iteration of the for loop; 2) `iout`, to hold the current index in the output;\n3) `buf`, which is the temporary buffer that holds the base64 indexes to be\nconverted through the 6-bit transformation.\n\nThen, in each iteration of the for loop we fill the temporary buffer with the current\nwindow of bytes. When `count` hits the number 4, then, we have a full window of\nindexes in `buf` to be converted, and then, we apply the 6-bit transformation\nover the temporary buffer.\n\nNotice that we check if the indexes 2 and 3 in the temporary buffer are the number 64, which, if you recall\nfrom @sec-map-base64-index, is when the `_calc_index()` function receives a `'='` character\nas input. So, if these indexes are equal to the number 64, the `decode()` function knows\nthat it can simply ignore these indexes. They are not converted because, as I described before,\nthe character `'='` has no meaning, despite being the end of meaningful characters in the sequence.\nSo we can safely ignore them when they appear in the sequence.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn decode(self: Base64,\n          allocator: std.mem.Allocator,\n          input: []const u8) ![]u8 {\n\n    if (input.len == 0) {\n        return \"\";\n    }\n    const n_output = try _calc_decode_length(input);\n    var output = try allocator.alloc(u8, n_output);\n    var count: u8 = 0;\n    var iout: u64 = 0;\n    var buf = [4]u8{ 0, 0, 0, 0 };\n\n    for (0..input.len) |i| {\n        buf[count] = self._char_index(input[i]);\n        count += 1;\n        if (count == 4) {\n            output[iout] = (buf[0] << 2) + (buf[1] >> 4);\n            if (buf[2] != 64) {\n                output[iout + 1] = (buf[1] << 4) + (buf[2] >> 2);\n            }\n            if (buf[3] != 64) {\n                output[iout + 2] = (buf[2] << 6) + buf[3];\n            }\n            iout += 3;\n            count = 0;\n        }\n    }\n\n    return output;\n}\n```\n:::\n\n\n\n\n\n## The end result\n\nNow that we have both `decode()` and `encode()` implemented. We have a fully functioning\nbase64 encoder/decoder implemented in Zig. Here is an usage example of our\n`Base64` struct with the `encode()` and `decode()` methods that we have implemented.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar memory_buffer: [1000]u8 = undefined;\nvar fba = std.heap.FixedBufferAllocator.init(\n    &memory_buffer\n);\nconst allocator = fba.allocator();\n\nconst text = \"Testing some more shit\";\nconst etext = \"VGVzdGluZyBzb21lIG1vcmUgc2hpdA==\";\nconst base64 = Base64.init();\nconst encoded_text = try base64.encode(\n    allocator, text\n);\nconst decoded_text = try base64.decode(\n    allocator, etext\n);\ntry stdout.print(\n    \"Encoded text: {s}\\n\", .{encoded_text}\n);\ntry stdout.print(\n    \"Decoded text: {s}\\n\", .{decoded_text}\n);\n```\n:::\n\n\n\n\n```\nEncoded text: VGVzdGluZyBzb21lIG1vcmUgc2hpdA==\nDecoded text: Testing some more shit\n```\n\nYou can also see the full source code at once, by visiting the official repository of this book[^repo].\nMore precisely inside the `ZigExamples` folder[^zig-base64-algo].\n\n[^repo]: \n",
    +    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 1 - Building a base64 encoder/decoder {#sec-base64}\n\nAs our first small project, I want to implement a base64 encoder/decoder with you.\nBase64 is an encoding system which translates binary data to text.\nA big chunk of the web uses base64 to deliver binary data to systems\nthat can only read text data.\n\nThe most common example of a modern use case for base64 is essentially any email system,\nlike GMail, Outlook, etc. Because email systems normally use\nthe Simple Mail Transfer Protocol (SMTP), which is a web protocol\nthat supports only text data. So, if you need, for any reason, to\nsend a binary file (like for example, a PDF, or an Excel file) as\nan attachment in your email, these binary files are normally\nconverted to base64, before they are included in the SMTP message.\nSo, the base64 encoding is largely used in these email systems to include\nbinary data into the SMTP message.\n\n\n\n\n\n\n## How the base64 algorithm work?\n\nBut how exactly does the algorithm behind the base64 encoding work? Let's discuss that. First, I will\nexplain the base64 scale, which is the 64-character scale that is the basis for\nthe base64 encoding system.\n\nAfter that, I explain the algorithm behind a base64 encoder, which is the part of the algorithm that is responsible for encoding messages\ninto the base64 encoding system. Then, after that, I explain the algorithm behind a base64 decoder, which is\nthe part of the algorithm that is responsible for translating base64 messages back into their original meaning.\n\nIf you are unsure about the differences between an \"encoder\" and a \"decoder\",\ntake a look at @sec-encode-vs-decode.\n\n\n### The base64 scale {#sec-base64-scale}\n\nThe base64 encoding system is based on a scale that goes from 0 to 63 (hence the name).\nEach index in this scale is represented by a character (it is a scale of 64 characters).\nSo, in order to convert some binary data, to the base64 encoding, we need to convert each binary number to the corresponding\ncharacter in this \"scale of 64 characters\".\n\nThe base64 scale starts with all ASCII uppercase letters (A to Z) which represents\nthe first 25 indexes in this scale (0 to 25). After that, we have all ASCII lowercase letters\n(a to z), which represents the range 26 to 51 in the scale. After that, we\nhave the one digit numbers (0 to 9), which represents the indexes from 52 to 61 in the scale.\nFinally, the last two indexes in the scale (62 and 63) are represented by the characters `+` and `/`,\nrespectively.\n\nThese are the 64 characters that compose the base64 scale. The equal sign character (`=`) is not part of the scale itself,\nbut it is a special character in the base64 encoding system. This character is used solely as a suffix, to mark the end of the character sequence,\nor, to mark the end of meaningful characters in the sequence.\n\nThe bullet points below summarises the base64 scale:\n\n- range 0 to 25 is represented by: ASCII uppercase letters `-> [A-Z]`;\n- range 26 to 51 is represented by: ASCII lowercase letters `-> [a-z]`;\n- range 52 to 61 is represented by: one digit numbers `-> [0-9]`;\n- index 62 and 63 are represented by the characters `+` and `/`, respectively;\n- the character `=` represents the end of meaningful characters in the sequence;\n\n\n\n\n### Creating the scale as a lookup table {#sec-base64-table}\n\nThe best way to represent this scale in code, is to represent it as a *lookup table*.\nLookup tables are a classic strategy in computer science to speed up calculations. The basic idea\nis to replace a runtime calculation (which can take a long time to be done) with a basic array indexing\noperation.\n\nInstead of calculating the results everytime you need them, you calculate all possible results at once, and then, you store them in an array\n(which behaves lake a \"table\"). Then, every time you need to use one of the characters in the base64 scale, instead of\nusing many resources to calculate the exact character to be used, you simply retrieve this character\nfrom the array where you stored all the possible characters in the base64 scale.\nWe retrieve the character that we need directly from memory.\n\nWe can start building a Zig struct to store our base64 decoder/encoder logic.\nWe start with the `Base64` struct below. For now, we only have one single data member in this\nstruct, i.e. the member `_table`, which represents our lookup table. We also have an `init()` method,\nto create a new instance of a `Base64` object, and, a `_char_at()` method, which is a\n\"get character at index $x$\" type of function.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Base64 = struct {\n    _table: *const [64]u8,\n\n    pub fn init() Base64 {\n        const upper = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n        const lower = \"abcdefghijklmnopqrstuvwxyz\";\n        const numbers_symb = \"0123456789+/\";\n        return Base64{\n            ._table = upper ++ lower ++ numbers_symb,\n        };\n    }\n\n    pub fn _char_at(self: Base64, index: usize) u8 {\n        return self._table[index];\n    }\n};\n```\n:::\n\n\n\n\n\nIn other words, the `_char_at()` method is responsible for getting the character in the lookup\ntable (i.e. the `_table` struct data member) that corresponds to a particular index in the\n\"base64 scale\". So, in the example below, we know that the character that corresponds to the\nindex 28 in the \"base64 scale\" is the character \"c\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst base64 = Base64.init();\ntry stdout.print(\n    \"Character at index 28: {c}\\n\",\n    .{base64._char_at(28)}\n);\n```\n:::\n\n\n\n\n```\nCharacter at index 28: c\n```\n\n\n\n### A base64 encoder {#sec-base64-encoder-algo}\n\nThe algorithm behind a base64 encoder usually works on a window of 3 bytes. Because each byte has\n8 bits, so, 3 bytes forms a set of $8 \\times 3 = 24$ bits. This is desirable for the base64 algorithm, because\n24 bits is divisible by 6, which forms $24 / 6 = 4$ groups of 6 bits each.\n\nTherefore, the base64 algorithm works by converting 3 bytes at a time\ninto 4 characters from the base64 scale. It keeps iterating through the input string,\n3 bytes at a time, and converting them into the base64 scale, producing 4 characters\nper iteration. It keeps iterating, and producing these \"new characters\"\nuntil it hits the end of the input string.\n\nNow, you may think, what if you have a particular string that have a number of bytes\nthat is not divisible by 3? What happens? For example, if you have a string\nthat contains only two characters/bytes, such as \"Hi\". How the\nalgorithm would behave in such situation? You find the answer at @fig-base64-algo1.\nYou can see at @fig-base64-algo1 that the string \"Hi\", when converted to base64,\nbecomes the string \"SGk=\":\n\n![The logic behind a base64 encoder](./../Figures/base64-encoder-flow.png){#fig-base64-algo1}\n\nTaking the string \"Hi\" as an example, we have 2 bytes, or, 16 bits in total. So, we lack a full byte (8 bits)\nto complete the window of 24 bits that the base64 algorithm likes to work on. The first thing that\nthe algorithm does, is to check how to divide the input bytes into groups of 6 bits.\n\nIf the algorithm notices that there is a group of 6 bits that, have some bits in it, but, at the same time, it is not full\n(in other words, $0 < nbits < 6$, being $nbits$ the number of bits), meaning that, it lacks\nsome bits to fill the 6-bits requirement, the algorithm simply add extra zeros in this group\nto fill the space that it needs. That is why at @fig-base64-algo1, on the third group after the 6-bit transformation,\n2 extra zeros were added to fill the gap in this group.\n\nWhen we have a 6-bit group that is not completely full, like the third group, extra zeros\nare added to fill the gap. But what about when an entire 6-bit group is empty, or, it\nsimply doesn't exist? This is the case of the fourth 6-bit group exposed at\n@fig-base64-algo1.\n\nThis fourth group is necessary, because the algorithm works on 4 groups of 6 bits.\nBut the input string does not have enough bytes to create a fourth 6-bit group.\nEvery time this happens, where an entire group of 6 bits is empty,\nthis group becomes a \"padding group\". Every \"padding group\" is mapped to\nthe character `=` (equal sign), which represents \"null\", or, the end\nof meaningful characters in the sequence. Hence, everytime that the algorithm produces a\n\"padding group\", this group is automatically mapped to `=`.\n\nAs another example, if you give the string \"0\" as input to a base64 encoder, this string is\ntranslated into the base64 sequence \"MA==\".\nThe character \"0\" is, in binary, the sequence `00110000`[^zero-note]. So, with the 6-bit transformation\nexposed at @fig-base64-algo1, this single character would produce these two 6-bit groups: `001100`, `000000`.\nThe remaining two 6-bit groups become \"padding groups\". That is why the last\ntwo characters in the output sequence (MA==) are `==`.\n\n\n[^zero-note]: Notice that, the character \"0\" is different than the actual number 0, which is simply zero in binary.\n\n### A base64 decoder {#sec-base64-decoder-algo}\n\nThe algorithm behind a base64 decoder is essentially the inverse process of a base64 encoder.\nA base64 decoder needs to translate base64 messages back into their original meaning,\ni.e. into the original sequence of binary data.\n\nA base64 decoder usually works on a window of 4 bytes. Because it wants to convert these 4 bytes\nback into the original sequence of 3 bytes, that was converted into 4 groups of 6 bits by the\nbase64 encoder. Remember, in a base64 decoder we are essentially reverting the process made\nby the base64 encoder.\n\nEach byte in the input string (the base64 encoded string) normally contributes to re-create\ntwo different bytes in the output (the original binary data).\nIn other words, each byte that comes out of a base64 decoder is created by transforming merging two different\nbytes in the input together. You can visualize this relationship at @fig-base64-algo2:\n\n![The logic behind a base64 decoder](./../Figures/base64-decoder-flow.png){#fig-base64-algo2}\n\nThe exact transformations, or, the exact steps applied to each byte from the input to transform them\ninto the bytes of the output, are a bit tricky to visualize in a figure like this. Because of that, I have\nsummarized these transformations as \"Some bit shifting and additions ...\" in the figure. These transformations\nwill be described in depth later.\n\nBesides that, if you look again at @fig-base64-algo2, you will notice that the character `=` was completely\nignored by the algorithm. Remember, this is just a special character that marks the end of meaningful characters\nin the base64 sequence. So, every `=` character in a base64 encoded sequence should be ignored by a base64 decoder.\n\n\n## Difference between encode and decode {#sec-encode-vs-decode}\n\nIf you don't have any previous experience with base64, you might not understand the differences\nbetween \"encode\" and \"decode\". Essentially, the terms \"encode\" and \"decode\" here\nhave the exact same meaning as they have in the field of encryption (i.e. they mean the same thing as \"encode\" and \"decode\" in hashing\nalgorithms, like the MD5 algorithm).\n\nThus, \"encode\" means that we want to encode, or, in other words, we want to translate some message into\nthe base64 encoding system. We want to produce the sequence of base64 characters that represent this\noriginal message in the base64 encoding system.\n\nIn contrast, \"decode\" represents the inverse process.\nWe want to decode, or, in other words, translate a base64 message back to its original content.\nSo, in this process we get a sequence of base64 characters as input, and produce as output,\nthe binary data that is represented by this sequence of base64 characters.\n\nAny base64 library is normally composed of these two parts: 1) the encoder, which is a function that encodes\n(i.e. it converts) any sequence of binary data into a sequence of base64 characters; 2) the decoder, which is a function\nthat converts a sequence of base64 characters back into the original sequence of binary data.\n\n\n\n## Calculating the size of the output {#sec-base64-length-out}\n\nOne task that we need to do is to calculate how much space we need to reserve for the\noutput, both of the encoder and decoder. This is simple math, and can be done easily in Zig\nbecause every array has its length (its number of elements) easily accesible by consulting\nthe `.len` property of the array.\n\nFor the encoder, the logic is the following: for each 3 bytes that we find in the input,\n4 new bytes are created in the output. So, we take the number of bytes in the input, divide it\nby 3, use a ceiling function, then, we multiply the result by 4. That way, we get the total\nnumber of bytes that will be produced by the encoder in its output.\n\nThe `_calc_encode_length()` function below encapsulates this logic.\nInside this function, we take the length of the input array,\nwe divide it by 3, and apply a ceil operation over the result by using the\n`divCeil()` function from the Zig Standard Library. Lastly, we multiply\nthe end result by 4 to get the answer we need.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_encode_length(input: []const u8) !usize {\n    if (input.len < 3) {\n        const n_output: usize = 4;\n        return n_output;\n    }\n    const n_output: usize = try std.math.divCeil(\n        usize, input.len, 3\n    );\n    return n_output * 4;\n}\n```\n:::\n\n\n\n\n\nAlso, you might have notice that, if the input length is less than 3 bytes, then, the output length of the encoder is\nalways 4 bytes. This is the case for every input with less than 3 bytes, because, as I described at @sec-base64-encoder-algo,\nthe algorithm always produces enough \"padding-groups\" in the end result, to complete the 4 bytes window.\n\nNow, for the decoder, we just need to apply the inverse logic: for each 4 bytes in the input, 3 bytes\nwill be produced in the output of the decoder. I mean, this is roughly true, because we also need to\ntake the `=` character into account, which is always ignored by the decoder, as we described at @sec-base64-decoder-algo, and,\nat @fig-base64-algo2. But we can ignore this fact for now, just to keep things simple.\n\nThe function `_calc_decode_length()` exposed below summarizes this logic that we described. It is very similar\nto the function `_calc_encode_length()`. Only the division part is twisted, and also, in the special\ncase where we have less than 4 bytes in the input to work on. Also notice that this time, we apply\na floor operation over the output of the division, by using the `divFloor()`\nfunction (instead of a ceiling operation with `divCeil()`).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_decode_length(input: []const u8) !usize {\n    if (input.len < 4) {\n        const n_output: usize = 3;\n        return n_output;\n    }\n    const n_output: usize = try std.math.divFloor(\n        usize, input.len, 4\n    );\n    return n_output * 3;\n}\n```\n:::\n\n\n\n\n\n## Building the encoder logic {#sec-encoder-logic}\n\nIn this section, we can start building the logic behind the `encode()` function, which\nwill be responsible for encoding messages into the base64 encoding system.\nIf you are an anxious person, and you want to see now the full source code of the implementation\nfor this base64 encoder/decoder, you can find it at the `ZigExamples` folder in the official repository of\nthis book[^zig-base64-algo].\n\n[^zig-base64-algo]: .\n\n\n\n### The 6-bit transformation {#sec-6bit-transf}\n\nThe 6-bit transformation presented at @fig-base64-algo1 is the core part of the base64 encoder algorithm.\nBy understanding how this transformation is made in code, the rest of the algorithm becomes much simpler\nto comprehend.\n\nIn essence, this 6-bit transformation is made with the help of bitwise operators.\nBitwise operators are essential to any type of low-level operation that is done at the bit-level. For the specific case of the base64 algorithm,\nthe operators *bif shift to the left* (`<<`), *bit shift to the right* (`>>`), and the *bitwise and* (`&`) are used. They\nare the core solution for the 6-bit transformation.\n\nThere are 3 different scenarios that we need to take into account in this transformation. First, is the perfect scenario,\nwhere we have the perfect window of 3 bytes to work on. Second, we have the scenario where we have a window of only\ntwo bytes to work with. And last, we have the scenario where we have a window of one single byte.\n\nIn each of these 3 scenarios, the 6-bit transformation works a bit differently. To make the explanation\neasier, I will use the variable `output` to refer to the bytes in the output of the base64 encoder,\nand the variable `input` to refer to the bytes in the input of the encoder.\n\n\nSo, if you have the perfect window of 3 bytes, these are steps for the 6-bit transformation:\n\n1. `output[0]` is produced by moving the bits from `input[0]` two positions to the right.\n1. `output[1]` is produced by summing two components. First, take the last two bits from `input[0]`, then, move them four positions to the left. Second, move the bits from `input[1]` four positions to the right. Sum these two components.\n1. `output[2]` is produced by summing two components. First, take the last four bits from `input[1]`, then, move them two positions to the left. Second, move the bits from `input[2]` six positions to the right. Sum these two components.\n1. `output[3]` is produced by taking the last six bits from `input[2]`.\n\n\nThis is the perfect scenario, where we have a full window of 3 bytes to work on.\nJust to make things as clear as possible, the @fig-encoder-bitshift demonstrates visually how\nthe step 2 mentioned above works. So the 2nd byte in the `output` of the encoder, is made by taking the 1st byte (dark purple)\nand the 2nd byte (orange) from the input. You can see that, at the end of the process, we get a new\nbyte that contains the last 2 bits from the 1st byte in the `input`, and the first 4 bits\nfrom the 2nd byte in the `input`.\n\n![How the 2nd byte in the output of the encoder is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input.](../Figures/base64-encoder-bit-shift.png){#fig-encoder-bitshift}\n\nOn the other hand, we must be prepared for the instances where we do not have the perfect window of 3 bytes.\nIf you have a window of 2 bytes, then, the steps 3 and 4, which produces the bytes `output[2]` and `output[3]`, change a little bit,\nand they become:\n\n- `output[2]` is produced by taking the last 4 bits from `input[1]`, then, move them two positions to the left.\n- `output[3]` is the character `'='`.\n\n\nFinally, if you have a window of a single byte, then, the steps 2 to 4, which produces the bytes `output[1]`, `output[2]` and `output[3]` change,\nbecoming:\n\n- `output[1]` is produced by taking the last two bits from `input[0]`, then, move them four positions to the left.\n- `output[2]` and `output[3]` are the character `=`.\n\n\nIf these bullet points were a bit confusing for you, you may find the @tbl-transf-6bit more intuitive.\nThis table unifies all this logic into a simple table. Notice that\nthis table also provides the exact expression in Zig that creates the corresponding\nbyte in the output.\n\n\n::: {#tbl-transf-6bit}\n\n| Number of bytes in the window | Byte index in the output | In code                                    |\n|-------------------------------|--------------------------|--------------------------------------------|\n| 3                             | 0                        | input[0] >> 2                              |\n| 3                             | 1                        | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 3                             | 2                        | ((input[1] & 0x0f) << 2) + (input[2] >> 6) |\n| 3                             | 3                        | input[2] & 0x3f                            |\n| 2                             | 0                        | input[0] >> 2                              |\n| 2                             | 1                        | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 2                             | 2                        | ((input[1] & 0x0f) << 2)                   |\n| 2                             | 3                        | '='                                        |\n| 1                             | 0                        | input[0] >> 2                              |\n| 1                             | 1                        | ((input[0] & 0x03) << 4)                   |\n| 1                             | 2                        | '='                                        |\n| 1                             | 3                        | '='                                        |\n\n: How the 6-bit transformation translates into code in different window settings.\n\n:::\n\n\n\n\n\n\n### Bit-shifting in Zig\n\nBit-shifting in Zig works similarly to bit-shifting in C.\nAll bitwise operators that exist in C are available in Zig.\nHere, in the base64 encoder algorithm, they are essential\nto produce the result we want.\n\nFor those who are not familiar with these operators, they are\noperators that operates at the bit-level of your values.\nThis means that these operators takes the bits that form the value\nyou have, and change them in some way. This ultimately also changes\nthe value itself, because the binary representation of this value\nchanges.\n\nWe have already seen at @fig-encoder-bitshift the effect produced by a bit-shift.\nBut let's use the first byte in the output of the base64 encoder as another example of what\nbit-shifting means. This is the easiest byte of the 4 bytes in the output\nto build. Because we only need to move the bits from the first byte in the input two positions to the right,\nwith the *bit shift to the right* (`>>`) operator.\n\nIf we take the string \"Hi\" that we used at @fig-base64-algo1 as an example, the first byte in\nthis string is \"H\", which is the sequence `01001000` in binary.\nIf we move the bits of this byte, two places to the right, we get the sequence `00010010` as result.\nThis binary sequence is the value `18` in decimal, and also, the value `0x12` in hexadecimal.\nNotice that the first 6 bits of \"H\" were moved to the end of the byte.\nWith this operation, we get the first byte of the output.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const input = \"Hi\";\n    try stdout.print(\"{d}\\n\", .{input[0] >> 2});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n18\n```\n\n\n:::\n:::\n\n\n\n\nIf you recall @fig-base64-algo1, the first byte present in the output should\nbe equivalent to the 6-bit group `010010`. Although being visually different, the\nsequences `010010` and `00010010` are semantically equal. They mean the same thing.\nThey both represent the number 18 in decimal, and the value `0x12` in hexadecimal.\n\nSo, don't take the \"6-bit group\" factor so seriously. We do not need necessarily to\nget a 6-bit sequence as result. As long as the meaning of the 8-bit sequence we get is the same\nof the 6-bit sequence, we are in the clear.\n\n\n\n### Selecting specific bits with the `&` operator\n\nIf you comeback to @sec-6bit-transf, you will see that, in order to produce\nthe second and third bytes in the output, we need to select specific\nbits from the first and second bytes in the input string. But how\ncan we do that? The answer relies on the *bitwise and* (`&`) operator.\n\nThe @fig-encoder-bitshift already showed you what effect this `&` operator\nproduces in the bits of its operands. But let's make a clear description of it.\n\nIn summary, the `&` operator performs a logical conjunction operation\nbetween the bits of its operands. In more details, the operator `&`\ncompares each bit of the first operand to the corresponding bit of the second operand.\nIf both bits are 1, the corresponding result bit is set to 1.\nOtherwise, the corresponding result bit is set to 0 [@microsoftbitwiseand].\n\nSo, if we apply this operator to the binary sequences `1000100` and `00001101`\nthe result of this operation is the binary sequence `00000100`. Because only\nat the sixth position in both binary sequences we had a 1 value. So any\nposition where we do not have both binary sequences setted to 1, we get\na 0 bit in the resulting binary sequence.\n\nWe lose information about the original bit values\nfrom both sequences in this case. Because we no longer know\nif this 0 bit in the resulting binary sequence was produced by\ncombining 0 with 0, or 1 with 0, or 0 with 1.\n\nAs an example, suppose you have the binary sequence `10010111`, which is the number 151 in decimal. How\ncan we get a new binary sequence which contains only the third and\nfourth bits of this sequence?\n\nWe just need to combine this sequence with `00110000` (is `0x30` in hexadecimal) using the `&` operator.\nNotice that only the third and fourth positions in this binary sequence is setted to 1. As a consequence, only the\nthird and fourth values of both binary sequences are potentially preserved in the output. All the remaining positions\nare setted to zero in the output sequence, which is `00010000` (is the number 16 in decimal).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const bits = 0b10010111;\n    try stdout.print(\"{d}\\n\", .{bits & 0b00110000});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n16\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Allocating space for the output\n\nAs I described at @sec-stack, to store an object in the stack,\nthis object needs to have a known and fixed length at compile-time. This is an important\nlimitation for our base64 encoder/decoder case. Because the size of\nthe output (from both the encoder and decoder) depends\ndirectly on the size of the input.\n\nHaving this in mind, we cannot know at compile time which is\nthe size of the output for both the encoder and decoder.\nSo, if we can't know the size of the output at compile time,\nthis means that we cannot store the output for both the encoder\nand decoder in the stack.\n\nConsequently, we need to store this output on the heap,\nand, as I commented at @sec-heap, we can only\nstore objects in the heap by using allocator objects.\nSo, one the arguments to both the `encode()` and `decode()`\nfunctions, needs to be an allocator object, because\nwe know for sure that, at some point inside the body of these\nfunctions, we need to allocate space on the heap to\nstore the output of these functions.\n\nThat is why, both the `encode()` and `decode()` functions that I\npresent in this book, have an argument called `allocator`,\nwhich receives a allocator object as input, identified by\nthe type `std.mem.Allocator` from the Zig Standard Library.\n\n\n\n### Writing the `encode()` function\n\nNow that we have a basic understanding on how the bitwise operators work, and how\nexactly they help us to achieve the result we want to achieve. We can now encapsulate\nall the logic that we have described at @fig-base64-algo1 and @tbl-transf-6bit into a nice\nfunction that we can add to our `Base64` struct definition, that we started at @sec-base64-table.\n\nYou can find the `encode()` function below. Notice that the first argument of this function,\nis the `Base64` struct itself. Therefore, this argument clearly signals\nthat this function is a method from the `Base64` struct.\n\nBecause the `encode()` function itself is fairly long,\nI intentionally omitted the `Base64` struct definition in this source code,\njust for brevity reasons. So, just remember that this function is a public function (or a public method) from the\n`Base64` struct.\n\nFurthermore, this `encode()` function has two other arguments:\n\n1. `input` is the input sequence of characters that you want to encode in base64;\n1. `allocator` is an allocator object to use in the necessary memory allocations.\n\nI described everything you need to know about allocator objects at @sec-allocators.\nSo, if you are not familiar with them, I highly recommend you to comeback to\nthat section, and read it.\nBy looking at the `encode()` function, you will see that we use this\nallocator object to allocate enough memory to store the output of\nthe encoding process.\n\nThe main for loop in the function is responsible for iterating through the entire input string.\nIn every iteration, we use a `count` variable to count how many iterations we had at the\nmoment. When `count` reaches 3, then, we try to encode the 3 characters (or bytes) that we have accumulated\nin the temporary buffer object (`buf`).\n\nAfter encoding these 3 characters and storing the result in the `output` variable, we reset\nthe `count` variable to zero, and start to count again on the next iteration of the loop.\nIf the loop hits the end of the string, and, the `count` variable is less than 3, then, it means that\nthe temporary buffer contains the last 1 or 2 bytes from the input.\nThat is why we have two `if` statements after the for loop. To deal which each possible case.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn encode(self: Base64,\n              allocator: std.mem.Allocator,\n              input: []const u8) ![]u8 {\n\n    if (input.len == 0) {\n        return \"\";\n    }\n\n    const n_out = try _calc_encode_length(input);\n    var out = try allocator.alloc(u8, n_out);\n    var buf = [3]u8{ 0, 0, 0 };\n    var count: u8 = 0;\n    var iout: u64 = 0;\n\n    for (input, 0..) |_, i| {\n        buf[count] = input[i];\n        count += 1;\n        if (count == 3) {\n            out[iout] = self._char_at(buf[0] >> 2);\n            out[iout + 1] = self._char_at(\n                ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n            );\n            out[iout + 2] = self._char_at(\n                ((buf[1] & 0x0f) << 2) + (buf[2] >> 6)\n            );\n            out[iout + 3] = self._char_at(buf[2] & 0x3f);\n            iout += 4;\n            count = 0;\n        }\n    }\n\n    if (count == 1) {\n        out[iout] = self._char_at(buf[0] >> 2);\n        out[iout + 1] = self._char_at(\n            (buf[0] & 0x03) << 4\n        );\n        out[iout + 2] = '=';\n        out[iout + 3] = '=';\n    }\n\n    if (count == 2) {\n        out[iout] = self._char_at(buf[0] >> 2);\n        out[iout + 1] = self._char_at(\n            ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n        );\n        out[iout + 2] = self._char_at(\n            (buf[1] & 0x0f) << 2\n        );\n        out[iout + 3] = '=';\n        iout += 4;\n    }\n\n    return out;\n}\n```\n:::\n\n\n\n\n\n\n## Building the decoder logic {#sec-decoder-logic}\n\nNow, we can focus on writing the base64 decoder logic. Remember from @fig-base64-algo2 that,\na base64 decoder does the inverse process of an encoder. So, all we need to do, is to\nwrite a `decode()` function that performs the inverse process that I exposed at @sec-encoder-logic.\n\n\n### Mapping base64 characters to their indexes {#sec-map-base64-index}\n\nOne thing that we need to do, in order to decode a base64-encoded message, is to calculate\nthe index in the base64 scale of every base64 character that we encounter in the decoder input.\n\nIn other words, the decoder receives as input, a sequence of base64 characters. We need\nto translate this sequence of characters into a sequence of indexes. These indexes\nare the index of each character in the base64 scale. This way, we get the value/byte\nthat was calculated in the 6-bit transformation step of the encoder process.\n\nThere are probably better/faster ways to calculate this, especially using a \"divide and conquer\"\ntype of strategy. But for now, I am satisfied with a simple and \"brute force\" type of strategy.\nThe `_char_index()` function below contains this strategy.\n\nWe are essentially looping through the *lookup table* with the base64 scale,\nand comparing the character we got with each character in the base64 scale.\nIf these characters match, then, we return the index of this character in the\nbase64 scale as the result.\n\nNotice that, if the input character is `'='`, the function returns the index 64, which is\n\"out of range\" in the scale. But, as I described at @sec-base64-scale,\nthe character `'='` does not belong to the base64 scale itself.\nIt is a special and meaningless character in base64.\n\nAlso notice that this `_char_index()` function is a method from our `Base64` struct,\nbecause of the `self` argument. Again, I have omitted the `Base64` struct definition in this example\nfor brevity reasons.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn _char_index(self: Base64, char: u8) u8 {\n    if (char == '=')\n        return 64;\n    var index: u8 = 0;\n    for (0..63) |i| {\n        if (self._char_at(i) == char)\n            break;\n        index += 1;\n    }\n\n    return index;\n}\n```\n:::\n\n\n\n\n\n\n### The 6-bit transformation\n\nOnce again, the core part of the algorithm is the 6-bit transformation.\nIf we understand the necessary steps to perform this transformation, the rest\nof the algorithm becomes much easier.\n\nFirst of all, before we actually go to the 6-bit transformation,\nwe need to make sure that we use `_char_index()` to convert the sequence of base64 characters\ninto a sequence of indexes. So the snippet below is important for the job that will be done.\nThe result of `_char_index()` is stored in a temporary buffer, and this temporary buffer\nis what we are going to use in the 6-bit transformation, instead of the actual `input` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (0..input.len) |i| {\n    buf[i] = self._char_index(input[i]);\n}\n```\n:::\n\n\n\n\nNow, instead of producing 4 bytes (or 4 characters) as output per each window of 3 characters in the input,\na base64 decoder produces 3 bytes (or 3 characters) as output per each window of 4 characters in the input.\nOnce again, is the inverse process.\n\nSo, the steps to produce the 3 bytes in the output are:\n\n1. `output[0]` is produced by summing two components. First, move the bits from `buf[0]` two positions to the left. Second, move the bits from `buf[1]` 4 positions to the right. Then, sum these two components.\n1. `output[1]` is produced by summing two components. First, move the bits from `buf[1]` four positions to the left. Second, move the bits from `buf[2]` 2 positions to the right. Then, sum these two components.\n1. `output[2]` is produced by summing two components. First, move the bits from `buf[2]` six positions to the left. Then, you sum the result with `buf[3]`.\n\n\nBefore we continue, let's try to visualize how these transformations make the original bytes that we had\nbefore the encoding process. First, think back to the 6-bit transformation performed by the encoder exposed at @sec-encoder-logic.\nThe first byte in the output of the encoder is produced by moving the bits in the first byte of the input two positions to the right.\n\nIf for example the first byte in the input of the encoder was the sequence `ABCDEFGH`, then, the first byte in the output of the encoder would be\n`00ABCDEF` (this sequence would be the first byte in the input of the decoder). Now, if the second byte in the input of the encoder was the sequence\n`IJKLMNOP`, then, the second byte in the encoder output would be `00GHIJKL` (as we demonstrated at @fig-encoder-bitshift).\n\nHence, if the sequences `00ABCDEF` and `00GHIJKL` are the first and second bytes, respectively, in the input of the decoder, the\n@fig-decoder-bitshift demonstrates visually how these two bytes are transformed into the first byte of the output of the decoder.\nNotice that the output byte is the sequence `ABCDEFGH`, which is the original byte from the input of the encoder.\n\n![How the 1st byte in the decoder output is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input](../Figures/base64-decoder-bit-shift.png){#fig-decoder-bitshift}\n\nThe @tbl-6bit-decode presents how the three steps described earlier translate into Zig code:\n\n\n\n::: {#tbl-6bit-decode}\n\n| Byte index in the output | In code                       |\n|--------------------------|-------------------------------|\n| 0                        | (buf[0] << 2) + (buf[1] >> 4) |\n| 1                        | (buf[1] << 4) + (buf[2] >> 2) |\n| 2                        | (buf[2] << 6) + buf[3]        |\n\n: The necessary steps for the 6-transformation in the decode process.\n\n\n:::\n\n\n\n\n\n\n\n### Writing the `decode()` function\n\nThe `decode()` function below contains the entire decoding process.\nWe first calculate the size of the output, with\n`_calc_decode_length()`, then, we allocate enough memory for this output with\nthe allocator object.\n\nThree temporary variables are created: 1) `count`, to hold the window count\nin each iteration of the for loop; 2) `iout`, to hold the current index in the output;\n3) `buf`, which is the temporary buffer that holds the base64 indexes to be\nconverted through the 6-bit transformation.\n\nThen, in each iteration of the for loop we fill the temporary buffer with the current\nwindow of bytes. When `count` hits the number 4, then, we have a full window of\nindexes in `buf` to be converted, and then, we apply the 6-bit transformation\nover the temporary buffer.\n\nNotice that we check if the indexes 2 and 3 in the temporary buffer are the number 64, which, if you recall\nfrom @sec-map-base64-index, is when the `_calc_index()` function receives a `'='` character\nas input. So, if these indexes are equal to the number 64, the `decode()` function knows\nthat it can simply ignore these indexes. They are not converted because, as I described before,\nthe character `'='` has no meaning, despite being the end of meaningful characters in the sequence.\nSo we can safely ignore them when they appear in the sequence.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn decode(self: Base64,\n          allocator: std.mem.Allocator,\n          input: []const u8) ![]u8 {\n\n    if (input.len == 0) {\n        return \"\";\n    }\n    const n_output = try _calc_decode_length(input);\n    var output = try allocator.alloc(u8, n_output);\n    var count: u8 = 0;\n    var iout: u64 = 0;\n    var buf = [4]u8{ 0, 0, 0, 0 };\n\n    for (0..input.len) |i| {\n        buf[count] = self._char_index(input[i]);\n        count += 1;\n        if (count == 4) {\n            output[iout] = (buf[0] << 2) + (buf[1] >> 4);\n            if (buf[2] != 64) {\n                output[iout + 1] = (buf[1] << 4) + (buf[2] >> 2);\n            }\n            if (buf[3] != 64) {\n                output[iout + 2] = (buf[2] << 6) + buf[3];\n            }\n            iout += 3;\n            count = 0;\n        }\n    }\n\n    return output;\n}\n```\n:::\n\n\n\n\n\n## The end result\n\nNow that we have both `decode()` and `encode()` implemented. We have a fully functioning\nbase64 encoder/decoder implemented in Zig. Here is an usage example of our\n`Base64` struct with the `encode()` and `decode()` methods that we have implemented.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar memory_buffer: [1000]u8 = undefined;\nvar fba = std.heap.FixedBufferAllocator.init(\n    &memory_buffer\n);\nconst allocator = fba.allocator();\n\nconst text = \"Testing some more stuff\";\nconst etext = \"VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=\";\nconst base64 = Base64.init();\nconst encoded_text = try base64.encode(\n    allocator, text\n);\nconst decoded_text = try base64.decode(\n    allocator, etext\n);\ntry stdout.print(\n    \"Encoded text: {s}\\n\", .{encoded_text}\n);\ntry stdout.print(\n    \"Decoded text: {s}\\n\", .{decoded_text}\n);\n```\n:::\n\n\n\n\n```\nEncoded text: VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=\nDecoded text: Testing some more stuff\n```\n\nYou can also see the full source code at once, by visiting the official repository of this book[^repo].\nMore precisely inside the `ZigExamples` folder[^zig-base64-algo].\n\n[^repo]: \n",
         "supporting": [
           "01-base64_files"
         ],
    diff --git a/_freeze/Chapters/01-zig-weird/execute-results/html.json b/_freeze/Chapters/01-zig-weird/execute-results/html.json
    index 1238c4cd..f1342fff 100644
    --- a/_freeze/Chapters/01-zig-weird/execute-results/html.json
    +++ b/_freeze/Chapters/01-zig-weird/execute-results/html.json
    @@ -1,9 +1,11 @@
     {
    -  "hash": "8ffa4a01e784b723e1aaf1806367c53c",
    +  "hash": "ba740c33772422f50c73c140fef90a2d",
       "result": {
         "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it is still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. They really make it sometimes hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscures the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that get's compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e. it is where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n    ├── main.zig\n    └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contain Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nTherefore, Zig contains a native build system in it, and\nwe can use this build system to write small scripts in Zig,\nwhich describes the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e. creating new objects)\nare made in Zig. You can create a new object in Zig by using the following syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). At @sec-assignments we talk more about objects in general.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n    return a + b;\n}\n```\n:::\n\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that at @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIs worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt is like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n    const stdout = std.io.getStdOut().writer();\n    try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portable C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig  build.zig.zon  main  src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nIn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e. the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. Thus, if you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith a \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, operations like accessing the `stdout` (or opening a file) on Windows\ndepends on resources that are available only at *runtime* (you will learn more about compile-time\nversus runtime at @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n    break :blk asm {\n               ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword at @sec-comptime.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    // SUCCESS: Stdout initialized at runtime.\n    const stdout = std.io.getStdOut().writer();\n    _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation at a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues \n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described in @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig later in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig? \nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar to our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentation.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It is a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (on YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e. identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n    age = 25;\n      ~~^~~\n```\n\nIn contrast, if you use `var`, then, the object created is a variable object.\nWith `var` you can declare this object in your source code, and then,\nchange the value of this object how many times you want over future points\nin your source code.\n\nSo, using the same code example exposed above, if I change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it is an \"variable object\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIs important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code use this object while it is uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object. \n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e. if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n    const age = 15;\n          ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to a special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It is discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n    of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also get's discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig have many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e. the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\n\nIs worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it have the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array. \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it is a slice that\naccess all elements in the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhave 2 elements in it.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" at @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth at @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially at @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned at @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e. the start and the end of this range)\nis known at compile-time, the slice object that get's created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nat @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that get's created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e. a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can \ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n    1, 2, 3, 4, 5,\n    6, 7, 8, 9, 10\n};\n// This slice have a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n```\n:::\n\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat get's created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, the `slice` object have a runtime known range, because the end index of the range\nis not known at compile time. In other words, the size of the array at `buffer` is not known\nat compile time. When we execute this program, the size of the array might be 10, or, it might be 12\ndepending on where we execute it. Therefore, we don't know at compile time if\nthe slice object have a range of size 10, or, a range of size 12.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    var n: usize = 0;\n    if (builtin.target.os.tag == .windows) {\n        n = 10;\n    } else {\n        n = 12;\n    }\n    const buffer = try allocator.alloc(u64, n);\n    const slice = buffer[0..];\n    _ = slice;\n}\n```\n:::\n\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code have its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e. a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n    y += 1;\n    break :add_one y;\n};\nif (x == 124 and y == 124) {\n    try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nIn summary, there are two types of string values that you care about in Zig, which are:\n\n- String literal values.\n- String objects.\n\nA string literal value is just a pointer to a null-terminated array of bytes (i.e. similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string into the data type of the value itself.\nTherefore, a string literal value have a data type in the format `*const [n:0]u8`. The `n` in the data type\nindicates the size of the string.\n\nOn the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes,\nor, in other words, a slice of `u8` values (slices were presented at @sec-arrays). Thus,\na string object have a data type of `[]u8` or `[]const u8`, depending if the string object is\nmarked as constant with `const`, or as variable with `var`.\n\nBecause a string object is essentially a slice, it means that a string object always contains two things:\na pointer to an array of bytes (i.e. `u8` values) that represents the string value; and also, a length value,\nwhich specifies the size of the slice, or, how many elements there is in the slice.\nIs worth to emphasize that the array of bytes in a string object is not null-terminated, like in a\nstring literal value.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n\"A literal value\";\n// This is a string object:\nconst object: []const u8 = \"A string object\";\n```\n:::\n\n\n\n\n\nZig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n    try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"This is an example\";\n    try stdout.print(\"Bytes that represents the string object: \", .{});\n    for (string_object) |byte| {\n        try stdout.print(\"{X} \", .{byte});\n    }\n    try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n   73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Strings in C\n\nAt first glance, a string literal value in Zig looks very similar to how C treats strings as well.\nIn more details, string values in C are treated internally as an array of arbitrary bytes,\nand this array is also null-terminated.\n\nBut one key difference between a Zig string literal and a C string, is that Zig also stores the length of\nthe string inside the object itself. In the case of a string literal value, this length is stored in the\ndata type of the value (i.e. the `n` variable in `[n:0]u8`). While, in a string object, the length is stored\nin the `len` attribute of the slice that represents the string object. This small detail makes your code safer,\nbecause it is much easier for the Zig compiler to check if you are trying to access an element that is\n\"out of bounds\", i.e. if your trying to access memory that does not belong to you.\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n    char* array = \"An example of string in C\";\n    int index = 0;\n    while (1) {\n        if (array[index] == '\\0') {\n            break;\n        }\n        index++;\n    }\n    printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible. In a string object for example, you can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"This is an example of string literal in Zig\";\n    try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it is a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    const simple_array = [_]i32{1, 2, 3, 4};\n    const string_obj: []const u8 = \"A string object\";\n    std.debug.print(\n        \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n    );\n    std.debug.print(\n        \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n    );\n    std.debug.print(\n        \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n    );\n    std.debug.print(\n        \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n    );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nType 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons\n  st [4]i32Type 4: []const u8\n```\n\n\n:::\n:::\n\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIs important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"Ⱥ\";\n    _ = try stdout.write(\n        \"Bytes that represents the string object: \"\n    );\n    for (string_object) |char| {\n        try stdout.print(\"{X} \", .{char});\n    }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n    var iterator = utf8.iterator();\n    while (iterator.nextCodepointSlice()) |codepoint| {\n        try stdout.print(\n            \"got codepoint {}\\n\",\n            .{std.fmt.fmtSliceHexUpper(codepoint)},\n        );\n    }\n}\n\n```\n:::\n\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n    \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n    \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n    allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n    u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig at @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers at @sec-root-file and especially at @sec-assignments.\n- How strings work in Zig at @sec-zig-strings.\n- How to use arrays and slices at @sec-arrays.\n- How to import functionality from other Zig modules at @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* at @sec-structs-and-oop.\n- Basic control flow syntax at @sec-zig-control-flow.\n- Enums at @sec-enum;\n- Pointers and Optionals at @sec-pointer;\n- Error handling with `try` and `catch` at @sec-error-handling;\n- Unit tests at @sec-unittests;\n- Vectors at @sec-vectors-simd;\n- Build System at @sec-build-system;\n\n\n\n\n",
    -    "supporting": [],
    +    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it is still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. They really make it sometimes hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscure the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that get's compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e. it is where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n    ├── main.zig\n    └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contain Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nTherefore, Zig contains a native build system in it, and\nwe can use this build system to write small scripts in Zig,\nwhich describes the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e. creating new objects)\nare made in Zig. You can create a new object in Zig by using the following syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). At @sec-assignments we talk more about objects in general.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n    return a + b;\n}\n```\n:::\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that at @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIs worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt is like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n    const stdout = std.io.getStdOut().writer();\n    try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portable C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig  build.zig.zon  main  src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nIn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e. the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. Thus, if you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith a \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, operations like accessing the `stdout` (or opening a file) on Windows\ndepends on resources that are available only at *runtime* (you will learn more about compile-time\nversus runtime at @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n    break :blk asm {\n               ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword at @sec-comptime.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    // SUCCESS: Stdout initialized at runtime.\n    const stdout = std.io.getStdOut().writer();\n    _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation at a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues \n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described in @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig later in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig? \nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar to our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentation.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It is a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (on YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e. identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n    age = 25;\n      ~~^~~\n```\n\nIn contrast, if you use `var`, then, the object created is a variable object.\nWith `var` you can declare this object in your source code, and then,\nchange the value of this object how many times you want over future points\nin your source code.\n\nSo, using the same code example exposed above, if I change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it is an \"variable object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIs important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code use this object while it is uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object. \n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e. if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n    const age = 15;\n          ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to a special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It is discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n    of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also get's discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig have many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e. the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\nIs worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it have the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array. \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it is a slice that\naccess all elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhave 2 elements in it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" at @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth at @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially at @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned at @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e. the start and the end of this range)\nis known at compile-time, the slice object that get's created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nat @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that get's created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e. a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can \ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n    1, 2, 3, 4, 5,\n    6, 7, 8, 9, 10\n};\n// This slice have a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n```\n:::\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat get's created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, the `slice` object have a runtime known range, because the end index of the range\nis not known at compile time. In other words, the size of the array at `buffer` is not known\nat compile time. When we execute this program, the size of the array might be 10, or, it might be 12\ndepending on where we execute it. Therefore, we don't know at compile time if\nthe slice object have a range of size 10, or, a range of size 12.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    var n: usize = 0;\n    if (builtin.target.os.tag == .windows) {\n        n = 10;\n    } else {\n        n = 12;\n    }\n    const buffer = try allocator.alloc(u64, n);\n    const slice = buffer[0..];\n    _ = slice;\n}\n```\n:::\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code have its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e. a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n    y += 1;\n    break :add_one y;\n};\nif (x == 124 and y == 124) {\n    try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nIn summary, there are two types of string values that you care about in Zig, which are:\n\n- String literal values.\n- String objects.\n\nA string literal value is just a pointer to a null-terminated array of bytes (i.e. similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string into the data type of the value itself.\nTherefore, a string literal value have a data type in the format `*const [n:0]u8`. The `n` in the data type\nindicates the size of the string.\n\nOn the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes,\nor, in other words, a slice of `u8` values (slices were presented at @sec-arrays). Thus,\na string object have a data type of `[]u8` or `[]const u8`, depending if the string object is\nmarked as constant with `const`, or as variable with `var`.\n\nBecause a string object is essentially a slice, it means that a string object always contains two things:\na pointer to an array of bytes (i.e. `u8` values) that represents the string value; and also, a length value,\nwhich specifies the size of the slice, or, how many elements there is in the slice.\nIs worth to emphasize that the array of bytes in a string object is not null-terminated, like in a\nstring literal value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n\"A literal value\";\n// This is a string object:\nconst object: []const u8 = \"A string object\";\n```\n:::\n\n\n\n\nZig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n    try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"This is an example\";\n    try stdout.print(\"Bytes that represents the string object: \", .{});\n    for (string_object) |byte| {\n        try stdout.print(\"{X} \", .{byte});\n    }\n    try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n   73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n### Strings in C\n\nAt first glance, a string literal value in Zig looks very similar to how C treats strings as well.\nIn more details, string values in C are treated internally as an array of arbitrary bytes,\nand this array is also null-terminated.\n\nBut one key difference between a Zig string literal and a C string, is that Zig also stores the length of\nthe string inside the object itself. In the case of a string literal value, this length is stored in the\ndata type of the value (i.e. the `n` variable in `[n:0]u8`). While, in a string object, the length is stored\nin the `len` attribute of the slice that represents the string object. This small detail makes your code safer,\nbecause it is much easier for the Zig compiler to check if you are trying to access an element that is\n\"out of bounds\", i.e. if your trying to access memory that does not belong to you.\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n    char* array = \"An example of string in C\";\n    int index = 0;\n    while (1) {\n        if (array[index] == '\\0') {\n            break;\n        }\n        index++;\n    }\n    printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible. In a string object for example, you can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"This is an example of string literal in Zig\";\n    try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it is a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    const simple_array = [_]i32{1, 2, 3, 4};\n    const string_obj: []const u8 = \"A string object\";\n    std.debug.print(\n        \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n    );\n    std.debug.print(\n        \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n    );\n    std.debug.print(\n        \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n    );\n    std.debug.print(\n        \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n    );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nType 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons\n  st [4]i32Type 4: []const u8\n```\n\n\n:::\n:::\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIs important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"Ⱥ\";\n    _ = try stdout.write(\n        \"Bytes that represents the string object: \"\n    );\n    for (string_object) |char| {\n        try stdout.print(\"{X} \", .{char});\n    }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n    var iterator = utf8.iterator();\n    while (iterator.nextCodepointSlice()) |codepoint| {\n        try stdout.print(\n            \"got codepoint {}\\n\",\n            .{std.fmt.fmtSliceHexUpper(codepoint)},\n        );\n    }\n}\n\n```\n:::\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n    \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n    \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n    allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n    u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig at @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers at @sec-root-file and especially at @sec-assignments.\n- How strings work in Zig at @sec-zig-strings.\n- How to use arrays and slices at @sec-arrays.\n- How to import functionality from other Zig modules at @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* at @sec-structs-and-oop.\n- Basic control flow syntax at @sec-zig-control-flow.\n- Enums at @sec-enum;\n- Pointers and Optionals at @sec-pointer;\n- Error handling with `try` and `catch` at @sec-error-handling;\n- Unit tests at @sec-unittests;\n- Vectors at @sec-vectors-simd;\n- Build System at @sec-build-system;\n\n\n\n\n",
    +    "supporting": [
    +      "01-zig-weird_files"
    +    ],
         "filters": [
           "rmarkdown/pagebreak.lua"
         ],
    diff --git a/docs/Chapters/01-base64.html b/docs/Chapters/01-base64.html
    index 36bf226d..9e6d25c9 100644
    --- a/docs/Chapters/01-base64.html
    +++ b/docs/Chapters/01-base64.html
    @@ -894,8 +894,8 @@ 

    ); const allocator = fba.allocator(); -const text = "Testing some more shit"; -const etext = "VGVzdGluZyBzb21lIG1vcmUgc2hpdA=="; +const text = "Testing some more stuff"; +const etext = "VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY="; const base64 = Base64.init(); const encoded_text = try base64.encode( allocator, text @@ -910,8 +910,8 @@

    "Decoded text: {s}\n", .{decoded_text} );

    -
    Encoded text: VGVzdGluZyBzb21lIG1vcmUgc2hpdA==
    -Decoded text: Testing some more shit
    +
    Encoded text: VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=
    +Decoded text: Testing some more stuff

    You can also see the full source code at once, by visiting the official repository of this book3. More precisely inside the ZigExamples folder4.

    diff --git a/docs/Chapters/01-zig-weird.html b/docs/Chapters/01-zig-weird.html index fed40272..1f772abb 100644 --- a/docs/Chapters/01-zig-weird.html +++ b/docs/Chapters/01-zig-weird.html @@ -371,7 +371,7 @@

    “Focus on debugging your application rather than debugging your programming language knowledge”.

    This phrase is specially true for C++ programmers. Because C++ is a gigantic language, with tons of features, and also, there are lots of different “flavors of C++”. These elements are what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction. Zig is a very simple language, more closely related to other simple languages such as C and Go.

    -

    The phrase above is still important for C programmers too. Because, even C being a simple language, it is still hard sometimes to read and understand C code. For example, pre-processor macros in C are a frequent source of confusion. They really make it sometimes hard to debug C programs. Because macros are essentially a second language embedded in C that obscures your C code. With macros, you are no longer 100% sure about which pieces of the code are being sent to the compiler, i.e. they obscures the actual source code that you wrote.

    +

    The phrase above is still important for C programmers too. Because, even C being a simple language, it is still hard sometimes to read and understand C code. For example, pre-processor macros in C are a frequent source of confusion. They really make it sometimes hard to debug C programs. Because macros are essentially a second language embedded in C that obscures your C code. With macros, you are no longer 100% sure about which pieces of the code are being sent to the compiler, i.e. they obscure the actual source code that you wrote.

    You don’t have macros in Zig. In Zig, the code you write, is the actual code that get’s compiled by the compiler. You also don’t have a hidden control flow happening behind the scenes. And, you also don’t have functions or operators from the standard library that make hidden memory allocations behind your back.

    By being a simpler language, Zig becomes much more clear and easier to read/write, but at the same time, it also achieves a much more robust state, with more consistent behaviour in edge situations. Once again, less is more.

    diff --git a/docs/index.html b/docs/index.html index f53295df..6bce244a 100644 --- a/docs/index.html +++ b/docs/index.html @@ -7,7 +7,7 @@ - + Introduction to Zig \n\n\n\n \n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy)\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy an eBook or a physical copy\nof the book on Amazon:\n\n\n\n\n\n\n \n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion)\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/contributors.txt b/contributors.txt index 80300af6..d3b64d0c 100644 --- a/contributors.txt +++ b/contributors.txt @@ -20,3 +20,5 @@ mwilbur,@mwilbur Dima Budaragin,@dbud Jorge Jímenez,@jorge-j1m Alexander,@alexwheezy +Maarten Coopens,@maarteNNNN +Niklas Johansson,@Raphexion diff --git a/docs/index.html b/docs/index.html index 6bce244a..a51518de 100644 --- a/docs/index.html +++ b/docs/index.html @@ -439,7 +439,7 @@

    Acknowledgments

    This book is also a product of many conversations and exchanges that we had with different people from the Zig community. I (Pedro Duarte Faria) am incredibly grateful for these conversations, and also, for some direct contributions that we had. Below we have a list of the people involved (name of the person with their usename in GitHub):

    -

    Calin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m), Alexander (@alexwheezy)

    +

    Calin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m), Alexander (@alexwheezy), Maarten Coopens (@maarteNNNN), Niklas Johansson (@Raphexion)

    diff --git a/docs/search.json b/docs/search.json index c0ff4a2f..80f3c7a2 100644 --- a/docs/search.json +++ b/docs/search.json @@ -84,7 +84,7 @@ "href": "index.html#acknowledgments", "title": "Introduction to Zig", "section": "Acknowledgments", - "text": "Acknowledgments\nThis book is also a product of many conversations and exchanges that we had with different people from the Zig community. I (Pedro Duarte Faria) am incredibly grateful for these conversations, and also, for some direct contributions that we had. Below we have a list of the people involved (name of the person with their usename in GitHub):\nCalin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m), Alexander (@alexwheezy)", + "text": "Acknowledgments\nThis book is also a product of many conversations and exchanges that we had with different people from the Zig community. I (Pedro Duarte Faria) am incredibly grateful for these conversations, and also, for some direct contributions that we had. Below we have a list of the people involved (name of the person with their usename in GitHub):\nCalin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m), Alexander (@alexwheezy), Maarten Coopens (@maarteNNNN), Niklas Johansson (@Raphexion)", "crumbs": [ "Welcome" ] From 5fe95a7450fc424adfe786fea80de53de8de160b Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 16 Feb 2025 17:14:19 -0300 Subject: [PATCH 069/151] Add leanpub link --- Assets/leanpub-button.html | 21 +++++++++++++++ Cover/cover-art.svg | 25 +++++++++--------- Cover/cover-artv4.png | Bin 0 -> 577665 bytes README.md | 7 ++--- _freeze/index/execute-results/html.json | 8 +++--- _quarto.yml | 3 ++- docs/Cover/cover-artv3.png | Bin 1030663 -> 0 bytes docs/Cover/cover-artv4.png | Bin 0 -> 577665 bytes docs/index.html | 33 +++++++++++++++++------- docs/search.json | 6 ++--- index.qmd | 17 +++++++----- 11 files changed, 81 insertions(+), 39 deletions(-) create mode 100644 Assets/leanpub-button.html create mode 100644 Cover/cover-artv4.png delete mode 100644 docs/Cover/cover-artv3.png create mode 100644 docs/Cover/cover-artv4.png diff --git a/Assets/leanpub-button.html b/Assets/leanpub-button.html new file mode 100644 index 00000000..c063da7f --- /dev/null +++ b/Assets/leanpub-button.html @@ -0,0 +1,21 @@ + + + + + + diff --git a/Cover/cover-art.svg b/Cover/cover-art.svg index a91b5b5b..100bfc3e 100644 --- a/Cover/cover-art.svg +++ b/Cover/cover-art.svg @@ -27,9 +27,9 @@ inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:document-units="mm" - inkscape:zoom="0.5" - inkscape:cx="491" - inkscape:cy="366" + inkscape:zoom="0.70710678" + inkscape:cx="388.20162" + inkscape:cy="524.67323" inkscape:window-width="1920" inkscape:window-height="1011" inkscape:window-x="0" @@ -268,13 +268,13 @@ sodipodi:insensitive="true">Introduction to Introduction to ZigZiga project-based booka project-based bookPEDRO DUARTE FARIAPEDRO DUARTE FARIA1st. edition2nd. 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ℜI5&# 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≪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

    BYl2Y+bz?I$}Yhi}V+_`YmoQ4%?Ek#rD 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%0A6;pMGnD6T&ItlRx9T+8m`rhp#jR{ zPaaPYLedlcj`^qFOjOr*I|XkTadbLNyBB{c|D)*#iSbt!VYOkvW?oL2u_CNuiBT&9X$z1sMl* z+@FkMbK)Aq9UP{ir-~&&>t|F7X9K7FF^Cj(3ZPok9XM=VJmI4(VS*|s9|%_w<&2xp zYvkR(rMbE3H3U!f3krU`hp4fBpFK6o=tCugd#mh`tVFZkrM>)oc4kD0RYQntq(uNc z`QHO4AVHIYE1a*hO_-LW-U*B!v*Ja6O4Ez(#Zi-~ndsm7%J*L;tMp=!OY@6AYn}k{ z4-Zr%>$Kz_Wtav}&gUqSBwBnE>Ak$jRygtwyS3d30m;H8fey?PFZ zxrdc?VLa0`oQV|0Vcp|J{imhu?jyUmgyx0AswbeX1S7RK`gp;x2LWCdio3wjzmwaUv7C%Jj0)Kga-+D5)^$LAT=|u}Y;Vux4>);3%}5AAYFSIp=oY|H4)s5+;u?O~9wJm_Gl8BDE#S979I7A$43jqh#} z6eGSg)oY;@Hu0XtdagWKK8un?SGqLL5c`kk{XhYfN31EvA4)6I74fuSilSX4mzI>6 zo$Wf1p=OYz1Y^;16ux4$kR)`>;!qU%ul;)cN|A~e*|cAQ{V};#8GYL1tg_7ggV@K6 zCMl-j+4_LS)+GK9vF=C5sZtRYd5$0AM5FoYf=!$=qgwK&`*T^x)#L-8S_palyxO%| zy~fdGYM-SZJz>IL;o8&eNo7{@0=0RYDw|7SC{N6Y{^RGB=|kU+^?BgoukzAyxu22+ zyIDo6V6N*9PjV2YwmF2s{SI*&QX2OCUyVUm@>8hZ&v|*dt}Y8XI@M7!vBc4UW<+Y<4^5o z;46U~aAleKP@YC3Tx4Vh`yBx~{9nTjgXhdyPe)hS|3M@e=g zM<_FXLf7>;gSwTPp>DSonFXI1fD`OtHYm^55CN#9vhgGZV3ieAW%3XjUrL79dzOjH7%f0mZqsKJn zWDh8j>|f_$PT()-Wn7T*90_T}FnjJKdeSBSBI0BRTG&YT=ml8BelpllG)wuT_^^6W z@U3=384nzCyU2K=KxBjf3q}RwJ1e57+L)Kj>);S6_@390+|4s;^_$qOwb-l#;hO%X z{;YXM*5El>?l=lB`z=rZXySxWX*U4D!UsDn8#%pFCIG4ubeRMQ*`Ixrzmz7sALB@2 zkm_a#c34ogyrM6-I%vwNlSPkjr!32p{MotSNKEBp%piE0Nu#hc+)g5>-;Gzo7;}`8 zHnNaw*2QqH%_6Gzn3HYIqK!6i)ss+^N5quzBH|$_rT|9!9w$!x_KRjJU?*fg4*{5v zpr#DVGx6+O5V%@^I|+7>9i=6wlWeDcQb^`MA`~}ZV>n0SC;)Z?DHPsTlS@jqAAgdK z*D!wnM1z2+$T=y4Qd0cn%fy0)ZLWeb^v6Dm$=s>ue4EbN^I5y z$?e5~!uUA6kox_5&fbtdvd;x`i_Et`v)i9A#C-3mTi8g#bOdBx0RJ13!UXL>LuV_> zYS1vFKMJa5M}CA5N1!|-SGhzZBK7svn67){ySdlu*)}5d-&Sv_0D57Sw}C%T50oS! zkw{g*OLsaz&>QCaLwQlIg;k8YSUgX54O{fFU!*{?LU8YNpKseMj&tcVM9GSwR9MT4+&|$D5qqJG6UCc*})>Zc<+!unfWgEwW#tX zTM))_J3%o;c7N?B0#IyJjE2G&Au8GRSuX9qJ={!fu~&sO^do8;V@H`!8c+F=#zXzR zLBR8}S59oA_*`FWUEn4AVQZy%CmI{JT+mY*w!~yN-9Vl%R}tM}A;d^9(07Iy&KcS# z3X9L4J)FZxRTD-L=ZbY;;r%YThR?&`AB!~91L7Ks`0@&uUk=y(X&LfKX7k3Ngid5b zRf^eN@-7Z&n7cXk)VQFozXr5b^8f1l-*zUYM~c{-zj*yuWCjz!j?R`MI60WMpfWEh zP*gUikOXB>SXQS>ZbCpT_#;&aHREEM?!l4$`qY5mX45`mhUeC)nHJAB2QJt{vuWbF5fR9T0fe5!GRCM=>u?i6uj@|d_sa66=; zNCYV`&$A64;Q=tv`O`{w+}CGbu@^IV4vrjq;8=o5Z1VUR+aNW#@%2WT|EOKQHe zm#Cb*|75E+1x=@aa+I9gaZ@N>Z(qwWrnYImu;$G^CJcQ7hEvp_nRr6gS(%){1On;S zmfSWPO+2H`FpXAYpM=g!?&xaXcTYh9HmP8r!{8`3&Ze+SQLZ@0Pvs4CwcwL16F^1p zc0&Trw8AC_sU1WYOMRVr=lD7q;9yM^H)1bypqL5`cOWhNCCE{j&mz)aRkMh-&$V17 z4pIOD{?+P-Obut>E^`IQRO!(ahnm<3XL)65Pr9jI4mrxR443os;Cuf54MMe)mz%1| z$6?~q3heU*VY|(1Gol0-H#dG@mno5hLuLJbITr>xo7qn55&!vT=V_fbg1hsWbpDIW zGC{XU2(g^`WbPwLSSni8&>!iJZ26H%&+Q>5k+IrBQ`eyx4sRJDb?92DE4U8YjjO4f{`s3v@h+}dArb)S;;L7SS9K+t5Fl)qlJQAEhGXSazfxPCW(4xySdW!GQme#-WwAUlHJPITYsqAb^M3g+;; zfUGoD)h%FgGh`9?*>kgU6%*x%Gyz3}q?`N$B)i)GQ3a|-!u8(a%+pUVS0&_M`|wUj zKNHGm;qfTr+eCd$$bp6phWS4aR?Xk`5ypDOzeg@U;(w!s4)uv}tUPo|Z#vy-t%l3X zlX3j%|F3T1VG5Fqh?he7zK==zm?k(M1eBt0%-kqXYBn`Wu{o5 zQYg(@Knc-ni#}4J)2mKqeq|dMKU2u@3=c)qho(&!jrBEV=e1(n#=d`)=6?o4A_WIT z3_Q*YMkWP0kbe(XiDGvKz7pp8igg(~KWhnA|EB}J4hjMD9}-M`e(QjjN>5i5RkV;? zL8!&Jsgn9#9c)4r+}uliTDRgd$!c>nRc%4|Q=L=}dng2Pwrd^uZMQLw^iNlnrpDto z(W>-8i?Iz}`p_P8%Yq!g#t~CGhcoMl1>tE+ZE(d?vzEiHO}}Ns8s#P}l_w6ih=aRd zrZF+53I$M)Q8RSjNAE0y5KvY_VPofp!_Q4lSzqPrPNCQZY-ufZl0k>{bIuYJa(BD; zE>jV39pL6xG2~KAg|y4iEe;(}6;>tq*A!qfHT+Q_+a!mF1^uiA{~{ea;E7Dab!~SP zwhLB2iHLutLYwkW*flZW4(^&{?XwR|oqw;tY}E{!=L!R=B1OUhPKR@1S(Nb4;HC>n z;U#=%>G3qFiyR>6}8d?XeW!jR>IjxFj!c5(}Xllb1#=xmNRF6NDhj7;9u zZkMNl<=WrHQHZqWvHU_0&m$^zE(FnumqiTtsILko*Jp2MCX*%R!jUSnO{DVxeetE{ ze*Q%pD5Huk*dK5IFMShru@7Wu;rqLE?M%^?)ec9I7)`!Xkb%Yn`?7`3zNPW>p%qW% zlzRQ$(0hIv0e~S#MD~FQlpeHN8qsp#wPSXz3Z*7D3Ih1RYzE2OOE`QXV1?|sxRnlz z+B+2hc9?=S-D)ieABlIky?N1-JAN^`M{#4QD*h?zGW5tBN%;6n!t_dY_3prCsNXVL zwh9&RWT%k^M&x?JmLow{r6l!VXSm%~UkqE8wAm?8oB;4ELD-kI1rsy#vdn)G{T0T( ztkp09a5Cv zlb$4;(R}#8BOt+M|ARnX!22D;pUoM*zQQnuavoPG7uHli3E^@^QoAovIrbyHwI|m{cI7JS@WA=|XL||Fs`iJ64{NSgk-{nukB#*ZQ*}_7qm4QcK&7o#ncth@K4S$$zL^6XD zxsRyLM#(T|vW0%FY>=%fYkkKSsmz~!Ql;zj^Qd>-;ufG%i`d#B2#|t8dwt7=ovFKUwqQ_L5$9_-^ zwI+}J2CtiK2GY=eJV_LjY3mc?8zL^{o3I%|pdV4%v<^QHg-G!zQgA#aTgobe#n_@EIyus|BP}%b0d+Y?jLH>nkMdyA_db8NreUh z+6hILW)Il;?KOGI z1wKU}*2%ugr z+c4rKOl~Tig$^uiISjcxDN!Vd7A*>`$zJa%hY+x8F!1?5Hx@)a=|%Uq@e@;D{+*e2 zarFPp#z|&If|ZCL12Y_*3DLEk{)7WNchO(cqHRKK7KrhsShW2<07VoVw*QoKng(~K z`;=39HhA`wT9Q?Yl?%}gY1Xgy#E+ED*Mb2N$r1_Jx%`Qn7anENJscIQ`u%aCt#Q8S z+e?mkY=*A%Rj+%#ad4)7`swYc8=QnX{e%OQ1s@z>i)SE?bzd-0Y1=iAH`*mQS;n36?n+Qb_*CE$1$(S3!@K{#g$FYFIaY`z6HP?5SH%zdD6^>Mul3C z2c}wX8mMf+<=VzLu!5UGG6F+eR6!sA}P9!Tt0cPj=h3O%;@($wa6^N|DYz~JOW&4=>BcZW}h zd4kL(2)e;I7Vz_{KFkE8NmXSO9?W8bx%_mv2cQ;V> zQ_c4hRTp)vxvQn%G#K%+h!?zA@I|GMz3+Q{1-oIpSy_HE%WtChY(-Cq6u~Cp_PNDt z54Zc`FH`g}hVON=`%L3B+=xd?0tN0JlUFb&4d-NR0DbA5yWeU}C#ZGo8XR0=Q71AN z1Gj&A3gHjnD2W?A+^xZHE%!b3E(38)1GVx~P16Tkm3n721n+5%!V1S`fw>KOt&iDk zl!A3g`kq>Ul%p|L%fl!938x~%g<$v%{oyNY=Fh~%rfsOb|0$}YDxZ4qqq!wM%KIO< z;Mrq;`ca4>xU$?`V(6Ls^Omyd62;;u5EmSJl9K9HA@Uf?wiGmKVAv{!3ulpj#_kBW zz2)@vM!u#p61fnUPzi5TikUW?x|2DLF`aC>P(3L(dN}rIDb3hH2HPd3vvEDL>2rSv z44l1w3o^Et3$p5VL;rhXzW+j;E}twOB}BY&DQ;rwbSKH#6&sD$2mWRAfWBK+UzX6k znjikWQoPi2Dv};D*(pCq&29>}{>Z_rhB~?MAu#HeQ2HCgtLnC^DR@BjQ7|#QnW}4F zG2`WGyi}&?q~=Q2nPh0-mncck`jBX5#P2LhwUCDitn-!olcXhiB=W(1WPS3~LZKrJ zMgbPI%13X1z3L_3%^AhH&p*8F1Dy@ds2AB?Db zR@81*7-l*+JN9hpmMpyf_PgJ?5z(~jct7FycQh@Pl*xQXL!rhi`yhYsz!*;v2EvuM zu+?bq_h=NCnXB;krKrf3{XzF*0^wbX6epiDa#|w)BY|UAiW6+mJ10b!i%`0>_#X1e z7{XbjFDeo^6w*ua$%m6qc2JI_?4f+!0aZ+iUj@^o$*5BJ^LS=CBz5$nj`+#7Ot$tLL9>G9zhCVw=X{Mohx^(=`gcjQP8a9MMJFvjKalYaMv3?K6D;!24}zo!{c9iX1vZOc zWtw-#n6ELw}~3QSf+%M#Wr@!d?QC+&3W_m zXTV7}rwTCt2<77aFh1uw;J*;2rAU@HK-It5HA>@v8A~X)JXFmnllzT{2o}akGR@f% zcg>b82Lc>1{(c++c|O{*4E5f0;<=TA&dq^k z)5SU|-GRQlKnRHJs2GgxSZ5|Y^Oa*uG+bOepaCRU(f!on5ji4VLxbuU#X zbH-c7H?-J9m8AwpFhFZ9P^{Kxn@6u!RfUK0bYWcEopojQ9OUazdV5kiW{%{ys>Y>{ zzO}saHu*t>sSiSGJwKme|KE@i>zB)eGBqU-RcMk;nv0+-)#+F+e|Bwck8;23qOz| z<#c2{A88rew0~}i+c;oo0Lj7`-Vb5<9q=3UGrVnUdbl3qZ#O#Bm|^OG?1Sd&(#ww8?Riybt(euY)NJ33|JET>o{- z^nn7#Q2m|L{!qE*>&9yTTT99Mp^7V|7m3nB+*uz{9*MfWMPP&)Nz;_3Csx}Kh5rc<~ zwN?NQd6D$B(OFjT*5+(&a9nDH;U7I9rxBnI{^zEs`xfy>eD+Mkbn>^bidN{ISXHS1 zxwv>7P*tG25Mu=dO@V{luZ1Pav%q-1r1LZ=8om*$h%3l8C%@`Fd<8q+2wE%hgKL1a5Hl4Oi&*-5i+{O)H1N0(q%0NYF)s`PkOk^LYzF zg6!Bs4cqg*p*Jr7>Gef;b_?EqE?;-C-4gdmF^%S}{ZF91dE|?fw4bZb!2o~DDh{O+ zvsx6WPxwBqBtEC$<#WC+OtJXq7<~v!Hhr-ydsjfgr&(3D!)S{@#fnv9^c!R&p#b!a z2qE(gYGv*34eZ-wV27vPRvk9N{|bz{CdRc*I%i^7aVsO>4_^x7@;p`ybY#$!2o2|E zXiV0>aS&)R(!jJ-b`aMPj!M(6Jl%%dN-wEsP|ZApq;4A8%BwcmLH zOV2KQ2xZ_n+FeK*?6UqF3T(m4WAXGLAt>&5y5jNiq4`6ktC*T;QqtF>=C7K9_@)UiM>6nJgsE0Ro~ z{V1SvyZ%W3L}luN@AS|!cMiqmzR8-H zr)yH@_o>*Pq6>GHW@S!ogL+Js-Ag^n)5d#HOU`1RyJ$tyF{tF!Tqhbxa&(9M9=4QD zNt@(Pz8XDtLcKWdk&3j~0KHqFrP!XN`jDp{zoY%5F$m3D!SpufPCw*ZB<9H0muyH) z1wcDA)on+ep1Y)J-}+thj0GWg0thJH zy8FlQ`q*;5^>&gxaq?SbStAtY_}K27xx4RmN7ARffM-y@#s8t{s{*3zy0%HBM27Ad zxM4{X;6>m1V%>%>~)gLt1ql|uksn2g@y{3$~sxkuIdp2R|` zcgF=3Zaz(3cqn9on8wnVBUloM7?PA}t&_WnX61>&gAk;f^A&`x*o{hyfIZ~C&2?3; z^KTC2%V1uFsfw1V&R#R5?cfNpd+gsKI^BODLIM7a0 zU7C?;YU8HDd}nB51A91K>ge&h!RjNrzMeh*Uuj_%7mZVv{@>grkX8(pLwOWhyNBad zx;vcboi+MzIEDZB!%)IASVb+T6WIE0DA${ac0dM_oX?0qgoAysix&KXY66VRw&KU{2uk}vvi9DZKbjOOT z=4;2kx|-?vDJPi5v)t(NYQ!{Tt6Cvb}#1p~BkxVV2CQD2X*tq)3|I*^DzFMiv*9^{PLux0A3e8A7A; z(Bq~WTsC*in4+n4?b;FO)yU04tKU^Pby~Q)e&|@W`xNo} zhY~T??W&zy{+rnM*qsI;87oA5R#uY2SFL;w8=dJYv$k)~E~hj&3A^jP%;GYt5P&&# zz{U~3SA+O*JV{#SC(fqwBEi83z79|9U!~l}iFv#xj>NSfrXE5{89|al_~r}HRO(3d zhE7t$kxan7Jl~CNeRd>%**j_C%&~{>SdMn?BLlQ3;6C2kIWhK&-HmV)spY+y=q7^3 zMVI`c4Es@g7u*!>j*#H^$=iS+!rX-WuBeo-SX~C!`N601H|TE?L=7e%ZT_b(c-*1M@4pg$7svhFedgJqFhAt=0`>SGMwi%l&05kg?4k?9Z2 zw+>MJ8u)^uF7hjM4~on&eQ9p=KJN$Vs`1@`?TaF0+Fin2F2^65yI*nzQ;^>~8G@@F z80als5<{7y5=6HP>Ho7NC0B>SH-qG>jSCl*CLi%3aAsrVn+D#C&LpRt`3lmiRhaOaMC~gJI+5>YL62cE6MlGVz*OEa#omg{TuDcf^y#pTlCPo zHW;#`%jO_r1e!l77r`CTdXKoi+nf0nAn3!=zXAitFe&J#skMOes_S>siQdHH`9eAJ zk3H0a$X9%0bS5cN-m1Iyue8@XnOVDxMXgQLtGF5l8A-8?taC9pIF5@yTEBzJ-CoNc zFRXH#{Cm}s8Nj@mggpwXCB7z{I1RXdQi?xXC6sJoln07g}ke^z``79x{(xpz%`VlbAu_6&e*%RbOP@}NwVGclpc*4i&6 zkIcfeQH;AJ`$a7;r$Sb3rLl|gy9OO;r&al+vYm`$5{eZNBuv0k`!&fVCpCxgi#Ndv zjU>C;99~P%xRR=M4T<~qrKd%UexsAW#!Ztva4T-Is3GEtiUAYJjv}kE)1y#w|go^RerT?-s?o!BAn(d>VpSL{A?WMVYK~@id7+>^U!7KuC+3*9JHz3 zrin&6dGIIqx~#YMT}G??AGL`W+?9zBX^ZF4Xo%wCXK>WrV#~ zlNcW-uTyiqqseRSR5H5LvqziyVL^i-qO^L5>;Y?lklk@0xmV;s1UE=a#Poa^fYw>#hO;5b)9OaNvE z!~Iqr{beeIg4yPwX9ctMrmhWktQXi~&;l7g_1*?QC)&BY6^@8`UVnHD*RY#jWP`J= zCBCgAZ&hZjzMYQL^)`9PyuO|?qBPuhkV4Nhy^J*VdAHK~UQ}p;#HR`PScTs9F}^YjTHO$v-L9QJ$m*&Ejj zFTGk^{PQ;Pr71`g13*sVsByLNX^D3A^8aYY3LrF5{?98T0;g!15OJj`<>|M!;&TaN=WP53hqkj-`r zLnshC@v7hslg|XQ7zq*sdYq0XIl>f^M2SW`_^T=R?6_SiUMc>Zjwt>;BA6mQrc7w! z))!@t7k++dk)OmV{csBdex4$a5ZgW}Z$CFkB4vYvmWIfH{XOR}N{B_UUW!2si0wDe znVr6Xw$`bb$1}0-PJAk1)C=6rJu1u}H>jne0QgAbfHNfMGbsQ($hR6&*4F&V^2UjM ztv%80aZUa*H{!+JzK?ksqxwx5@})C{ybIhLv*$nTP;iY8-=iv1l|(lQ^<<6bRNR%K{ZKn`*yb;B zN{jJI1D@FDEw5H|rq6x$B!4vFABg3{Q8L~4pmB5c7cw9f^LzwdkrxU+r#;)64Fw>G zfEq1NRg+k^Q`yl5+1vELm2Ixs;d5&zpGiKVQf-_n2BS&|t*5SM^SM6#IPOCZ=m0PW zI3j}A<=!cLWBMH9#}sX;Vm)cKiE0t;-S|(hg-2UT;M!8ltzC}24W1U<#?;gd0xOX1 zh647|Jvo%AFzpkK>83?m<`m%&2f)rI@=G*stM%GbTh(WCdBYJkfb8>_P2$;>yQL0l=;RMR=US~zF99OB z93=;sa@aFFLkiTPv@b+w69)lyU+;3b7fVwYaej!hfj`u*t1JaTuqmkO2dFHbzZ{vh zMo`>!^!-Z;WUqw9ng(@nNH*~dLIF;ybppR9rsoB_W^&<4GAD13hkH%o+i{@LM8Flsw ztt)7~XVt^I@#1U!t01a5efZl*m0(Rlpff~ugFf9~Qxu<_a1V%wEhJa4S;be+5_)hP zlc|Q`s`v4}-v-Jpma~s$@Dw3ON@Hn?+bJi*(Hf`5G19=Jyla%~ubs)5sR+>zM)@$$ zdH>Q3_8k8*>q)=R-m^w5Swt`vMj!c+cjl@!`^^6F z|Mvp$s|G9jPDC#pRo}~e0rSS}Bz@AM3PmC93{rJ~Dk#I@Nh?DBIt-*2^_51w$HSZN z6Fdb_7h>7Chd02nF63K8JUv~NrwIo9C%bf5ZFd8Qw@+iMys_ltHaNPdHF(S2V%EdikG`7u5n6Z9wA;aRDx$Pbw-LBa@nY@UDJnNQ3ZlpUPmH6? zD}?1dq37%g1(;zV4&7}u?Nlvp#6s#yCyr?6%)4K?7uKL942w`!uFdbpwO!Herp zm?8~)n6TSMED~Lu03jLrN+VPG0N*P(0jOMmE$ZD9B|6Kt6-7EOf?Ehl{W!mPcjr3* zhlioXc_v*n*@SWpHpiELOmZkojeR}hlJSGevO0L#)O#2UyFi7kgyhs%fDV=V@{-Zj z0m`!IZ}4`%Z`ne5_`GSihl+{HX?a(`QnTM2Uw*5W>qGelaoO7*&t>(()C&`witV{^ zRyO%}of>*8eZWr!sn?%_4vZF)k4z3yFlu~7Hsb&CG)Q3T&XW!-zuP;Z!E^SOdZEN? z0d=viAOlGna}>%SVwU8mv7;2L<0eTa-;k4sq@>kf59G1@g|gxWS#t}7_xEoUp}n(K zVg0K&EL0?|mncrxDG;Lw|K6R>5HZ?{q?SU9J3RE(K=e3}19Rl4@dmN_16(9BEuz%? zM?U-C6B}mqz;V#DMDUp>HO5NgCyY22-H~WW$y>hCW+9+W~1TAR_BM}2AgN^ zmobVnfCv?(NK9gxS*~$5U_GlKAQ4k1EK`~ICktV&{s-3wQusp$8hq3G_ zk2e~>z1w`=DC~N~!{kW5>2j#>%2fR{I56S2UN4{O71_gVIeK_{b>H$={bu;`e*+}a zpl%Wd3^hKafVz-;&VECraC0j29S9=!8;^@Xg9HqTuDg?6u8-vhF9QocP3Huja?tN^1vKr>%8 z7l0)1ulGWCjj7kZ+JV0BT!sLQ_E&umWz0!Vh(%ez-{=AtDWA|j5E9WLNwv=u6WHIi z+Hh}LZfsv2-mGU%rAUr_#Q$GojwS$Q#NkqvQFHckA{K=KPZ7uP=F`O{kjCraPzYIf z>E!wQUAk*=@8+baZ(&sJl#6%#gTc zvgX{;1j|vMtVu{qU3t|Fi|chp*H?R4zNBd@(kdM*v0<-y1$A)ZlyEvzQrzfDQ~p^l zyJ!%7hBx}*q2&BYBX^|z@raZApWLBL7A|H3fD-Uu6!sbK-{xy7(|&L5oeF;|yJUN1 zW2Q$nw1@tmlMjSj3CIf_2aZ$k?e4Xau;EA%pbp72_8i$-xHc@3>gYbpe>JI8ts1&% zFF+&_2Yi)cad4sIq20Y2sYu=1DMc4pl~0CWhAlOSAa_0 zdqYA>L)@+}(y!yROZCb^NYfM|H#u|%v9yg5OpJguoug1CDKn0$Vi1UzN;3i7XoYC0?mNo6N}?DY_+;}+18W$1D;L4Sh2lV3i-}{ zU)x+(5$Yf5^=7!9>O0qcCPyf5Y6@6c0RSs^q&ol0B7HK!n|ce3{Q*tv=W2Xy;dr=O_CaL9nxg*#Mi|7K(oS%Xw(S%gCT0R7Ob-3LpKu8m8+95 zbDTimH&6fcmdr?=GGp@GE~d<>zt*Ymj7GPAyKzw!hI9ZI=7C>19>js)7-X#{=k}TE zGZ@8~a{0sDx7x9P9reXgVC?do4t{xKcpTkjW$X^ff_oz0^OIU|J3qm-k&Msy0kaY{ zIC_k3QTgFZ=4gv|^Rix)IMtF;Zyu@J7*s1!$Pg+#+qL>;dBqFg?K)lPdwmv*$Vl~} zRe-s-9@Tum!n9|xG%Y>U?e|KLlHNT{x~;yfLQX%@_!#l+?dsO;A8m@>l^@b@!X1B?<3YQOp<7WsI^$$OqvQ&+SF4p0(QtnTJx*`|NcD7 zR#VCVMLxobBP>dV`Y(U@T3<^d*dYk)*1YRvsAD#y9ei~o(IR#!fI9b^&2@ZNVlfG2 zMU?V|b=xp}!VfqF0QN4J5ry!nBwAK>^sm{D+^1z}Q<~lF#5E zIEoR`9}eC{CuhB}i8P1tUJ9~oqG9jy(;HoZunYFYnVmwJz=W z%k3!dvZC^IS{HTpM4DTDy_aXdMimbJHdZqX5}o^j((!!aEqV%Bz0u34`!y@zYlHsx zOUPLFrl{S!amZZK#(_(=RP|YXzI5iPmPFy+jeCK>-}+MoU$&{+(}4&b_#K$mZj>cF zcINv6lz|WOF;XP1=h7z}B>=LdZj3>=rHYiQeI9o5qxPu_B{3?=#Sc&zzwu+6^4RnO z%^UexJ?ZxiTj+~Kf+yel8(?NB>Is4zVJ}xMA38maTB=8uTG~%IC(aMTxEwT z#s;%D?=#0L1<%i&M%CH-57R#))SNmgK^sru#^_VUNAih0L>6fRY{xJrJv+gqXI_7Q z25%xKYpMp%N5zhDRxS)o&=2>&`D;1H{~7zKgD5mmz8lZDf}&21_oIiXxwm6DZYRPsI_GS4 zsuKFZT{kNiv^p@M+rm`+=+uEf0yi-Rom?O-sYo8!EbcFD7}hT}i&?RH@@_`i>d4(Y zwA7MlUpIES`GFEYlG3UjUMnj^N+BNC<>?Sg%1E#H)66%Rc2rT2;U}_8@ORS`7mgze z2<*PAM9r>glJ3|}k_MsRVNnf%<^c<@v#F+rimT`aojMHLnc2FsL-c!2bgZd8@1}Hf z$H??(CZG7MK;wL1dF1XNw#_i@q7}OF#RlrS{3+{Ceo@jY1XhQsHGZpsD3PXZlh!t@ z(o$vzHY9LJ9zG$iH?|T|S1&7h3q029-gCKKx+oJEXC4au!AR2Bk3?**g?{K^TCWbnl0+;);G;#G^MU$;B@P0~qei#_a)I8gTa#s-~*X zT3;4=is{NpXn~Fi+z;0n3@>qi9=+KW>6xZCAVFB_;g#R6zkkX7!oLl}?#1jF7kZmD z^jo?RFCQM@K%PKnn+{u@-(z8jL-|T^3q>pzKP-j6r2dIv;dK@Ok24nR70>%LYJ>6i zrjMlkiV6;+TiaYem?nl{5Ka*ZyHZ>t+L9_9H0-FJ7)fn5uWGiBfW#oykgZh^%N({P zO)-c}8&~k^dlJnDY-hLPmya!2K|)>H?$$V}XgD52K9_cUe=C1td48ijUOQs*L#hD&2Q1|3#>q}@o&*E#$J*2bxOYMAN^I%KLzsD$oMzsf$Li%b zEu34(Olm`mE6Lv2t20{oGtHVc;eBL}+6IB;3~Ob?d%Bzby`yPCwl%+o1onl`#XPoU zUq(jhO<=m#aM_}`uEqj+)fVJ&ZTBtI8s<*yTeuoucKdDFBW=K!XVIqT2Qx}vi`nUl5$(XqL+k0EzT?)ihKuxt9npG)lizX{cUX*? zszKr^*hEpRRDnO+V{vIK;Uvqcks&2CFes7(R=)~q7b>=RIqOo`We5g}qH#a2bw~w< zLWH6g?gxiNofAj5Yo5~vx82rz&8s1bl}|2upJsgQ(i&Gp*4}csH7cbQtqJ58H36VN z07!6citq=ncW9G>`bC4p7;_-9hj_(&iBergT^LkL@`V8+?D?hPX?7Nec1kL9q7@cd z1J@uTZQ%DRM9;7M7146ha~HX2y;XX7S~5RfpTyY- z|0$%Aft*z&*#bZ5TXd;6WvMS^m9O1k11G-cSUB6z;z49(wKKZl5!;Jt9K5dfI$8$C z^tS4CiH#qw$y$ABO*j@2a;yd4;!bB;N5QxKeHpl=#PUy#^ON1jBuy|G`Z0<>Ta!b5 z=4IojZ;0NOyLnxoW|{60%ZrVSu=Q@4#t5ux?cGfZM%JLm)Zh2W<))Zdv;Ua2a$|?z zI@p_=Y}UC~`D}@}6`R7}!kky5=DWeyMDR;yhW!h}jC8iHXdAg~YRrV!%#xkhr~9QW z%WK<~Z(Ckv@Nlzb-f%*+SL|XJV7+G?4JNxj`}y9}7rnbjts2+B$65>LbcRx#0Xp*L z3)>iT-c+U52;&43+23cf9{sC3w%XGL_#TDI!YZss6<7?Ho_+Oq*KgE&rr4VcYSu`j zbF8ylLR+#ePcPugS5_bjJR%Sr8}A>TTGQ>>5?5<=N;>_bP99IE-GQlg8h&N){*iAp zl*({*jdQB4_7-Oagi+RSn`&1-q;ZB8bU!!ET5om&$-k>XCu%;TKgd3> zZHJIB=k#8cFIb9SdDYJqiykl2r!&3SoKIiV5vR^%++5{#)?EEvo2HmQ*o?3DRM~RU z-l=7GUaa>%=E6h}-hAGM{&i`#TH%e#KCrPXtFdoTV@vWfG$PYqD)uEizf0>GlWi+C zTwW`EcALrlNU~JwNdH`w=z6xRa+Pss<~rDBmodK&S+tVCJ{4`yY?ZmX>>+E;E+W9w zJK-*0U~1K0Cb7$0p;&iqyFdL&Fq$T-$NjBaz;9<6GyQ%xk*Q+t#5GdjlO{1plAqEv znToJn3Q5$gam$;X$th|t4}%e3^^1vzVPGIv#iL(Tc{c-JpB%faiVvlqHx%xx9(@X;cN~_TYo$vbc z;cd-|()2h4au5(*iUa8n13SPn!h&MP`@?cEW9#pw-$DBSgd)PA{ix#vr_Jc!P07{* zOWab8@{CjKE5n zGR5WRKTaC?!x~Db{=6&DrAq2 zN1J24ZpiYB$<)BT901j6VizA{9an zqs=&uV1dGfTstC)OI~ESquUL`jXAZH2(pCd6!{-;n&e}m>Yfw-G1q@0@6lZ*vYT-% zyAhbXx+I?=Qj>A}D+P)|k;IWs+C%<0N{?=3s${3NRiltRNL&g0r zuSp!~>@l{yu)I6(fQ;N*TZjT#GezT4q<3DebvF1CpMxDhOA~8BU~uK6rB^c!cDgo0 zPM#8J?ppbgV!RcHVgu0{!ylt1yP(NcWa2ICfzL)|skX|Cf?*d{cT(4WsYoUS2q+QY z_#=esMN(iaook27=9m&v`2D+%wf*e`3+=dA+c1u9%ew2+97f6Y!q;2w(pjj*ieDqM z9q)5*YSeXNsbvNZr|i8Wgqq5>W>1*wAI@B;nTi=13WZXjFFz6Qo|uhOcE^^-+>R-i zOds3srLxXOI;5NDli6oB51)o`HDlrf0S0K`P6)Ao#^g$UX33IPG-IPe50&~!&w{Te zdoz6@=BJLXvjfarTPiZt@R5O%T5R-~n3Q_$_Qy zN;!32h^U=p)P@$$HCij*gKyAOhHf3!jSq-;Ka&HEO|#hQwbW;nZztAD-LJme7JEkJ z{zb-%8u^KW|2{e4zQdu?3mLU47bA9(E9oKZKY6d4f12#=O4Xvpp(AvOGcxxfmKIrF z^&vYIb4R`*Z{eJ3UdAmj?kftPlB!A?ua4Ryh|O6dg&#h^3GK8K^F$T%+R@L-HGL?Z zjl+MQ=mQ0kQ1P!=Yja`S| z`L!QoxTJ(lK8oxJ=&Afbs~e6|HH{9{%R|SJ*%Gxq_Cfr&V>gP{&@ZOiW}|rE;p&?| z1uQAZa4M`f%_MX29<9z^(dY=!m(yE|N2yEM`sIU>>M@dU3hqYs0`@~Fg#`aN?v14Z z@>oa$PKTv*^;b^>;GKtM;)C?n(XF)aN9$}>3-IqA8o+2d$JjRL)z|mZxB`I~AnL?g z4d>Wvr%F~d8Y$;)dKte?bWASh-}_(|t;QJcK{?%X(n{$Y?i6S%kNx8JP#d8@X}VhX zpZNW#R6!-YE%neFnLVtIh1$*x+R2g#QFfr@aOvOsLB&#_W@OzAwJuc~1n_ie~MQ@3-aHJJ#gQye6 z^Dx7*G>2D%S+by~qz~De!oH9d9=u-yeSCw&yTwZVT;jiwfpsteM9BS)m4=0qG@EJ{ z0M{uX=%k_B27%1N1)@dJ23G9|VF`6~73Gvn$!fAIqhv#j`m4y+FDEx)Q2YUelFC7h z32EgYwC(|>8dTzNZ@(Q`)7r#ZaD$cvuzG71%ZPNXH-29DUyE>|=NN|f*~k6_r2b$c zTHD>O`5j2p9Neoll^v>NuX66=%Jc)t`dqxx!%*$=Chj`tRJy^W(7r29hUQN=9hd`| zb`aZpzwa7dsdB4Be~g-v^VqW+Z<7LDTgSoa^i8wZOL2Y6jbN6VlpGs&QV_vSJ+Jp> zvZhLr#ZSA3`-%tDpwlg|Bm1JbzNy>0wP;>@mScZbaE|YPy6+RTP!dH`-grheq}$sv zJw}?w^dJV=gh_ZD7q0de@-f&iYdlXyF&qy=bdi-y@5 znV`XhoXXr&v`6jL7Z)1`>7b>zYu!z6^?F8LueBFczBVp#xIj^Xyi-z-HcVOcJt>QG zPQ9%YVOs`(`}d;Ld!m2(dtCXYnkhHl8N%M{9IrrL}0Cakyil zaWXlU64?awna&ER9YPgtwnG8U8x&*GOV3-bKes_ROSTlXo&^zdV2KG9 z`zxus|A893@P!|Y;Xrnj=iiP~3c>k4?}N7wy~x8jpHb@#*6cy%Q9O^4_CJ$7EkHiM z@e|cLldkf=A}TUjZAB7}m^~kQ+lrIc0>bsL;2u{N$KeEXbHGSOdF1@3G8UF8%yFP`fNGJ+Q{RG^L++0Jf_Ty(wgO zAkchL3jMQ@Qsav(UmDL+?M1MMxT)=2+sAN(rU27orizM>X=$S5zle_ZSn*1q?~~_q$owq;ntxcWO0CKEdAY5ewB|_d#JuU`tn% z`|&P?z=hUYeGs+2&M#R4RI8<9BfXqxuvEDD#zQHvb~a9bz2#nqGbiTEHRS;+qw|Ly9uAx!cn_e!9-NVF;*REBMjA18aE}gOZc%+7gqrhF4K$Dw*$;BijW1Z^s{#`?F^IbrZg3 z9u(kn3J0P|wtq!sQmqK04}{)!<0RWtvzx$}4f{jKO{XiQ3AK{9XQtFN8N4q>nQ#9_ zuD$EcR&>TD&Jgd(ctsmzqt6{~jIn$4!kzWsE(gB?o(XW3|I`w#X%AS7(iFH`{5QYG z4H@n6?ekwq!V`M~%fwz+w~loCOmb9-=re)LBpTP>i`zZ@M7C_PCDmZAJ`<(dN39{n zIA=Mb-_q+ctoLYLK1X45PSR_-zH-Qdp2gL6+%%3_`2*jDDi_-iKJpQ5steyhr3QKX$P%rL>}Tw6&3v5ce}!Reb_e7hI<7!xF=iIM2!)(+8oqXWggAdMUoxuHO? zYum~iSJjl_je~C;TzV@ALay;YI~xQ7A`30ZPNo>Mp)Uof(p}lSLh2UZx5_3j#-P>) z+$yc~VrZ>(;_#S?-c1WeYth*)7W2r)dfgy)k6&|q9n?{~p*>&rZ4&wEtLp}gH7Bo? zUWp3-|8xnRzA^mqD#7>10*ry{A{g1PZ+=nnsWROQ^s*>LH7jXmUSKu%-Q~h0&1J5Z z4i6`_CTn5dIqhaJ;`tBc?uXQ#2W`3t8-4AMTy;1WovBPTJe_x7Dq{pF;H*~$a=4&S zDMSQ4|IuXcgaLYkGy-U-m`AT4c*#SdT1p_80V_#u@Xxk{w>}r(%LGh(-eIi6XY5g1 zV{m&Qehml=-tXy6V|FjcNei9a`MGaoS&ifs(&;$adFJ@EhQN!ZGEN>K(477uD1{?d z-}(B}pGsNonjicf7f5*ayFi<8vA8nTZavWjfvh-3Dhf4Uq+ArgbOy;m?4AtrVcT#2 z9P)}TB)@|nf(+rqeD8{OL=x=>QK+JY{`v4y+{A&zlULvI{Qr46dPv2169|wHfLiwz z6o06fF-r^P2O6iC0qe)avObO`%S(mf^E*w3Z=>+#SpI@meJQmW482z=z01;Bzv6#P zGsjPNBJKS>CZQ5N--(}?Q&#i0{Oq*|pwK-Tur-6y&62?3B_)=zP_N~m1^6jvT?=dp z?g$GyJtC$M-$5+3dKHzy7}9g`?e}Dc*CT59gl!yDkIPzhX4TR^+_VK)joPZPA_1Qq z@n0kg^uE4wKPY_N93Q9pe-A-5L{17=J^E`XzCw>;c)V)4O{4xVSf@Y&YnJ^|Tq3)m zhOFKQniJH*$U74D7?6yc<5B`Qdwa32=C`aT3 z062AkRYJ;BHwJlk0&^ypUcNKCM&eBwUPwPvvR4+^&Z^bytbo|usXq0B?@MQ7j&8mp z(f4;|WOyZYFo$Nr>=28&l%y>zEybg!G{YZb0hYUun8lJDz$2#9+WCY+6&|SCE-QLZ z9_2+QT;Jw0J3eRAy;^kI zIR4Wg+Xo9D6@RWoDrup-R*V$3@i1}5_=Nq>Emu^^YC@hq$ZMR{wc#|2->MY@Q9yAO zQ%hx$O5&HC@_Nk2-obk9c*mp+Hl%cWB~i%6#ixG+_{wsz`m5WfRzH?mIVnOwp`9(} zh#FcV+~rzMqJU6_OD6Y&OR81~(x@u5TaJx+RcM&{2`(DJ5z8p}qnthu!^EW!yBBXp z$xF?rev%2W{%whDG`d8^dXpY@Y@`VOyX+K>-^d*U(b96r&a=d~^9n-lcTh5C!4KXS zX_DUO#a{DX-LEZ1iT~X-mtY!ay0>8>1YH&7-?4O;q>KmtQyTpIN?$~|P{sewId>Q5 zeE%EDR_SKQ{`RBKVakvu^Gzt$_mTHLA2?!f|Ab2s)V4!1QTf7w=^5$6X<1PtGIbDK`{-v9zdwDVK@@iZ z`Su$+Byb$0J-3e(BJJ!?gI2fqsjtnJJNrofx#g$=byGrzbTP=Xo9CK*0a%WzpIKc{ z$Ql791jZF-rC;bQYuexQ^Taq4qvca$0#yuE8QmQae#>gC3SxLYNAM>*kJsHddl+hI(pNbuMCEef^zsM&c7WpfD-(bNRO5=c zc9W)Y7A|(fHELIfeoglaNJ+%d8Vhe4VlW2$Q(Ia{%yiY6l8G@r-(pP@u-jk=qmWWR z1OA00kg>TE;qF`=zLgXHfzO7=RsM;$jnd-LwJcCWNdH{&T@xY{(oL%2Rv{)lD9C&nH&r&&j_G9_nlrXULlr8hT5z1;1I1&iIBibR@D`Mqg-oD_I0ZM$dm?i(T) zSH?w5L;k0=jbU(ZrzbyM-t}j7(f0$64#bPVQYNe8p9~mE0Qi-06f;@;^p3vMuQYTF z*fEx_o|O8N4d1%KYqL)wzv@4Z_P_|0%)v}%opzG@DSbzb-*NF1F{w5?>Ul4e74C+( zc(q=CJ$4@Rt~=jA!Jn}Gn>kL%xfbC!AUQ=YWD3%p<{abP%dk}sFCtX1UY!#8=vuZ8 zR#J{VNn=mPvhtb`9!!;?VGo3UjuASYz2B3n9^Z{!b*An>=C!41Y22F?_x0P;wzbk~ zYuaz8yK;0ed((C{wH63S{M)akX{UpB3{WM%CFI9R{bxea^N9+{xvZck%XxW_&x?w;ki9uwuexaFt!Q>(gMd@1U#x%=uf{p-k=KC z`TAO7R5ddcNnT&-lJeIi=tp3Wr{DGt2-i_njFrau2{SYnbl*&ye35GU?R|Yn@-R$P zK~QSMelU9wL zbwI(ld*r!bj8g0E$KTBIM5_79lwx6e3`b7Z31eO>JXGf9ZMp{^d>|-rj{~PI!G1Su z^}J3`W*N)vV~_J82(_^7j@zIh79y2taa=Wt_hGT^=o3LP{{6Ql+R9|ulAjC3f=bYU z*DW#t(Z4PhhsQF4S6)l71&K$~F-<)^UdPTEcr0SG3*ACrJK4Pma&YOgvUOnzA{D!B6`%yWn%8-iFgvLdN*z&T`CtAZk zwaWD5q}&I&H~u-rtVCD#b_)}1VNaD2(-+~_;uewd_%t^`q4DzP<*leY=;et%z3{Q# z7&YdPFtw~PNVqZp_$@!q|D8W|N)saAj`!#ZZB4=I0I9V}2$#3IQ` zDlT#{-Y;@pqwJFz1khm@YHe@MkK*M_Gpm=6IjHhqT;-=MIvm`75{C`7UD5x}T1Yy* zxc?h2RPWmmzI5{tpe5~{13{lLm*f$uI%PzFK25T0POOV=VtGbQ=vl<`A5amKi6hKM zzq(O4?B5sdMcbACjLeXW)%P~Q)S>14TsH_sD=X`Du1iWJ)gl@6+Vd)wppj$;-Fj>5 zHEc^}$4vst+51hmT4*eBdMV?sQ4NmxO^2~bagu?bvLI_{@7n-(jNuE9+NEjp40ruX zN(O-$o=j?$w_KtKf*NRtZ@g}Pnbt?`)r!@Jd>+tvU*&^QQ>y~h0+p>qe$a{%lCMZm zi?0R9ns*}>^mFZH5!IoL{wuV&pAx)qA}pm-?eIA>s2qKWlskK(zC>A&nTlgc%x))r;v+bIIX;K8#=@|QNmv$#>;s4 zLbpcm^j(e;o97#Y52Mq)29hCvbQN)9Ogok$Ox`bUJB%&DRgtV4c@w2&B-!4`u#dj6 zKj?J=mZX2p)f?;drggG7kG4o;PW3r!iAiugngZ_qH%abKcRn7gxm&CCA#z|it9~Sg z0fFQ}c`18-euz=j+GSN#SJ#%$%1A~iNuD7=z&Z+N;|d!w{g()K;%LIaY#D1EoX~lQ z-B@f`MTOo<3)`Qb*nKYIx-~eCuz)V}2wQ)Fg>Mu6f@{0CH{-oa*}S!LO{=kMM>+MrGSo!m&V&S*%k=^xRc4Vs?H&EGBzjMj|(HYtG zmpiJ-A!$rU-|#4UkiEdms6)oz$DKvBR|Pel5O_2}kK(iX02t^zfE5DnuDOe@ST&OER-mHmyGz z-xQ4w8@@MZxJksuSyLV>Ba_mM;+%q>^8klVad9(DwlOvJOL&!2!7MO+D??FJxw=k8 z9EqYQ7!Vw*Yh^R)X)`&k+@O|F(h*wgPhA%6VmM~I?I zBwKJc-KIeUgOT3ssF;RUzSx((b^h+G!oVZz1Tt zm#ot=SP-J4&1&tss&R&*rM`tymmsKny)LTJ)H>a0f$x3Nj-Q{luxs;IP>P?{Yzhij z!b6w%IM}f+_=+~Y@0$;FBfE~dZpB=`JHFT?TqJOJaa0kZ-NV9GhplvK!58~5pjWRp zo#n|Pcab1qqh-*BPb*Qrhq`E?H{MJXqdU5YXLSYTZ1{u-6g~cDn6E>_>Ya{Ksf%+R z8>AO6TEu_Wv*BrXQCd8h;S=dtxFy78P|Qu6AVXZOC}U5mKB)4lU&hG^d_+v~*;c=1 z2)VIz)TDZ+bkGKoth+RAQY(9cZnL8)Ufa$&oh^sc$GXg9F2y;6?Wxu0fuzpi zkYuf(nYE(Ch?0V}Y+mp!Mp1@YK@I)Tp)(sIHoU_Xs4K;aK&d)|5!A2u=P#57(qX)y z=ERzB7>qCh-3j|xw18>Y&i1Yc6iTLF{VJDhDHyAZL9%ftIZ+gLSmgatkU8KKe;ZfK*C(%eT|;Ib z(t1-Cc)wdo&AI* zKT9)2J_MbcG3$8rsr2O|gf!cjwKXNX#Eb_sHruVw`S*7_4W{Uar3w1RzfdvL{dO6T zqKfqqeT!O>nJeYMTqSReny=%_)D2Gu-vuf)pK)IjrBT((^`OTc8`{Y(xVC-GRSw$t zK=d7_1H6zgJ{;RJHfY%Geyu$cB2kyBG5j3fx|UP2BoNJyiQ`dS<+^&O%lLUZy5>as zl469NmpxlVSAnx{F~SsnCb-}Y<+a#)b~VASi-g>h_wfj#_YFPUNX=N+6X-;^;F%AD zF?bRml7JG5*LpWn+}si8$dEu~Yyr|FO74-05J%Az2SPL4(X_*jxQyliCEvfVL~lF1 zzMPIa*?KGOCoesQe>;hD{$p51?^elf?ci!{LfWr6Uybi(z(Ut0U|VT^9OM+t+ERcr zVRQR8B%})i(IzU|uDQ4_W8Hy#`n%-PQL*A$5GL!fi(u~4s9uOv%-*(2$Cwb1Z0Mmv z+fQM{(G2pI*U#{~m%{(##C_y-daS9v>|xRGf#{r&x)F?_`<&mPy_YwbBdYi?L07=`bT3O;@Z<=Q&%I??inVzAGEC#jH# z`2B>#82gW#P6>DXM|ky-c}zeDV#95hB9{+w6+cl(CX^yEdke}(4$RLHq673TQ*K;z zb|NV2_v^EZ>6a0D?9+e0PX6Ent5WVcdp#JBGx^nFP+aXjB|^kZher^y+bfx+5cV4Gej*U&1Z@MVrQdI4 zMwPawZBAefKJTi{$VyDgm*IWruUWH2(>AL_%W>{?Qr6 zW@m*d80!SLGp$xABzboD&M;9*ihey+TeJ}?L?r7XN>4a`TZYqRx zp_ZIJ5uI*z(KHPk(GbdrDL?tIC&QzvSC77zdKN}xv5aq>vcTn3%eN+Sjekyn#u{RW zh~6l#(Ole)-)ukOJj9t7^+A}9e-;!9;DV=6Hn2M0`Z6yQRFoyhk|#WR}jeqPS28KigTtR$sGyu@y_LE79LX zpUIqUc2f%B<^?8{*T6#35u!$N8MtJ93Hk-mhaA;BR=rktR2=2lpxU>9(vsotM6M>f z9I~TWDc&a{U;&Y!`TX*A2bIzE#Qq6l(o0}#cX@i`?5=p28jaLMT$bSKUzEewneQC*wHAd-j$mRTmHAXy{Ro(~^afY-tJ!=lDixksVzn5Dz4mvw ztD=UF_xih13d_^;7PJjqvJ9@_?6x9ah%u0Kds^V?{i=0J&O-wD55&G-h?qND+oKp5 z789=;LXa#O>WKzxG~fQ9(_B4)slZwS3=x@IRM;x|ASqaUs zb@}^bLP9R)S!>88JkvXVdb5N_f>m@>v?elYB9r8zT}Fe1 zl?)Cj_pO|Q(z1O6J;hZMy~byyDYhE-E1?Qj-+_yhi-$uPs*MQgrHgz)5K$A-o6$+{u8j3PBvb#<)JAuK>sdLjqj#e6a_6=0q;(o^_ zLuFNFH^Y_8pHKN%9Y{fpIRc@l5>Nl;PybfJHc&dQg*lGPjJP7Xq7l6SU^S=Y7C;70d;w3zk}|aGV~&^~<=~jMY2AAlfK6 zV^l~@M~MFtU-e&fs)JlDTio9jtPKHX65C8ES#0Y1bYV@!j?cpuZcIumq;?y|wIP?t zySl*fp#aWxG->)4#~XFua(sjR4k#8__xiYBgPJEg>fJHcpSI=smeDGjzz%6zv=NJl z_-4zl7M)3Q;99g&Hs36{`+xG{iX*x4^?5TDj7kPfN5wSwY4%=8hF8=4H@PQcUyXn8 z*9cx9|+n5SP>t4)m^VZ2)3|CCB@YJpI#YyJeVEgUD}GPK7i zRNTcA#+cE;By-$xRK4Pbd;(lM4(JHaOL0P3DgM!Fm~*ZgTlGb0b$O6c+q4pyA%wSN zg9{QAMuOqE{eh3YxUxh5g7lw-#PlL@>s$N8^9sHkEXK4Cwj8gv)bLL_+^xpj<5$Ky zpdSPp>p=Wf_7eJ2(A{_K+nsHWgSQw%JG9rP@N4SHbEQ{LDOq{sC3M+XE+~?B9aziB zue!!%sMa19!`LYp(Le1Z#)X}Ncxgwx4yK6=2#zpnS82QaX1Z6;7zT8A=zz^ENq@VG zj&*eMIAUk>{5=d)dNUlc=dxMgc*~&UIh>(JVTV_;B9zv(V;5Y0TG-{7$Fm*g*1p_N zM!dIM4D2E24>VV0kHXHjPQRoR7`aON8=SjondphLM}^}W3aBDdS& zNcz}czIZK?;~zNE<5Xs&-EFv32%Gr0cYVkkM`_oyZQg!KKF4VWT_>IAW*37p^5Bgt zkqAe_Mpj(Ng0q>}+YmZ&0u(g zLyp<&*`iPx@y(53+r3QRm+mv*Out@c&ZctmoSqvRfWzA0Lcjuwou zJ5?LJ?hA*cIk9IiwTvGm93J4GX74MN?NXhMw$c@@maM*~xWZs&fnh7KOiwrK-{fcI z9`+P}!93$)%IpYfv`%gwK7n{AC*f}iWJ`l$7yriw;=Fvl#t5R--sY$;tuRG89UJDO z6#2LA2O}GpteHdVHoMmyBJz_0v0SRhNMuWeN0+`T|I)rU0w)-Z0oO4(;mVFE67gq1 zaBd2Ddg_l(I+mS?FXpwY*1aGwA1qFF^a{adlwpoqj9le{X;=R-UWJ$B5 zH4smYIs5%>pTGoGNE+4~(-sN2Fdg8OUjY7TOg05gX^<0;rU(&hW)w zk4Ys4+>4vUq$#&Q-!|<mR!I@Jbduxm0FzpN<`~$r9n~Ry(D3@k+4B zGLQ|e+J{*j6+1R`$r_^L9&sb+N&%87yzw@;PN5%@%1LSO!q%~p+hARKIm@sxq}p#b zQ8MRejD1m9>33m|yF1}yagsletzs0{d*5h+{wsB|dti{MCj^v(WGpVEGPKz}@i&*Q zx+lt=V=JSPGfS|{h1Odk@pbM|fvloS+!JB%Z3d+SGAI}>H~y`n3pb(bO%O@y5RFaL zkBV?}o9>ZfHNwI)Ve$mwO4vW+DGN>XcWwRY*PfU^<9!6xF&Xpxv}^kTX1^7KHPWyk%OG7=q|7sAx{7VyYHW zJmr_s0J?!|Lih&xSa?fomr9$O4jb^;MdL?DBs`6rx>$IECHOmai>)$p6w|S1E+YGr z#Z`IGdT5yl;A6HZ*@^#q;D3t9^1*%HDXPq#{TOQ8t*P%FWbmM4Fi71|quIOrBeoy9 zPV)aV1Ec5#ST9Hp5e|AbQFvY+)|&4w9$fZpG&f0|zp{+>VKx4y$G^&GlgAK{vQ$$*^4X9hTSX%?iLpnX zDZYpRR?V$(v%LyuRmmEwkSsqU%1eq}I6wILpgvW}aZ z34*gSMT=4B!5Q8Lmk%x5qwUd^lVhPa?~(Es(G z=>INorHRrB!!1ECwIw3h7#soJyn>wz-u**)rJd4Z!UqrD$#u>9L=t`NLLIXwtq9t5 zCiedIMLqOG17Q&kn$zmRu*#^@$GIy*)Za`r#~w%mV)drs>^07~Yi`vGwE4cZ^TCr+ zJ>j~)p-+A1xuecp5ktL+vTtIFlI0si;f|u`ryLp_s~6?-cJ_z{)gsG@WSsD&sj%Oo zv;(H-MAy&8P7hiP%PrgvOpQ+%XEE<+YbN_iX4nzOQfE#G{K+n5!ejl5J#$<4x>o6zz=aeAqSU3&~piH|Ke< zB<#0QBoX+$f8s+4qz6+O2RG2ffTC*c;edO>0j_xY`=Q?-=XuKNUw~eWknQb%Z%V_O zEsw-!QEWCAA%;ZWQoo7+EqT2k)7Ir%+Jfj_&hbPu?g?~iElecjarQ9o^n_fF8)RRH zgkl*<2-v!LDFyW&KD^V{Q7+-Sg4wK%)l&U<_gpiPB7`OT;hHBpLFl4S__9|A(xEQ|9zacSOTMjz%LN?y;r}zY@w@J2m#Q23oy~-uTd>T$e&l%#cP3| zmWa@Ct^WPA)E_2t>bve)P<1@mX@=5yH{bEf|L(pbZ_)7L?Y|qT|6Si$c4&zJ@NML_ zx-Ah*;EP-1$W<`$8+2yX&kb2HS(kRY+6G>N7qa`N5~_B3k>votNNm0MI_n7iHDXuQ zE&4!IYU02HrI0TZbg&x!eD#ePOFIeEG|i!uU*YD7Nux_S9k*hal0A0o+|wv~3;#tuq-#HB@mhGNsZgvo z%ZMAwH=Z(n(~Qr6(B;(_*7-dZ3p?~Xb!6rEy(kY;ltT8I#Y@ua_7jn zjaS7bA}!C3VxX2iH!FB+>R{9f4V3>n>y-qdE+P?xrrHJ#1OD8PJYF60aXjhq=vhb*(Mxse z$pQFB;my69nZZ+u*}uUO9LkvSbbUjtin1iP5#{#eW3p2UtJsI94MDU6H;8^C>yS|5 z*5{3^o9TWc{Ir(U$r2G&rUuloeT8@Wt$_)#SH97t%bp3XolINIE4orp`uXa?=qvHy zo?{P6U_3Sy;p)+26kx?-2QeHF=}PwXw+KmR=&W@=#X-4I8g>FE4|hh5?BHue+%GZ0 zr?2ILUfZ;CGyan&t-Z(HMcu14*^%YI2=P5?0S2xy9d}*sv_>as(AgayzckK0qC(97 z$3PmkPxoE^($igl^wPs5GitS@73#~PClOrs@M=6z)$iEI--_#jBO)I}$JSuakmuO8 zsu1bW#>6A%yOzi9c=F4n4LFI0**oF5{@gF?pYnk2Gyw%S&{Ku`gwHj9a`FU2 zzgrelV3{^fRzb=pbBMOppF!yYoQu<50VJb}Q8x_E;F9znRnisXEGP4;)DEbf$m_JR?~0(_5E^OJsaZArt@!v^3JcCISEk1 zRbd*{Y3@=P+kg^1q*S*2pZQ|0VPd1=_mw|!=pTO_m5^052bq=?ofNWvbk_CM)=NFk zsj<5%61xNq~nSK!ves!BqBH*p$@cA|2E^-IzO(^zwrua6{xIIjjV!sTy^}leK0PSxD92q4N z_Y_Z829E?!u#=YX?*=Q~MV&B&rvz%RgR(R^R3SpvI@B@7T{Ix{t65k0rvhcXQ81W) zB$iFiYb4UE1Ls#J<8`F0jk^=+DQ5?={}OwDivwtvRNlI`RCVPU0Wp3a`zd7c6N35pX&qx`Z5NjY7`-uXg=hWv*Qs1VHP z&8qQFBA*rXupHK}@3+Nw3*%AegVQ~OXS^#LcfGHC#U*|w6MmI?aIF>kFrKb#6XQSr zolZ`QU**)E_^ZPBQe2Y$=w6K5XzYTT`cCR@`gn!6@1dFXTt%sQJ*JLy^!p@MOgy|56%;Li@X+Ly`U@_M$_gJlf@i{7ZR~w z=0Qa~u3vTlWtI{{dj?r8pyoU6*bTZe4$YbqTJYG`I)T8%<63rAXrsmA%DpQG(B&N;$a>{Wy{W!T;Cv zzis%oK|tqb;(3esbW7sm_1u!ZA??d`@r%YA*U&y3VHe>02?A6eIx3i^m*{l)LE*^I zNB2Fm;f@45RSjUQQNK`V^73!XCIKyK3tk#q*WGXEOtoYR#}kX@msne%6`xvWv;Mf^*YFEl0#eQd@cX|lv!@*Rz5?&;F3rvv@ zBm7e1RCwES!xs-Aigzs8>r}PMq!{KoO`Xpp`N3dI_T5&0huNUsrF z{UvV>Icnn^!$a*pPy(}zqGWX8eV#+pA*faUg1JM1qR9Zbf(vE(A(jyOQBu@Pm1Q;* z`8tQphSA>e*h${Iz?J?$W?)ctO!@DX8S*{JiF7_84OxODfSkk|C7n_IfZ5LufYdxQ z-;h$%+F#(JXyt_Fw*T&6J<3}=&=9|(MF{&vEc|9khQM_5w5m=;$u+Vt{A+y_z7Eg` z$6BkR|8KKD#Q1PEj$4Wj+{w8;$p&mN1*e~$GpSMIP2gN9QsuaYA9BRV={^xy@cIN; zVurHnx2mIuB4fXoaDTgm>0B8W&7~fCeZw`nu%%{2Nh&VM7BxbQmiRF=v1pwlB8-&^6S<~X%m*N|fDuxNyg`+uIwylvP8OGzSu zV8k=W#yWk`619joLJE6ffW@PpxYkAS8yk*_bth}Ed z!R!2aVv>B>WV3#|OmV{w2Y8zs8Si1rmPH{ie5Bb zPfalz0aau2Q()Ud1Lr$FG&mEc3)4vZ;f1ViZBa=?9_x_{b-t+loWvejo(ymQ^Qe`g z>5`jLF}$MW*J0O!fD5lHG^XDwTQj8by4Y)5QX7K$G7|PCt=wJBb8t~Ym0{kGUvk#F z1qZsBq#Gf=gQOXd_l&(d>fDCg4!9tje_;+w>KHO=4 zd2aD*6!&lF$!L&Iza1h&+>ecYJWMJw=Chs>EWZm%{>bQA&Kr1QszHtH@#n_<(TVk0Dr%kodKQyTOBl#(h!qdp zZ!bkis5?HFJHbUA<2U^~ix)1pb7^o7*emwBPkUp~0Eb1@zqjgN`(^p(Vt;>3+4u2E zAPCkyZ?;Xd`O(P*$$g|AIjO2+R?^*OnTh<5FqUG+36hTLf%#up*k@weHxexHz?#!Z z>OL;yUDA(i=a(Owl~q>Ce958^5y}|*x1O{*_U|n9dl(O27)>^>g)Ku14nbl;BeMXX z0wFW_cSHYSY@yI`lFuazoRhotyU31`l2a)--L^Y|tC&&)c3lUD+$mcNWxFiNf~l@c z#>|1Ksym@Ie4Y6?R1@9me$%78kXLR04!*NAV#2N8RiA|Dj^KNJ(9g1Qt(K_p6Z`Aa znvm(PV;k3I-T1>}KW{y-_vhyoIPtnUKHGh#PYhY|hQ5LWtq!ZF$LsBm@HczE@Zlrh zU%jePkyCTQ@NTWIT$o}Xy+fCL4Sj5i$WtTVP4l(oH^+ghKnz%kG3^@37VHIp#~gh> z)v?ShrFSp<^O4!|(eXm>X z@sO;x;N@NOXSRtEWtk1*MjtVm)z%1dlv$M^2`4M^uG+nK81C|Ed%yD8TV6dK+zD$R zuKx6&gNLiIvlkh6*TTh`qxDmr+tt{=c6K1|Yj z$|^$abekG4dyN0(w#Rj_!N4>QmOx$7lSPJ@S*_F<0nwD$EeJ#(UbaVkLz;_;WS z=wx@o7iYp(v8MAMRc);sm0G~%YdA}Hj+BPWC#8wObLxBE%_ab~3#2@vyDwAXnowc0 zqd3NVPn|37UZPfgqTd^!*6Q`LQMsq@?AElPs3Dnmhv=JF_(@ECit>VnR zpF)h1K!9SzPKLbV>ua`jmR?M}MnJn!wK5f4O5L)?-FGr_;cv%Ae=BIpUP9MagFi<5 zSQ-J=~-f`V&erLNI$`;=d(lViZ9999;f;jvV z$$CX<1}Y9z4@{e7Z9@JW5Hv z#$T)xV>9h6lVJR047VCQ`{dh$H!vhF6?9xWy`h=p3~74AmRcS6%OYR&hknBd_5(aJ z`i4g}O559aTH*afd<%0>$=t$@IN?4j>pM^U-BCu`?>_M)Y(FG(xmuuC`h}05CmWW( zS|ivCB~v7pMjO2%0Z zxB3Tqx84L+!~o_1)Nj9Sw^2W^C`*(kpfTGPb*h-=z!KKkwc#(Wc1rRDdBjbBE37aKFg3r*h8rzWsEyO@nrn#~ML z1i!tD-H9W9)T)XupLd1r%n_eIY%fYg&I8OrRLB;`W;*wgI$$D|;BI*#YI2*V!lnSQ{78*#N(_kT2x7A3jBO%xfCd$ywI*qaY2?||Xloq%agG=M zuGaQ9XQ@P2QqS9^S%{m%PR7-Xu2&X1uS(Y&C*%}t8~f?luxy{}&J_x@yJ!oR=!4iq zfhig3p?D|%$^}m$)0Y&FEW%JrT=^H#_a(LD3m!_iCHxIhAdGP@(V~0qb?*_Yv+S#c z`9Tzc)A2)ply@C?7CFLtpDMPjTCMI2o@DnR#D~50-Ne6J>~mx~7HH|kk3IxD>mx-h_9aeYGTAM9&75`pEZHFw&8>$sluLo1^k4n$s)#;)#sr1->W@f`?47qT8%;Z#^Ap!=E zhoO1hE;?6T3#J=db&nT$L3CE-KlmAJ{KeEL8Imv5(xSnCs+O7?WTigcENE|PWpxlq z&Ylt&ebHl}vo~noxH}0?BryF4=`ua~m13F5z&;VpyD#Ia=U3SKY$l<1USWh|ji*xN1m4RL&7YQBl zjn{Hd&LUA~6FvQBRL@U&dir5F(!79FgH!WS6f3TMt=%;e1^YZt<25s|Qoxdh5`9eJ zNyPc0!PM{B^Op8o^zBu;PVm|2F1BkJC=9nTktBFA#p6c?Rf(ANw_?HG+4ocH7S0rZHJ-Dx??ZgD9+%M z>WJH7wmY#v$6W*oHZ|lbmgCNgxWvY>>7ID`Ff4xqyM)3Iw6sf6Y+$;Ht7Ta!vx!cw z+btuwTnGs2d~i(d$FRwB{jX3vc|$agBR4IRO~C@6d-~lk{N4Rd^i4ub1CM9ONW?+0 z+KwHy;ODin-iD`D^rn(jge6W~{JCj=g0&N1w3rx@LTmJwx+qsjJ0}!r;9)Mz+GsWA z(MtTnrjMW;PLhK7x$sxkR`47DqlLpT50=Lj|38J75ASU(>cM52u~y@DCOe zcOaiXOTs^tpiFpe{*58ekMrwY&zH?BDGlyA{Ee!+!F^S(3#vsK?a z#(1LwjCbOwBVy(n)cfMr2cM*s-^ck8$iPwb+X#lwS51*@`ZxzPgqt7mfPzN9?H6C6 zQ8JwL#_b*nG(u@rbh)flFr~4xRZZ0*raQr=@I`vE#;EtM9ijaMkgmN(KV6T8h@0rc zXp2uYbzDf~x4xKiQq-~t47;TVT`!m{=={Z)GqqAfzsXe5?eV`==iK}URn}g!Wf48^ zL-uIig1~LTd`eY(c9$A*={g5roka&4rB~<#cqf-!4*s@vX`PkH_Bx~05 zM4n$au0MQM*id&LuKwIYFV?wyYifFIJUv_qreUe8U5{Kd0vau^11?-0Q#(A^hag&! z4uChfN>4M|o-XBd8Yn)c%My!YDdBpz{IR9->6Ys%qnN$S#B&Yf^|HQHFkKT4tk>gh zcRyEjj{kQ6VHJ#iS=d6laybMjAQjTljZMtv;lf!YmiVjhTw2nqK&~0 zNmHYC{^cab;8QdUATg2Np>q?Ju4Bl$(4*JZhTwi)heBub#D>Y1JXq_Ehjoi}H0OU? z`vt=o`dBk%w;9s${O-Zse?M=p?6#IhuX&++{k~sii}-1W^`+SYJ5*_72=uB&R<>QC z8hFCuAWwgeN$W##K9aI#V?{uxTu~uFN{DH5*u8_H%k}rEmMh}yPXeJ);D2yK^w5AE zM1hs+5_L`YDP`;E5NxNDfy%8vYrBeeN>>4(wPF=pOWE4frf8Ymm^6-tVpiW^%Bk*f z3!F)QLpkZ;J|g8$P@1bGr=8l5)7<#u;)ThK%7h{w${Nd`lW-ACd72-Yo=Tq)?XuX#g5R!uPmh)kbCWwu4EVxJI;eKM%!tbHCnKmLQ_~VVk z^QOF`Uu#t7W12&`E*UO$zshSo>16nB^n9$amx6KzAW|9uP1k&pYxmTXEf>@|)n|56 zwkh`0n=T-)MaxsT`^IN(s@12W(7eTu3T7DHsUCFBA|Z5;8IAYugpAb`1oTyVQ!WiD z#u(FQl)pQOWa$ZYQg-+h<46JA`J`5Wzx)S8G}OLZ zH^LxyvG6Z%V0V(rxLy*LB{C-m*mAl25QMn?d|1a238eE&KdGvm3%)vH&V@95uO?VLgwb+fNp+rlpv9w7`yB~OXfY&lP#}92kw5U z!fdpc0$7GVhMI=(ZNc@aQRi)4b1(Q4wuczVIXr(J#ZP*t@-eQ(kIy^IM3A5)Pp0`_ zU{x|B(c6$_Qe4yIV&u<;p}N5RN!nNfVzrDt${QFgcI7(s!4@R~|&Sijw^}=()eXZ&lGk#BhZ1fOnL{pP8Jkfu%*841+U3DPRw#UT&m~u zP>?YwZ3!y)X)ZmqS&JZzL7MK0j|w7+G_UsR%S#J&mw5GuNA>5cSx>T`u9%itA=dUX ze4HOLM?SJkx(3K$yf0U}wudXHWV-49l_0AM?Ovm%C4_yD49L3*cf> zrMFSR^Q>cq2iG9xJ43D~tW^ zum?eh0tej;RhYs`ejh(e-2(dIdiG;S$`pIuby#hGnld8So%kjA&6Y7bBan`Ot9y|r zSj+2LmuehmYYSvIVgyj>o#gv9JJcU)U0lERp?c%?zj|wukaWm{xJ`ad>T>r?wJN z_B-?cHOdfSz$E51$1sn}&92gjH#aq7Qsu*!PX3mp@PF2DI$haY+E)tCm~alG4KgMu zHY$&rlIPM--0-3;XYSloD<%0+JJpwrOCK7Y8Gu(kY8*4ru(Fe8HjXCxh@w|xcVrFf zCh$cN`6M1C2E{-9DPphBv?Dz5LcUOE-Ie zAzj%qt^jK)`pu$KJpb(92fCmc6+o~nj%Y6iP;FdoTbhCAMc)GD?ysPqj$rJsFrBLd zBHaZbF79!1l)mP)jROyI6O%!gjlL`w!1q`WvR%gLKwv5;l0&1Ol8Qx);ex$CK*ol?pGCfndxP*Ji^_m-0sA(w zS~BJ#I~!c+1^tl@r#?8c?Zso9+Lg@X;RbySOMS4A4;>=b{SZ}jGVSD8wu`~xLmNfg zEvph^34gA&i2QPgAtZf=ACrqkHLz-Rfi99ECunQYWGAxiKEA!s($%X(hli&l8N0wo z_aUf0YvF7Wdu)^zWA}j|f{p%qLE{3gGE};h)e%-;vO^5n8;nBFCB5&b3&@~)Lr}uh zr_lIu!qoung@{Q_7~DRy2XZ*iUbKCibP8=y2| z!$czvW6@1CYuV@SXWXhE+lm4ixAukq*%leUy~>Shw_9J7Ke}3)k92(u|M8TTcqtcG zRGH~}*mMKjot@mkYSJ2=~Qn5aU5rg3$=di7RU-ycTsHuw+i>W=+<4Ef*_YOZnHTm=vJ$@Iq1?-F`g zHJumRU3=z#{n>x$_P(Gn)z)>Vi+_c$`14=ABWiI570u}|=^^y02WgD|kYBR*Vhqlp z8r}trj)sIzs*uk50QQ|gM}<~}BVml=%LPt6ouGz{Mc%BtvR<@5?g2D}$a{9LEesCt zXEy$VAWD|@qb zcP=ENTEE>47kmJ-y60!`Nnig^{sxmW%>3Q-8)cxeq>5MK5AMU9RyCJM2tQ4 ztE6H%PPlC~L`n(_m-NQCSjP5iU$lZUS&SopKh>?(9acMUzVE7=hIZEZa2@Axe<-9g zzt(16SuEZbY3ChdZaf2%_rt0$1G6-E*>=7<8Z(<%DTwIKVzq4mT&jc$A$-jZO3m#w&cTh#mK$Y&j{ygQWD3EL8Th3j~R(a|d0M z1PAmILT-?#M!Z*;SctT{mZ%%bCFvh|2N0JYebEw$!ht{)kaN#}7oaa&k6XY4atbs>09NNw1a# zfeAWU@nqYrb8i#IF1;0fnUAT^PXup=LBk?)c&7mOgNG*37jE*XAP_AT){-V@4L*-a z6;qIN{nz}XL(^DmM#mWNioY<-_dEn*JSOCy%tvh6p7d3hjCv(%;naBDq*ve{c-E{E zX?+-}QFxzY*NPD1WovPD`3dB=A-TZ6jX}{Pf6n9}lS5)E7l(B5$i^My^xA<1Q{8lf z*n{4GbZg+_MXNI8z9lfiF!bp+88G^4YorFNwTB0p4tw}eoiPNJ5j-E1w(>+Ut~Gl` zaz32d{~=<>!UNR3p&GgxbX@kA^gLM^=5gGiO(V94_YGaT5!+nuY9cNQHvUbPaO3JJ zIgVL97b4UL)-u9GUnx}^C6NId&9HK@x zEDS2sY41IQAz9s3yM}C-eP6Tm8G}+nFG<}yuMw7%VP+>|Cu5U=DEA_~_>dWp3zsZW z$H{S3`Xzhu5*6 z;pZnyN9+5^JL~#47wQcSO?|!w_UmX+&bfP1B;p1pge&pftkP*Tj=QbuIk(d1cWLxT z7WVX*Z34m}t7pQ<(v0XJS5>wu)vqV6{p-H2V?2>3pPJTNjZ%d7+OKug|B#~RJ?np! zv0P>(grv;xnd(#zA#5J+dc&fEK~F9FLWt>C$`$+1S?vN5&1S>LZBKEj-VZxGtIkC~ zbzE(#4mFZ~LCpldNwIUCA`{UB=}3#x%p}K>P~qUQcVR0iTqu6~gM`-oYElasBsr<1 zIQg*^mMivY(M+>>K*wEpH}lqKEAy?%S*$vEyYBkw%ipzokweCeb6AE5k0#i3o8XYz zhOcd2?M%=eupRno3tX4YMZ+vXs6Ez0X;2zek$3rM&-c&wIMm{8J)JibZBY01wL#h$ zj|-RZ`Qz797@`l`c^D7l>rW*9|A>pyIP4o|f@AOzjRczDaoOozLuqU&@us8~_}?dx z0#SvD^@*=U9NIq0p=01Q;gjOPtD>79;Lxa;c8lRDL&OxHPH3Qz^f&z#ovTEV4IA{! z3emD&hzl7wiG}Aw34^BlGGs@~%IGFaj2WRx;`z4E)lMeVp4K?-X=M_{o5D#}3h9Zo z>U6nK8_r544zi7aY@F`iRH{E8uyL4rG6e=Z1msnQO_8MjfQWfh#y1K4j578OV}6-@ zhpu)XteSopHb~#}mJlEG*ptCGdKN2W(i4>YFj)I>J27h7 zP0bdL1j}M4Fkc#bSxULVm;c}0=P-6bkYZ4*))-ZBYjG?4se)qC(;7HQ3zYHr1A}8_ zecEi_GZ{mC1d;fbXxM33ql8#@nxW@-Or+0kJgq+__^7()h#^QUwMfDl88?K zd%~1+!e8-9?c?*mPxNnkLIYuKk=pn!vfzjsUOMwmfx};47lQ-zChA`6#KeaZ1=5rS zqXH|n;7OD-urJF|EQoDjm-Dr!RL@_k3HPXP+2R$Ro;*$iR>5`~K|{n$v)+N1nHvH< zgW>41fbN){;DcQ?Jlnj#01vi$HI&(PZxclCPOmCuJEccz8~2V)R3Vwgd{D=j2ew@@ z_SZXuGNUI-BL{CcnzG->DYr=Jz zEk|$vVL1Mil$sy?isz#=OT!SI^=a^@81BAT!|wTZJ(0|@L+$!3*zeUE?cBVYatU_5 zH&x#u5u3%+rmQntVSmmd%U5rXyLTrGuFbqk#hL8mrQ^pORMs~Y*ogZKkiq_9Ly4P>A zQuA2yr9+x1O2gR_Kg%_q@P@Jd7B|rJ_ZC^UPaO)3d_<63z!`2T6E|aaX{thG+^d+V z5B}eJ)RfAJelzZmD9hxn$mN3gb}BA*SnEPvP{Tcr5;`pPnOnB2F$0o|J9~o69DDN6 z$X1)Yu*!G;Sl#dV$@3bKlBnlPc`dc&c61fqiCrM7M%XN^V?s+*WkdO6K>N(uyJLs4 zngcXC-mx8)Wzo?UU9%3Zb$ypqqE|_oaATUfaJ8m}F7=wph2Dr$W?SL}O5L+p@7bN& zu{|pqowBSgRl+5We2#P+?u&2Jm(4@XwXU1kT*s#nnu4S5d^x917BbH)OLi&5BuuI+ zd(Q`4Lw9Jzwwxs8#^%#+NK>|c)WW$qw~+U|`L&0W(|l}~jgy4Mr0#;|p|s4ftNZIx zQ%f=jk|H~0_HTTNL(K#2^})Pa%D}jLFuaqjqUbvQgh+W0fubxmZQ;4H!JBWhhy}J^ zrFL>>)eCVUP^K1X)g3SXJ|db-_ay~R$$Y61M;^xgk8g9}ad$uy)mcz{olk1C4Jpt= zu`Tx6e%^G5{k^VjyrLb$2AfS9f2u47PD%d6B0|K)vx0oeerP{T9F2IuIonP`&!sv= zvmx(2g++M$Z_Pp~CnVy;$8EVTCSc!0XcFr#^d$MTL-L()IU@Z~R1YqP!E{}0v>$R~ z|0?^}qn^i;M*n|2y=6d@@AExO$_mo3NSAaY-L-^DgLJ1zN_TflOSgn{cY`z{-Q6s? zG(5MT@9+P--Q72P-*e5(IdiT#2BuVWJ&?E6^Rq}9p<__z2@4@u_Slci{gm7RuI+ff z%<=RS1IsMBHhy@GkIS8kl39HmY`wcjLp1Q%s+&L1dLILXbPq*Xoyb*JMo4l9HV{gm zMo7)IO^Bq$CfV>c3$iDAkQG;Y-HoU5`L$idI{Ai$39hmYNSlLD6xMMjtlq}iRo!`ZamDUpFga>FW#S%h1?+dMs2|3}Vr_bk zN2L*TCB!)qg;md~4eB9{f|B!Wbu+mWg*mlFtsw^{L0hwES7)VJ=n)CoIQzbj=S>CBVX;Co@v_Yl8~cmU1z9%-xLh~G3Rde z?re}8;U4k;YsbB{tLxNBxwKF`yEqQ)`9?&R@7w9Klp`u;Q19D5!|3kdfe#I&pbPZTtMMv zQGPL;6QoZugAyW{+T1jcYi;cLJkSGmiab~B1?loadj%UgA{IO804c$q;Hl-jF`7z~ zfasu*uJNQB#AEB$LxZjX^avM7DbtDQwHA7?tGHGrf8KRZV@|HB919m4-`Mw{sU0;+;ks)^u+UulEpZBTCB!cckzDB`n^0Be` zTwB%HhXAy<6R#@bkh|Q%5J?2)h|P{8ILBo9bPNaLFt~_fIE#~MKpav8?c(I^Q=Cxv zGHiNe-*DH%sjARtoR~XxLiF@(HsRpyrux{A zn;$z(FR=7^ojP*#^Ha-XzPU)49PVxc;m6LocvhgRRd`y>i6!fOzbba;XMu)@>Kxj0 zuw{`NbkeCxeuF7KI70;-$M&WkI_OKe^Aeo>Ui6&!;0aJA>&y~{0+gy_hv^ArVS3+B zsh_Mt1YE)Um?M>6yA9)#%B(t--x~3lou$J~N`1CUEC78b7J1snrhlw+UK(DLoa7Rc z3%axZe8fhgeAyI60Sb`g`9XMv@DrcZaXXfnTnZL*n!DNJ%L1N)*B7ZUkST#9YNxTF zt_*AJlZ=~t9?^=pkRIE8@B|UjV3*-;R5?(n-60}%V+mNj?94;C=Q7pEmH+zOBmEKa z;&R)J3EuS;-V>-Lm_a~k}q_-sN(*o~cR)3nWD~kke z)OqJZpzGYn+~xV2m5o~i&X21ie{tqQ)G48G1wUeUj4R+mxX|l@rl*chjF#;LB#s

    y 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

    )hkWjfdir(1AZjo$AcPFvPk6w;kMYENq zJDBNDb)))cVn#aWurIwy>gUp=?3u>qU%uT2W7rBV4SFJCvk26zSZ6Q6icXmJTIG0^ zy>weYJ0+2(2cDvgoxa)mMK7xlKXF4m_u9jYm0-ed)ph+rNo2wS-J@OTrwTHWm=xv5 zxeFm=MQ(C~2@UH@(Wj2kDsj_Xp)nWRGMbhYD2tuIY-L#V3pQj5tWzcWO6Mm z#Z05wpl_{gdUYyYoNF0#B!tAA#1jni>ZKjgRZOkmw`#U{`{&aHq4a%;!Gnx`ukVFj zXK1gtr*!Bnk-(|=V?erIk_-waG3`fb9JOE89RaocA`_u8_A zKlJv|+d-x`VR`t$VQ@tGwL&P)RX~d_@w!jB?$% z3)^+1|0`NsX+_+n0yWNpN;1sc9@dPvvw{MoDbd7Dc$y{BsCtiGJu;7;a2PeIqFq<- z-hijtt}Xa?;0c_<07KG9W)Ny`J0(@o*Lyep%Qy1aAk=mrW+EjThU&1o>!{|`2D-YR zo*fe!n?$1eyIy&V9LWC_C;?N6NPC5x1x5m2g!>8XsKYsr$LAaN#jh_$+}c72A=gKi zKm7AvC(ilU(r9OJSG@0Zi?S^GNX}Scp(`n$-Ag`K3A>n5oI0w1NyZDd=+g5{+rwV< zy5wK=gqi?3On=-wRiQ}9c12G7=;$|v<$az*=DCPbO#bYWKK45DdoJ`#MsN6^FuTzR zR-(DwGX$xr`up|^srKeFB!5g_r^!)35Uz%S(QTY0XoqS%{>IVp`ZFx%8ux6U&M4K3;jRNt=%YhTNEMY0WCfx;F$7WWnl8;@TdaYR)6I!cBSDR*A0<~qu znz~tZtj#=>%zqKDpuE3akdwW-JurgZx8ARAKWc5&4haNpNapNL#ltbvPOw+6i^O%~)U4x^{XBxsEi0WL1j5z6N4)w2Q)FR+ zGb-RnlTQ}d(>Mt&*4V3_MBH^OI=Rof4?1_Nh@-s>ac!Q$W8i4jSZQ8}` zLGhy)94$c#;Jux-UnYTv%eOR9C%w-U^){=L?!zGWZ>CKWv0$x9bcpTKAL5% z?MyN2k6XND=Fst0*B{^e8MBYIl;t-`9y_UVB5EStD<1unilUfpG)}>qj%)Ry7njQE-K_sBq?)Ctx3Rf1^2hO68|w@Uck;HvWSTiJz_%_G*Sp}u z}{`-Uk<)X8q)x`u14PzB(6eywX487-!DMb9sM>04K|4^%Oj8 z_ZAC~6VOw7dSvToP`0_X{2AB^G`CnSCeJkSc@CWUIO`|shVJTH?L#_2EP?Dfd1*fQ zSo*UF+YJsI=5TkR1*i~%yPwQ0b}t7VnOS}Qv|JnB(w@GZ_}x)?9?a$w;kxD>)D>%2 z_#{pq!9|;rFnfX-GREfJelAQBMP6r{jcPlDisiKqX| zCWLDuO58uYTb9!D0_PW~MEFzk+kK+!Hh66z+Zi6XpWR1eM@TZMia#=?j@X;L|2B=A z&JI3aCCu7*w(B%KxLk@Y-5nrIS=W2sa$aF}1QapZzCGEvXnT5KhMRoG3G`~GHe7wa zo;_Nzb=qdc@4CFnAs92xNIG9~Wp)aleLu;qf_EEeUW`!!PfLKNH2+A|&e;8YB!5qa zl)uDhsY3Y+@s6)>OF9?g`$&}cdqSHRioS``R@vt1=h--1`5+@R$R{Au6PW_pt0RYd z=GM*Tq9=rN4Z9+v1rot9vC);wrJ*%@3!1jqa*Z?Q1Kr3qojfX={&6M2tiAz4i&w+< zL+-UBR#v}Snd@4Vxt=wdmur#30W0_}XeOXKU4eBuLr(j z{1p*95w(bO1*wcpxD~VQ=2SiHz2UwUx<{|9-zH^mS4G_F4IJI5NMx~>eG&ET=$g61 z)M;FSl5f@Dw5dF35uxpD%sw?%fzs*R%K_6$XVVHt8SD6l?&oKgHixr+%F}f*QsQ6M zqZhGE7|1>6&n){s54bV|&+}M}6fg|>+EYL1-C2F;rPc$Kpc1+^9?RX2kz0qZV$}Eh z7Avs#VsCxba$lA(?zI#rory<+eO|rh5i?B_Jt{YFAEL;TieO@UM8xL|tJczg4i*z- zli-ZL_Xhs$JrFd5eCdtk1CN$mE?Mtu;yAUm?9fB^$?IN7P8rsJ@`^c2MK)2|Ud!Ab z)M>#rG1|q#-lMx~aiPKS?PEGTJPYdvpTwf92#Q#H4IC+&-|j0vK%Gt223IqA(L*f> zQLi@f$n_f7TwX?3{aIug83xIOgr09zncwC$w|TzUj3hI_EvBBK7Er}Re$pYR82hD@a@(^<-h1Q9 zpWOz`e(_W_ZN#x!%w3@+bJ)N*rrUBoe=Y$&nHMU^i z8q1t$zFzN?I%UIpU({xtVEg5w>om-qX^%mbFB4amS-U}wMjU(`hUf(&T@n*NuD*gT z@KmUQLe}#nbd?)MadcC67?{Y-AQP~?0(?q1$FEeO)O|T#&4r$ZJ--^YSX=e@tn=G^ zi6!t??=>>#Natyh8DAS1Fe4|p(;v+zFBsPwD7#MckC+qhYU$(8NHjUbk?1J=kOIrk zwH^`VQ1;J9zg@mlk+5kL>dcM)Q0 zwE8N;7?CQ;iujo4r&GZDM0ocr^T+vhJh|f`pQc$Mx^d4Z_U=`nA1Ys>(jD1T*c*00h!iX&1bT_2Ny|MV_ z)wlQHpkMx!dHq?PUGZ~1`Veuf!+E`2Wc31CESJ!1FQ;(3CkDw6B)Q+sUiF6IiMZRN zMcT{5zmcmW6t|b_$1n@rTE;M#_JO6T8S#@dI#${Ah{rAdK3ddUN>F!w5R|Q6ES6{$ zyw*1cTQvw5dKY~YckcJFKmE|RZHU%o+=6pEkm$0=}pZV4h?Db z#7;M6zN(YNl;Bv-)_#}ug5?g!V=emHnL_WzQ$Q0gZD=}2dUx%oyr1voAlO!Ft!>#g z0gGV%H$r^%;U61V9wT%PnltA~=%Np(60RfHGyf^^n55$y;ZKLT8Zb%Ndh3!!Q6lM* zeJ8O6eO%3#C)i4&%0QV!AFroV#5~_3Uolt;$w&`SlAjCQM)rpU1HukY>mFr8fvsOq z(g+qqJ`G0;Usl8Qf_;1E4&EY7`?*GBf*qbxWP%Y8H)l8UOc>LLjNk7E-BlZH=`bu9 z8?%$6XI!EagoQEMU}ZM0)I65YjdBlqQdjm%Bnsr)wFY<^PE$}JgS@TRya`1X#jN8; z0-x*IN+iGi8-jw4C^RrO7QHThzt;DCLJlx=wOB*#kr(%;W4^5<_a?vbgnurx=!^=D z^ac|LP;8%}{4$ryXyy&r3S2FUJo~_r_Ud*P>I-kzevQzsA4Y#6R)B>>q|GGc{w)k8 zJA)#sA~zugxVU8)FX;U7Sy9E($!P6Udb~F+@@d$Sl&p$kVxzc4$r}}A@suw*f7)oO zje7M_s8afthzPpn$ZOPArk&`D=>4NazpVW9$}}Z+`G9SbHVsDIRsB*E_5E6{W3H*%Y7vdjG-C)R-DVXuGAH2e+ zr#k4Pyxb#ND`IQ#!Rd908>J}lhSl?&IBc4G!a`0mZJ6WxPy-^}rZ@x8G+xCE{9<^o zZf>HFGu0#1naIhqQ1X$FUbtg9%eI%V5Z!QUtQL$fGVc=Je9n91#wM1$xVE|EGLp}2t)tfq9aY{5(I2v&A;g1Q1>!H2`0;16E<)UIgSpADs6GH=hXTIQoyt>gu6Vxi%JwrObjXA^Rz0MZ_jPluM z7x$BkRtBZbd-YSXNoBK#a8&xMAhFA%(8p> zj2%_Oz1E!t=mPwEB?si$&aE%Wg{OuJDT&wT#t(>kR}VEj>!L7mgI!l!RKn_`5J2rq zAW!! z;J7d_Z-C5%`R%Wl3s1K*x0-`Ikj+0bo4zV)K41by+YeUIW1(|x#DHGCHxyjGJO0f7 zU{fqe*Wjpb7LSyiwx9qfrf~NW340Dl_uW#Cl)ZApFPe&~KI*Q~RGOvjcUf?_+OG{ z{SD3wma1h}wyHXy0^~-4VNxHPc#M9Y9Us7-t_X%&nj;%cpNUdnwqqgEYz!j%r>x*> z$AMUE-}qkbv7M!NUfVq0i(b?E9F)<4yn-=BJEZV_U#_xBXag~!B&~{yuD=AAlN0v+ z6Qv6gw*JzW4`K6JRLCk?;i)$1X0o09B~qy;tp^fnjBZMO(2U=Uyp^7h&dnVu5iEFc zD%U0ApXC`;G^KxYs%Lr>u>Kk<$2u52-LMtiF0#yTm6P0&_;H$5V!hO`VyoRPr~c>6 zbLnrUMw?7GxY~M?VG-Z8(4cAL&l+xSf7u5wgZAcBi5Qjm{t$x{4eTF5XoPFr%Kvz} zAa1POV0&-bjX=!P^=RJgt$kT@VbmU4<#k`Nj<8pJb9ra@NS|HiW98qm9rA`lpU?2t zo;Db~L|uOD_f!A;D2G{_@Q*EL{zKTFR@(>+zy({EqqLO)0ZqS?DZ9PqNH(I{` zHo~kMT4pj4VcTuCR%gSi1++Ugh1e7oluh)DtXjz-KFZvis3uEw%+tY7qhd5iKbC4` zaDOi{J#A%uT?vc&KA=2Z6_$Mas`Z!} zCx|rU1^(_u#Fv1LDlLrylo7YM5eANzs%r`_P-eEh7%d=<4a-5w6{8FQGSPZH=@Q4@ z4d8_1vlKE)%?6=r*rzHD)LQfUf->&X_fNpS&sr*B#UP9@e7AZW=Mse5RgXmAkX@-Y zp=<6@kV#Kq=CT)0T~}4aPtZ@g9FNRNY|1knTC(@Efwx`Ma|p>OYd$L z)z%e%7j2g52vu6#rN8>VIPAGKq9QkkeVO>ZHdc^83vhAh%N+1_X}zh+7GosjNR5FE z{eNfl7e_ks?WL$MTJHvlhsXd`TiVJ|^!l4@(x9fl@MO#}XKvM@vdb7fpT*$LMJRCb zo?&+cS~j2nI6oInONT)7F($>{8;~}W<%vxTUqBU)6n5AhA)wey@~B2`wCR#3P{AWV zTX10}#&GkT6-{|+>ZtZ?W%B=MB?N0uh9s`z>-1qj8JBi%?!60^tR?K@ZKTG&K#D3R zsnWEvPc)hl&_yCJ>}sC385C2G(=qHMmDI^j{JMQ$zr)Opr1*z|-vT|?k((2QRc|SD z2Cl*@%|Q1vOT~JP@G@~PbY;}R$mq50|!`zE$F zQG(T6c0YCf36j4P}&K66=PK zLA0cs0xuC$TrIfGPKuY@h3S@5r!{K!gQW5W+WXyR53r*fO&C*o*Xj7mJa#Dryfk?= zk}OW8J^z2g^MCW29`19vM?u%lVE>4-&a7u4*1F}m;IW)k(po9hPTxClg=LqO3=j&% zG7!r~(w0E+u-;8%#P z5eA=;URJ+$Moz#CHbuQ3V}Y~X!-NLyJrA@ef4QzT=usPyET*Wc9l>VFTLEj6kSJgw z?aZkbf}lRn*hLfL_V+)x0$%qx&!5Y_59ksXz^bt70|PA>IFlmATnSI-Y*CSeipjKu zTp(bykRfy#>lm_mIH3RF3ifMDT1gbkt|BI-Xlk1RY0 z$7KVv3!W1^FyH<&(IunNs^X|8%8j?F)@O!5sk)(f%YOhR5=aWUGzgZD1Lv;i4;pq` zH^5$v=rgMx>blA8jTfN@&gYcN&Y&BM?-r_9Ek>@Pt(Jq-+RR(Ji%aPnb%8Y?37xoP zcrI~zYR5~BFc!WOZ46f`Cg&jI82b371~ZxnddKCGc2IRc z#PhjGo12+pzNK!q9>0?fU(C_p@1d(;9A%|D!o1{`fmds5unv5$iPg0Kf$uX-jV!gE zb$~i`4TRE{=rFSzYSV%Q$T8@FFIk~CplV+ZZ z44*5uiiOXv`)Sn*LrF0W);_H_#7cSU9yX?RcZABiEWC4|ZQULGrJnN}B=0TzbVR|? zIJIYywS#%5@~fHXUP1-J7P;93?QcO++mENxis@1(TUqXmUyEU|*&kzQGIrt|}Sr&%@Ij|!wUHpdMkvvOd~k(zHmFU%4j zYln{(nXA(qil>TdCw*iJdqi*C%9k@fs%Cf}C;N+<#S(Vs+{UIewmv$e49B!T#S+xU zn0cq^>?_;UmNhhv7-gVr#&=e?4TmPbi0HG`?C-YBVrWxoZ@U54-LQhLfu5714kW%| zm)YKWU|ffAz^~x@$ZLOoZfDm*-%}GOM1mGjg)H?ia(_tz)k}iL**J3iq$qn#3_iom zz7M@h#8I`}_q1T&g_eSy321)ST45Ru>?HkRH6J|RbvPRZvpxplnAsOah2La9 zI>(&5@bw}a@iO4<*#-_FFeOt0%VP*X{3~8qvyyE^0h3hkPXaB8$x0T@F1DdmKZN?u zHJ*ut?2rom^s#d1FgddSKbpQWstvB`7D{k;cXuuBZbb@|;#S<QV5EgQ^UrZW8PG*0JIJ34F5_*X-yc)hHgar zaOY?Zc?ykvv48aY39{u|XP?D*Co`dOeej z=7$`uK?v&!;*^DY*;m8-(@)lQ>r9(w7!69fas;h21-hBRyIZ_oiqRFz-<^LjLYFYh_Q^0LSKxu3UG0(M9# zH_tn@PLi%J4^b2p(jM+wz`X%L3wvl-2hHcgCuRPnv9+Ey|H=~Z+9Y!MYET|iMoDk&qHb;hZV~?XQz-AXVT?PxBWnWoaM2XDO+iHe zrNQVje!U|2E-F}>1-15Aqo%D?cvSU>L%#xgvL}CA#G*xA^E6C@>T2AcBPXE^Z=Y`& zya{X&F>vbp{k`$eK@RpEXm@os8{&CC)fb(Ic*dSn1G7ng(4!tN%B(b}yvC-nd$^W3 z%y!jL>Td`&Qg~%-r4+^Tp?Gz=Ur7;a!jCz042LWMAri)*Jx`7k+_k%qa{f)i$K@rG z=Kzz4A`wPMLd{mQwHNG=Gkm>D>DF)Fvbaj*G)R5zUy23*lztJu4>3rwqZT&_$4f^j4CurOIw_SwGZSh*1y#Y0KZO& z2ue`q7s-}NOAGoVPY4YV9L&7ZYrnMu-v?sgqv^L)A6B}O$K>{-BG?#6lqrVw5yqb! zJ@WQAcb^Nl2bTy1%p0lTGl^QaEz$UGw8rE@+45(Y6TT=jbBvcH<@joOp+wtAM~~w^ zjV=2;`^@pi5`ZUkOd0zb%8N3W7y=>+K0{U#4I6?}=FEOA_k6HZw=PV{98}e*kz%O% zl>A#;k9YbhP5NT@&!!)AsHGu9M4eh4nNin^Cm1lf?KXythQ9$;X`4jiu>^^;5@jaC zx(AntJB!vpmOuH2zg@*TeGm%oYJ}{rDsKZbzhSU~Z&ThC9?cB}qD4_lue$^pLJe*MV1YLpjDeD1{W?fdGm<)20sdBV;GpC8ZqYph5~Qi?e=GBSY!R!8j6 z01c*_3^nk_0;oRkEY-#J6%f1e`~89(g=Am9?+xCw|3!~7;di-==ri_tyb$nfuy?fY z`HboXJ&Q9UOuAOMtzgK-ee%z<^=ppOgS(Av9wsKkBW6FTnwxJ3KuoGs2dgv@_6pKK z8kGez*;c05kD8yG&GnPA1^EVP;#3UGJX4 zNB4>TR93NJ673KiHej^8pZ%?By#)x%hX8{}CQ1CSRy;yS9WZLH5`MFws86etMgXie z!_7EtAjn$DeZGPU;ty$~Mf4X?~`njNy&UQD`FNBI!1sAEm%Mb6A&8VFoqf@SB#z!!O@f*Xi(ljivg zmo6?JC6Fpa`>sauH=d7&ABrSi$Oup)Va*D@SHvPuZM;dHJm2~$v_cldGZXe*-YBq| z-gsm>{o|KF`9XwXu)}EXn4MSlllHgHaLI|FmW>W5cP^ruHV)%liZfFVyJ9;L4ArT) zJ1*a+Rwx^T%MSwcp=oJ(_~rYSpGfQ6sqDSq!`f08GT7crt!9kP4^=(WGr}P1!aiWj z-lTO=oQ7;iuD>Rxg+;dJ~aES64<9=n<@t z_lnIy`C@xglKR*6#r=&80o?-Qxdn{Sr>@_k4!pkoVS_nMDH?_W3hJU*YX|#GVPb$K z)dOeR9e*MmqC35>ZuuNnU`^TN1Sb8x&PUwN@TQGcPtsA}yhZRyg8kgp?h?Ah8 zmcK*yBuiI_-a9r*>@qL`7ODlx4&1^(-1HWRF}%+!^$4n@%Up!U{*BgH*ue!gO2zcL zr%|Zb#SD&T>m5Gc{y}(N!18M+229seo3~^}!ZKEXhNz-C)oEgaD{)iMDWaVNva)%{ z*JvuC^AHp+H2K!-rl5^8bj)wc0&JtO^n02;ua{W8m1`^K_W{MTEO>^!a{8R^dS5r+ zwUzzkW=Hzi8Nn=Bt+%uc;>)%$D<*7h@OD^nTVjL>tce<2p`WrolR)aeTU}m6$Irb* zJ`PC81Kt!ZIzHz{T}j-ugqpbXby7@G0At2|pEZ@i zKG)arOBDwG&kv@?aru5m2*BX5joRi{09AUVkH_Mx$gP2bH_C8MHs>>t(t6s&yw_#& zxovub^>AR%<*J|C>GSm>sC47? z(1udsJ~OXwu|R-qGp8o-msie?zxQVcxZsOtLEoZR;^QgE(#n2U(xT7f4KqRPvHjre zMwaCBwWj&Ate`|-$f#V?^wyo(GpxN-Xc-|xI7l>(OcPA;p<_I#a_7K4A4f_7k*fQ%y4LHMT32DC6$4LCPh`g zHGL;;p@6mW?P2;kIbdT0cVIvji^oYMd{smT#YI=)e01iWAd zLDH^*AYpGst^%5(%BTb=SC|gy~(?*sXN8-q~9NiZD9^JXYVk@`y2e#)oG{+belP_TRU)x%= z&jF#?(mH@x+{aRXM6WCvFEqFHf6MrO9m68tf*AxZFFMWqqq9Exkk*jP`;gWB#M&w- zVQ{Q02T%KMFQ_Ro!24rd0=*d+z`&HUJTk`Tdrh zXYQvNw~7@B_<#))-*7Pb>$?fPhXtE8v;)rVzZIlooROXxk*tSK zb44FVpntG*(VF@qqIU0w-YX}L+96b>*i|MvHdslA9?JgftH9V3ga=lvI)uHRxuNeQ z&imxk;YDR%dHXu&(#6B+bweDq(cJQ`-iaoo_|ASVjm<1bkb)YpU{XL?vw2f4K3R;Oqr1O_KHQn}54$8XqPQ82#ihhvqZ%3+4TeVlXcO*~ zY_w494~Zp=E0<^?#;$@%V4 z;V{NP6HvMJd}uAgrD$ePC;%Q>auz5FwMB%{&dya{;eg^^SPG|HhIhr=n*`)Y7)X}e z2~LJ}UQdzc?Rc;4rEQ~by%FpC3u@}_Lu{32$^gI-+tVLya{MILxRtgmbAK`3Dn+dn zRDnXd*_D%&kT@RRBnrOa&T=$&9iVE!*h```JDqA$ZFUf>?0 z!~iWoxNlJ@=TN{nl*)lfuHavnExT-?F>>E=F*fGIoe6^*6j2L1WALUWbrI=^uf0u~ z|Gc8f(0W$trKKtPq*4&Tc88voA!zn^LoHXJ*tXdhM}qyPP4Tm^m5tf*4`Irf0YjC{`v7Ucao-%ab$vm`4;h(+u@>6p$J zE{d%U>kWsF&!M#q^IzEn=MtMf&`G1B{>Q{_|F2bups)c9H%Up|daqmX0{K9Aupmk3 zz6l+C6++x zgSV3r6u)^Ax6$ro_rK``X0(^`&e|gPM%1z48m81(rS}0N*MX9PhOWRYYeR3qfAM-0j(S3_btXL7R+R()KzvhUJ7tK74+|=Wn<}E-X_w( z5sb5JUWp%~Qd?)CFoD<4qauxP0tVS_7JPu2*zPgZT2`cECi^|%vQfNRAFe-tD0_v( zryl8qC|XsZyd#9dCAV9&0q!p__o1u-ToOZX-oBWVE1D+kc)P-MNFXG+@5ZWF&6sne zmc^*t0|eRMXpgzbFMeN^)X}q`7?-U`S&W*q z00^6A8UK{gtJ!@kyd2tCRAsGKO^J>0zbN=?LuTcCNb@~9wK(FmYlOu``6Q3{V)5#N zg1M!-QkT5toYb@k`#sCFy`>>$hC{#jxRJq!JNnFs+E^Dx)1p%oC?f3sE9R4o0*~g9 zY%d?zvcfxCD5S-n^PxRE|19)$yg87~%!fH#-HVS%70c5yrIDsA&J7l( z;m)&WQs^T zIh{?)S$HopB+BdEpx>OWI`5}AH4b(41TNZqulN1B{4sFDBql#+kC+R{Hf_#Rn+bX% z^>g+2dMl&#<0+To7J=QGO^x30M{WtnoM(WcT2WkaI6%Ae4=?M3&iDUypSjeuMG|-F zn2ir%CfM|H?I0_uk@s=!AlwG7cM;xlbDpKHcuVXelNvr>O&z{-Otv3yAUs8E8dyOO z&|M2QHNLko`Enb$CLE~1@%8o8ce;&Ki{tnDyn(=?yej3REcLn~I*kS=j0aAxx|l*r zO=pTTNP)hcz4uJpUSy-h+90q!pYPeSm{s|?j1Jlf5*B#Ts%b6a*j?)E@9u^ZbuLm; z>4;Vohf}@NVe|zSCV{=esqeFtC}WOUI`viqVn0{g%4&Jh9JfY=5YjZXJ=MdogFkU$ z;p?&|GDc-bH|lyjti@KT3TAQ}C6$*8k7@zip~yqTPbWH5@+-{z)oR~x4#eIoF(NBb zvjX`3IBFwAcL8`AzWNBez9Z?idE#T-s2ft4W6-s;|Aj)T7c2l*2XMyX-KsTR5)Iu5 z(?nxtG;rF{Q`2c#jY4A$UG(PM`Ytb}k;b>k@Uz!V7Z;H7zEBiP8LQ3XtnG~v{BZ#= zh_)vo<1@>*eOBS9Nx>arS10v!_0#QHEJO=m_PGm;p?r~yo0t>6X+to9r49K}-1waS z?ek)jk>&9>0nW;uqC5!7{zU3TJM@;hz!e<>!zvX{ zEgM{kt&C02-6wQ|EObRi2=#4(iX>JqV|2NM4wgXLt2s0p&O52SD9yt<{z(zY2xyZIwn0JnjPBCI z;Xabd_X9<=)ZoGs>UrKktJ@m1O!*-#Y$+wQI+ap-wsHZMaN}aVa>K~R{-F&AJMf6g z)^{D!3DL;im(o=Y;OCYAMnlN~9FZ%zK-ol1Amu_cp6o6mu_`hP0uI;qZG>tx$#M`%c%{VpAO!%B}kOPm zj*jo_?XNUh-If||d4#7B?4n*d^53J{k@s_{x)Mom*G%L_PR)8FNF(K9_i|YvDq&sK zjdJZoo?M{EvTx^r;k#P#t5l(^-on3(M%8%y>5ze_+KelsU3!71}3 zSZoSHs86eKLV=z-JhJwY!4?VN`h`4_Sb)wI8e9@9(C|`^Uc_lrn&-Zog2jHI@RTQv z2Y>Q-9{$KVUDZv zG#0zpV!oE_Iu&(`zPqIwzQa^mrry86bnejJI;*LjG&NyrNNk1RuX~T3YCS3BxZZzG z1ihJ2hm-t<#P`$@3Lcc#pFIos#4AyFUq=yew|JQHb$quTyKpWi^ebb06-Uvos%7J( zL;mR5Rc(Zz&}d3z^?5m}hfCE`@q|Qp>6N+Iv+B5n3#}hO{C2Qi7yi#C#!+HWrlIjx z%MPOF!WsG!1s$(OH^N#XqZjreEUlEUZIP~6b)Sh!N70-rkn>4)IVR#OYWxxZphtjX zI1s~Xz6xqOAVeNWI~$ltL61=`q(NUO{)#%*KgBH4 z0Dj)p7+OxGyzYHPa@(GrE!2ZKj2y6JiMS759Wm{-uVf`+z3}5_!BA+3?vX}~G>eS* z_g>nu4Jaq8Zy0vnTAnIIk!DZJ-<^{prGhCJiLKVCR(`c3qxH*1yWY?;32Jb9VL`NE zrH1|VZ6JjX&u{qAf|B_DOfOS|wGFelY-P=qjHV-A4-7Hd0f7S1n|+kCuyuv8Xw;D> zpa05*xs2;`FXiPItuVIc=YPN-h(#@Txl7~ZyF4w8C7)lVAWTxYB-5^j?7Egsc`deL zx?OG*rDtXluXDJ{#zIsVq{H08-Fy9`E<4v+Y3UVc(fj{*icTcxDH7LY51!s&+uYla ze?Z>>24=N*r|QmpVRG3M>7SFaK*WYBrxn>({Lc?>9K9-=-V?)L*;7FBGe-xji1Q^J zSJ{=leC#2Cg(JY0^Za!BDcEd1g+4#CUbz?5yOa@pW?Q*G4jrJqM7Jc8*>|IbsHw6J zk>cf!rLpMc_`+rDua!0g$26n6ILl>fq+ypp4$e#jb4M>yT=D(zlC1}SH3D-jH(AsY zJ3O$$O-%vB-f<1G_OQLo)`&!Fro9e`H1lF+`zKhU`TUhxZ)8)8-sMin{ak2t0ArAl zwkNL_xwMNcY9z4;8G%06MC+_K3!Ea3L5e_w#3>UK<8D*XUFlMZn^l;+mhpgGkcNUr z3KnOpqKSlp9p+Mq$|W)*&H#RrV^aX0wvS(x}}`)GVzdZa&Y?=twORW_ocw zR5aDmxS9{-b4m4524=mXXI~T=iTE;ynE(z?*=MfOc$Uq~Ylz2=h@fwOHO~*Has0~Y zeNR)D?^9+l%N@0R{EHxFM8XLYFJgl$d(i}{5h*y#4A4=)Ds1|Af3|MKr2x^(I%8ZD zE-s>Ek!C|Ep>QX6&OKC!PxFZ7P8j`M&v@@#eu<&dz*0ZZYZ?m{LR~oJcUtJ1e3pg* z$a*hw!eYHUXMJ{)9_sl1$NIg)nzcb=cx*IbMv?}3{R z$_@PZV`}+Zc)~(zatm%gIs;OO}+ohF^}pH3c@4s zXG&!I_E4d*0jq;T-hQil&=Yg9`gb+?i^!*&qMqirY(ghg*qIZAb6+SG(rX2F;MDA8 z>91hYpi{KnmSTdI`9ll{Ql*= zAcl$kFnmH(Ki7nhG|to+c$<#~YIBCX4G^z5&&9*u>(#U~cl>8(b`X^Q$+r(qGDr9} z*_GX8>1l8c`fEnUm_yX*Bl)Hi3;x30&gzyrV5S_&!LutJ&DG?{&JkaGS&guRC{ zI>$WSxqC~eAh&j`dtP5Kjz`gFMrhxVYeuKq!}4Df)L{c?9QzS!ek7nidV)x^#`dA+ zbxP@FWEc|~l1mD}Z2yrae}ha*geG=5*Yy$bnEexLE(_G&5YLmh2;VXU$L+7>Sa~bs4ykM$t2>{>7 zU&ezV{9dbU+2thSVO(gu`+~Jj5Q#GKM^5TvOzm~38@(gO0Bkt0Z&i`zNg6G?P?;u0 zwlh%A^cq4t8tqR9paW?3bIpb@>~z=PMVj?}JAla_d7Hf+V0}-C?d3CdgF^;@WtW?| zqV(ut<<6lYiN>rl2_TgP&twoi|I zRkM{?S(xB-gO;}-`GbIE77^f|}<@##`Xaj;M zK!_pbG+Czu>tJnmekNKT-K7L?v@~~iR+Q~|YFKDE!;7J+PV$fk+|mp<9EHOoF0DIK zf_r-e`@o!#5&*9y3`4a8d3%fde#t=XLeNNP;Pn!0{eKSZ84uYs3e7_iQ7WI_vyo0B zIs!W&*DAd(?4QZ>*;Y@+`d~tpBC;XcaacORG_Ev*4->AXnL;#{_xlxHP&ojcnh_b~ zFIRK14h}ss+-AKb8`^6Bn3g26Z$6|?_u|_an2XCy9ieFB3rgs|0~{x;9~{%_-<&1A z6$!`0)leE`Mc+kzd?uz`7=mLq51_n}P@XIe_9Ea|x z5WjA;WoLEAviCqLclboq`I^8>HcNwq3LVtG`7G{%H7&}Y$6W97D}w~MKR4{MYbxW| zpRW3!wsgEJBp7Lj(-isWsRfmQbN~PvD5lrR)WgJ>4G|QY7KfM`e&vxK?f4Nei}~)C ztoByK%DETJZQ3(XM;=_DjH1@x+$aI+LU1$m2dafF8^9B_h#dVY{4V{ai;x970pP z%X578To)165>MK{kk%hN`Aa5!or<66N7rXeNe2>aZU3q9;fI!5RU~NmQ7*Rx$PMtp zc<)}jj5Lh#-t}UOp?X7`Hv7xp-ha`S7kXo<^BghsiwF+X;S*V%y8IXGl1kGmF4a-u z2t)^G89@2x9@NGx*iFr0cksv>R80|2We6K-8({G|Y2qaK!afXjm!zh9+9LrP&}PN- zQc(yV{Vr=-`lkT{iM654!ZI6LAy37c0Fwr6JR_!@6>yEjS{RLnd=5mgS1TXycED@fB7qeaH0XpII%7_2VP_ z;hk_eC^vL>c3#9M9Aq-AFJtro$ve9eRrw-MNj&g638R?V78Mf2yIg6*wP^}Z4Ss(QIdBSZ=n#|-cF>KoALiD4}7 zxNB_L58L7Tvsu;xCLJt)%nlOdFQMigefTzG!+LF4^7Z{;6GJ%vpFM{G3SH6>CdQX97o9zhN)^`BbUpBopl&j4|!1dg5ilV{C%;7YSTh{qze zk8D-eep(1`@N9-Dji^L6{G%ThBScc4d?4J7_Mry0@X(zi#Ldt?XVJ(;Xu2g+zRe^d zsWaj65x=sMLP}yR7)ic?ibk;wKI!r@!-hp&7GV8;`xLV^54raAy-lXj8fmxo4q)8) zR){8G77#GY?xkPR({r$@xu7U2-mOMr_aj=K^ff{BqFvu{pVnFK(vjjpki9 z8fgZ|Q|A{Uy^@B@J1n&Do^ciCn)KUpDkt}6?1kNr4~w5-K>N@uBKvL;WDq@Mj|?=h zca+rK%r~%iwn8CpKEojUUbYkyRK51&Y{I{?X;JYwk|nwAS1ZFW>oK z9qZ`NICJlswHyk+K5rURc;SvjJ}D(gKZ_yUT4-q!wo|)G-YC#)_B55~3M$42uHRuv zhb6fJ2~f`9V1$msblPyU{Bu+Yu3!5rlajR|n=0v{dNg1ZDTM~hl-1kXj6lpQO#q4fPA zie0gkML*-0RJ-EjXc`h5@!K^9&rmIGFt71bnUdL2ovch}3nIbwM}(;K_r7bc|KmfP zY@<2_n*#acrBUWebsahAMdH#t$64JUr~JpRY+BX&hrKE#yk|9<8Fh}REia!thPz4> z3=8m%=6#~o9b~FGWYO(vM~#=E&c&zx((fK8epIIR$ZG2r#eyI+=}e;|&=FOw^dZn$ zEoUGkZajX&P`XoZEmlKfNcOIO>t-8yEa%|BLXP`_WNgCT3nt# zio~VHg;fjr1EMzG0PRWsF+U>|YE!w-o0|c`6)5L5lR{*IpT^NrKy`NC&bEg;g#rZ| zR0EHh8V6VU9N~hwbJ#bHjhbimI9~%qgm~jAUryug|-ic5HYSNF64B zO%}z8`jFf5yl;39?@zTC&e)7aHP1kxk)`1tWaP~D^aZ|2 zJ`ADs>W+{DybFafN-xX6T|UAKN(5C-)5TCe6%rcsk5xT9qpjfO%hlZaLiZCN#X*yM zO^$cWvgQ#)!4gf;?BwaUn-3X|6A{^vtzH(5nh&N&m)NJD2f;h+lN4%#qQCh+ER>jz zZ|lrwmY9``rxMK;atf_ByINO0_)mms#fD69RyPk#&kx`w^f@j~3QzdQZDJ)-UGDNun-5MA1YnMZa^u#L5-x1_oYHJOcT$G3EsLqZoX=rK z75+jpc}l&Bo& z+7bNRmI^fCf1d$4_xl{qz}3Ws&S*KLBxAN}{b9-V;XzaI(_bR4tb3?ZZ!GlV>Hz?R zbkf6FBqjSLF5rGf^B~%t5JT}qFMCvW_=~?2{VNw&4npx$pRRzoRX-rFi>`cYtsaa# zy@QL4!P^HMJQI=uM->8Bu|dyt3FKowLfbp;CS8%N0)mc;3#Y5|)NQxxmWJzpCN4$= zRfYV!kIUY(v>UGn`qkN(-#5PJ)JbGyz@?V`d0^mq8rrLCi>pII`PP+|FXmT8iGUgr zEb4r#6d z-NS|el$BM>EB(kuE`rivB|YbfM4eA6tcXP9xAe1y)aW3~><}vxqw`ACsp<8TpGCR& zegUgvrdM)~*V8}X+z@yAr!D|eY#wfImZJs&vT zk?@?q+;1dXydQ{?L^@3KyVKa9ub~^Y33C=Rb6;)<1(i^CyV?IN(SWltE?^r4o8ut$ z7L`9T-VOV+8r})u=S;WjHu_$2kCKnS@vRgAbvDV*HB=ZWfPCPxsHXD>lkiPL^N+uH zB&)Sc_eu;%cIQ_w3Cmp&7jO|NY$ysa>EPU1H$V<%u@QZ3A=16tsk(Y+f3Ko#OgTb2 z%9ZNmsrZFlO8&Nd5;Zy|4{HKZYEA_0KC2uK`lR2Ek zmAfCUZ@)SII*lI@M?V|rPyQXOqB~WMuMe%O{rgyiYZK?DnB6g!z!C}PlZNYa$}Em4 zKe5sor3nIGIP5%8Gv#gUw7B9GIzkbR5cy!&55*BOt?o@G(?jvV5w?O@q4_5``gFj1 zcN<6Xi0QZ0x2RMD?~fpt-2vD6%*RrIQd?>VTmLCO9rEdEy0~?;`nja^7V0I(uKwv) z_BDRM+-IhGa-@p0HXvk{eV#wRlv|1^Q1PO}4GR2n>$oJI^TsKZrb9*lld~y@l@Ybz-t#<&sC+LLk&|bRRilBu&#MtI#VkB|K-H}I zM_jF*lD6`YM*5AV9{j8u>e5RDBzTNiQad2Py8HqtQJzl}?;er9Np$V5wOflAE1x?# zOI4j z24cK06`%Av*38WzYhOHj$lKXl`Om43yl9A+VjkqT?f$B2x8izuc^C|w9c+q7{djQ5 zBO1VKNeART{jmJnqLa(}j!AqF<7{H%rqF3WHUr)Y1`=kUIo$26sOT@53j;-$B(dx6 ztnKhMeE(ZHIi6m}6I6Sc0cg6JLe4TK=k5FPa}dg@xik5aybw*==J$FedH&1aZXry# z%1R>D3n+1aPYrJGWHjlO>3k*>&MMZuI5UUeL-?BqTzuD@P1+)FJK%~ZQv5{<;d%GJ ztv(Z7WbYH|m34cw;22q(Nnt_DwsD9xc}D&B;tlB)m6j^mZLLX0-!w7))t=1$Wmrkn z%N7#$Matnna-3vr5bUf-KPKj_t5Yqjd8GuyDPR_CC~{h-zqgUU+>7~S&@-{sVNARp zf+Y8TdBuz8Y>5>8u(LfPI-`m>`JFUUh?1R|)9YZ5+xj7(%e&c;&03ZX`0}e1YNFMp zY)DkyX9yWiesxz@i6?-&eOQ_%<|p_zt{*JQ7VLiQ6>9W>{V8v+hl#CTY8~M0?PqIi z@m$0!BKkOtgI2%S4Ygb=o9+f^1EXxe>wl9WBS^;?D5kaTw<_c?vE z5`9RnSs$<#cLfY5suur9mi_N{Dyay4Q=C%RG}V8qUR;PwI*jq6AXpzMaxz`uIQ{d- z+iUkDZhCqq#Y(ktUbs~k!Dp}67uU7+R4C;yib9gTe>6J+3&9j9&NJ@U5cqDKRQ+eQ z|638J*}04Ot!q65p>c>(;YZ7AgU|hb)W;<;t{`{?3}d2EAkLW@?g0mo>Q!OIGdk;* z#ES5MHsQt)i9B;g>dAR1D<64n_0|5Dj!k=H1TA8L?JO}#=ExMiO7Rw;3+Fk@a^Z4) zPQ7nR(LMm|uhv(FE<(GleSy0q7@{JO*MAmA(sf@0Bym?kjBE_zzg-$nBdm27XhNEh zCvSSnr-6fU(Qy9akTXG{+g?!giSmpLs*rQpe**ziqt`a-`* z&wCTjF=@W`2o_mI94bk%kTC0Rv?ymcKn&kou>h|GUBacbnq;&`uk65iv?j;Xc!chv za*WMv&3X%E0I8vsb{NsGr0qaXXcw%V3Hd09AdazU3h1dZ;rby-LVFdlPx?Dg1SKFO zc3(%3h+}LZwSjPUgMtkQ;e_o@WM^|gcNqaiu1UjMi8vIBRYF1diPp=fmG>`yYjS!e z9wHQ6U8r9>39v7>y?h;D0VLjO}64}gmgcCbyq1CbA-1(t2(8c_)yDEB|D#0 zbF^|KL_pBY#oP3ASMG{WSkRmMXz6@na4<|IJu{EA*Kf>0xGoF?(zA~>CYpH2u*hhr z7*Pt)`N%86b>lcNJ$o~wY7wqyNbB3d@3o0|J3$PQ!M)ypNVwI5Xn)(ZADqc_C!zQTg5R9xuWcdSJ(zy~F+R zPN}7Vj>lvRHEH!8M$(0gTkPwv72C?S_GJA<2MmVBQ4(*ohNW6|xC2hIF{Yp5f$}q3 z=kAZ+HI5%+KNMhnbt+hG1`m?Q)ngstvA3gBxQ51xdKSx8yVL}ADPk)XCiE2=-n_cP z3RqQ-?BMmf z2J16isXx%3!pz*jX=7*pt2bVRBL-f*2u@PEx|4*LY^JxxKT z*{rBp>lILAw+Kwu5==z>hhjnPGXwq{-&L%{+x7C=kB7aWIut61{P}8xijCS&F%8V= zrzf!tOFknR3m&n7)mn!d&M!Y~ot-WAdzhr*(hgNHZLO#Oc-v6K-hUBtj2A=U0aoOs{W-9DhK~eaz(rn~;Kc|EVPp3Xk0xN|%vQ{I zv{s0%(KC_+PDu-VS6g`sc{=aVtzEHYbv5&Fn;`hCXVhzd zuo3D+@CLQ(S;0Qe$0AC$_UX111G}-ADmiR#~!=6Pv4E zgIGs*@S(0m<^as<)= z=5;4>P+&b&NQNOY%-z<-P&?a|{owDPHHZFCP+(%prFx}E^V{D7vHR`m~-=$y|XL!b^?|(<$tv^8m zmz?9=wgo;s0CfY`bQD&9KYkn_K&D9s(h)`k2A$6Ca9Ks+2Iolx64V5q>=i7sE7T94 z5-KYHe(8&C^|(6=*z;eKQ7BQ6S)Yz0f%m%T#U>z*B&HBA;`v`x4F5k&otE~AtDg(y zuw!C0XMxh=PldZ0*_kJ&!EIxygFacA-LX6{bl8?f`z*Q^TJa zy3|R+y}pWJlMOH7D@V+m!1>6u#h*T*n&jJ0`Z$Wi^G}I*C@huQ)ry^52l&8{6FUat=^OW!^@$E>UihvywTUvmq(J}6HsnMIvfjx2$}{TuFz`;iSFUw`(~GVYANj{51ePX)*5<)OhYw8svL7PRm{h&jTdQsSajjFN`dApPHle zk!YmO`2~KtCUiObn_A$Ai^|SYqE9WU=?}JRx#}bAic1yojc7C7S9k#P@ExyjAa6&L*~)z{G<*QYEhbU59}W~_xSo6+ z(7gQ05j~IMh*RX5vY7%68)6bgaKv%4SX%dx&Y#@?9Eg~deVxM>{q?di8{Hd#5lQ48V%WN2J02Ejf z{Xb(GX(k`FEhEeOPu6&W0PDr)0rXC7nlY`Yo9^2}y#d)44O?*2y2*Adn&u~MxO;=o zF5HT;v5LDW-R`^!`q*#v#Y}`sp3$2lM+&=GFsFb5xz-;p^XMpqEJSWPEX1~aDa-PU zu0Na6d%Mt^`@7$?SEeYIj;U}mGT7!zIh6P-rIRloaMjT|&(mHZl;-vp?u`ggks*e) z6?u4~lt|nIc}G?kIpq%dFsTg@HfRn{Eq+>$suFIAELDgBC= z?AmUKHcdG)3d?usOGpDw{g0H(4sNu`^Mn~klc6u`Oy^a?T|CA%Td`W zEXGwp=)KUqpFp+o@KX0nYSLLUSzAme=22}GMx6c??~!-Y?_ebG!(Wr_yW6aOUD%LJ zU|o;=*@p@Fs$+&Y%+U2>r~qN+N&R2iG5e3M27QPI`$PF}hsx+QwoLgOO1KHfFmK+2 zyambOD9~+cRgSt7+wzGnpzRondJtB^V-j{7je>sCfF)cBfomFwN2E~B(8%&8=!-;} z;I+6=pqvo)`}P6ZhG@O&saKcoL^}gdTd*JEa1V{^AznCH|rUU(8X#8xIKMt5vs=2 z-fls~DY*LrDuK3HwVq*hon3O`cHX``i*>Pm|8f6^bC)>}S_5n8j9y2yqt*9ulrMB# zm;&B|TlvcY?Af*P7B=^g8uh?V#L!G$#|6>5% z;f2a9K{Z2L_GLm2niaC)DI8f7F@&2K!u-wt9VYm!-~gk0TS3@qF z{ojR)HoSIvzMS};L`J}wS$B0*cU&ZoF~r~)_QKQ0;%|o&B(e@boKIKCQNfU>mf2M&{4YP1>90+jL1+A3S9{$s zqoE%^UtW%X=v)bQa#=c1k4rjzWwOGy^*v##O%$TYWd3Z!hDPF{+~t=Yv^rGo}Qs?^_W*F1L( z)c%T@eaXS06^0RK^rugPA7U(&%V)RzioPvNLERfATpnwKE&lrMS5`nCi(Y4ETus20 zdTdqWaXg88S#zWyx3qO>1TXjrL-G9YD{20tYbmRNP|3p^!_`NEwP^?7^KC`^d&oOdfTU#b(*{;ZZdxZEsJf@9JKPTp zuOUzS`z&e+wOBkeQWqK!hB@o~2vq*u(t$X7pM0sKa!!%(1HBPZ3h~#aNCnQ=b8|G6 zX{oHxbqh^(wcFFib3ZwpF)p6)!8X~kblrz(j|as>_M&F=1tD?f8)w5jR?urYghCWi z8zca8nHuya>QJ$4EtFuBl;E%t@;Q*}uH|-5$57lI_P&$x^}cgxMay|}ze5+bDp>(+ z3eE2<+lO+D>*uNm{j_h6d%98+>C6JJGan45XzQ1JUqeJp(@aYFdd-8-% zM`6MpZL7Y5P#;{*x^=BeBFCFhW)fI!S1E`Oxn zhAE;Fk5CMSM=>*omIo^$hMDZcyZ+BzjOA6~f@?2V1yKBFIkPuCD6}t; zG{>_weg0V8L}Dss&c138LRfu}h7%S4v4EDoO;oBWqi4f8=S9y#N0@AJ(q6*v=<( zap>D+H^R(j#CWX!OwAM?cm+)CW9pCaC86T8v+!`Xg9s7p{%@C%Qe!jSX%~!bc6oGE zUZql67M#gppUJYi(?1V=hYLBiVi-zz`(AtyPw0m5?nV3597VPTC5{4NjtzhH-T{kJ zy%Yrkl}D?y>Eq}aH!E6W!r1OTT|7@V+}4wBFyV$pDr1o*0d!laX5XYKz06Or=j??a z|9ZIG<=PNq|Q4p zG2cuR5EiXb_Q6N`EfMsUzK(1;7>-(Fm>`hl$obG#ojt(u?UOqDb1C}7ad}&x3DKj& z4N*0vH|<5OlI}a24}2)?5=Q=rO^8}nNf0;Jb`b^{W#$4Zj*rYXeU5b zy31otI!;m+j$Y|M&j88tIxg?5$OA8=tEWE1{k(oOsBdfRZTc~OXZmGYVr}Jx3)^nF zk!o1>P)}*8x3=7IH_quOJHKdT^eWEHpfxvqPdM`GI7#~-Am;R)#$le9Od0|BCnE7` zlc@QBwHa9WO(L-`bDfHv(k7n|KMcF6r7Q(Ph@+UXBzjjsh$!3M_pn_J^=rbyQ8Ly* z3bg4vJ-SC_Un^8w_-6VPLrn9=O8Av|&0?=+hKPQUqb_DyA=V9tEwAa5tVinm7LfF!HCfL;!ZwI>m7Hpn?#@Z!vKnaPORLbvRMMp^p{@Tl46=B>NBRf%O@I*Pl+TwAF z0-L$()%?2*J67Nf0=v;H4ajF;;(PnF#pOm>)q*{JyAm6V_ldy0b=Y7z_7#;T-_*|C zbaMFC?WH~>yowB5TCuJ**U@NY=Y<3$BXeQZ2793(6Sjr?;^PB<_{fEb;D7pHo(&CS zC;tTOiJF=2OTud<@Q@#45th4j)}b1DybIL;4r;=a(A(xlR9q_a{)=MH$g0)^Q8ip& zJpPL(Yp~&L&oTU$P>%(Hzg_sclXRDyUc24qG8o@qu7=2yY2md4eDmjAPoIETX!l<~ zuQWh61VZXrY4^(}!grb2JY)I-8kAo)wdSY}8w2-B{{%g^$pMSUgUZ2WRNwEIp=I-Y z*sIe=qD&KBrWlzmP}jBRMTT-MqJ_vWwyEgNW?K(*UKHRg$DFQn^8s6vqFMnMtL5;pl%>DI?q_ZKg2Mi#%7im_w7idLO-?p4hrZ_qqe znkLF51)FYGo=5>@nWS3kYQ8c~Jnsz_*ljehzmc-RC~THyOs*D+22)6*x<#lDsd_&u z8t{4`@mJ2jpf9L8a_Thms+aK>IP%(M<`-Ueeu2s}bW|8z+S;jY9zXAPSF884Hjz-G z|7T8hU-#0T2M=p|5Mrib477EZ)vV_FfpZGDz*EVfUW9_KDtoxx*e&ol>p5>{)yMxk z3K1Dj@@u;k{>94z;)p4^&%M7IR+C{~`s6_CBL*Ha zP6I%5$el_s{6Kol-Q%9T|2ODO3;}X+!pi<7!W&(ek|&QnLBkapfo^ zTw(FBOsp)99VLXVnNI&bs;JiH=69Ji>XBVh=Gbv@ps=5@ za|XGUBSIW7N8H8shhfd3%2Q10x-Y_qB)-lY>M?chE)5z>$5lfYcdVEezr zIsDds_oPD$>)E#EZgwBawC)}qT5nxj&ipkeetL@{#y-K-0?8)XC_-k@dKgd!!x^0i ziI)^QX^lEy%YEQ1(R=88vpFgz^lX#8WDvWblvnex4tZe{<>fZis**UKXpJC#uFx+o z(2Lre?!P?w$}4jd2% z7B$yeRsxaX+~yO6;gR1PQou-9gn^7Wo$;!D2p}_%FYLuMvZe zg98Z;*&Y23zUR7fP@unW9s@+3S-2DPq>7wV8(>S@StF{o1(uuyFaqJenPlF^uh@-> zBZbT(q!t8Dt9z{BSk2_BwQai77Fz?|C6ZtdOLaH+FS)A6xg%M= znLpk*M3H=i6l)((uzYnc?Q(UNDo%4rR#2lnkIOHldvEoQX&?*#?VFS}*{cGE19mX$rY<<>w{ zHWW*ML&b*ZhmGDSLUOp;%-Eb`ih#3S=k58LG1uLvPlj`8Eeq?r0&TBCC#y$n$By-7 zNBW0ffLt^71AOw#G~aU@ZGg3ff#Ccd8G_@NK8x=+0PGD*2+#F^UV_|gh{#p1{z;nx9#>TJx-Z6qSZl-Bz9Z;uk)*O#u zVN#09_2x8(zTGd>Y(=)v{#2>umC4>92G`RCwl6^3mnunxv9l`d>bR^Dpd7*eJj=DqS>5cos~3W9 z@h23Ti{9iQZ0Fu9zbk#|6rCrorWIe(JRPqVGzCnDmZDJyC|M`)3)U}O&#%rFT8=SJ z#MwrlLKY0Xk&ShSAI@?y(eaeQ1-%Q$d;ZSiZ+cIEZP&kX5N|`s5`w|5u&n-}dWHYe z9oaaHxhc{BIg#xd`n`TTiZ@Z$D~ZWb*Tj}9*azoHqbrU>sgf&|PQE1~4!wKab(bR| zL{GO&2*1_g)}?GEVpePNfv5pfg+lfL6UItk&wZ?~?G&jtuE4h6Ch<{4tu^(iGxHcWtcjITn<`8`4Cv8~$hG%IQl4 z9Hp-*Y2Wi^FVX9>iBW%+NzdDrtoJNkIWwt4j`kMlxob>oEpHyCvoEu6g$}T&5I-hQ z56szEf1Kd4sZgu8$|5743#qW$^iY|e4$0r4^159$^rCTWh;Eh`cLzJSvn@Nm9qXwW z!uO?O(PBEiGPLLAZF6t(m{CVTOHwW4(y3#QMh-xmK*8$_;oU>Y|r$`#$%?1yE{<)-M+g3CFe^{S4!MqBmaoMVkh0g zOLO9Ltn3nnDw2N)7A?!->3KUV$|d&;sy(|CNWV$vbYGZ(HFYDHUV3HYm~WC9XwF#K@mu7E)@4fpwQe#0}I+7Aqg1N;AxHqDp8nYHJgCq*lyk3drX8wjN8 z3zXEn6_xS95yoYoOWHTxKX4RKxjgI{b$FBRS}Wr7%=Ghd$I*UPJkDl9Qm3ANsdP9 zwm&(#s=j$?mP$=|Uv*((*OlqZ@#FY}yiyvsK&MM;iDW16p)u`#_k7{B!yl@11_lS* zV{BXxRCW*6VnDp)1^|lhzD3k7Xv;G`uG;`e0M0$0fY?0UJZNfLb7$o3DHy{NGF0^R z{veCc^?ns|t;>(C(Gb)xl!@!aZ7>b}VjujzeM@x9zkTk#&mSI4m7;6qz={=Wn%?dAMq?#1m`Mu~_T3M8DSjej zQ%zM;t7zm#xmbHXbM$js<|h12k=zla4vJwKSEX1J(sV-Sg#ng?eb4tr{hN^J&4Kv( zjmS(J2dvPFJZ!-TDIK|RhWJgd>YN-&^eNj?K`wa7OGx2l^`v`}HBZSBK@a{P25R@c z8t%MiY8K&>@!}Xi9eMFRQZlJD3nj%W!9x_y=zIAIjy zq{P0UA|std*_Qg_c0>e0%Y9|DTuPGn6u2c$3|a0hHEJq@Ed@aMSgTWCJ%jx7DnISb zdOp(G-U|JP@XzwNU%CNUUm1maYLmLSsOcLTy9)Iy{(gAT-z%}|?O5P(1fQ_N+2&%2 zobKOZhpSm4CfK$jT6X&&$H2hJMZCOn(w}XZ1m^l5n~I2TSKni(Ki_7ykfdY=ChO*9 zN2Z{iJ12IYK@0*BFg2$Hz4I8jH*K<~^yclu0gS)im>~gS8vqr z{V68-m!l0u3X!g`$TxWcwdm5NJ-;cn!;jCN`$(tHlc$-z7+)k%YR{lFrL^!F7qRM13%=5_otiFr z#wQ46$b4gO4;G`<8oKgUnb_l3+uW$yTjifHomkV)Btf!o>v}svw=6W;jiM^7OT&J& zxJbrK`m1LQx?|IV;RfYNpI6x;`YmPvR2(mJMJ25S1=~Ki&oXPT4|LRO6@j!AC+VAr zH5QdBoLo|1hFC;nf2$3CUR7}oOd#1K7z7SJGwT6c%#;8C;fr@FCtahG&(KzSA{XyN z&78wBQ=qbgS0U`OJ?&glPjp;~1)AhBpOfm4nIkmwl-*AW3wxe9EOBzJ0P1s%vo&d> zn)Z3xK1Sh7$oV6O#vCJsxK-G5VQ`~G-zc-52-3blu&F<-#t?B5Dkv19Sc|zr7BTdN z1AJFiCslGDR*HJ5((qO|>`0p2PRx#B@+@Dd&GsI$=X)7y%R~l+;(qQ zrQUuq@GgIB&SK*CnFhz1u=U2=>^U#d>apAU&#fEPnGH{})1%w30l;qYy#C6L1 z>GAU2h)~J*^bWUk5Sl)(kaJPd=xW!o@a8+dJ8PnYON-!B8(G|0`FU6GL+)Z4h7l)y zm_b_8*u1zAw+a;Ff7iQ9rAhfrb1L0>$cJ+eL+un5I3uWGZ6dU>6XK3Qo30aUPWtOT zy5{V{Ju zD|`stlZr|ota~v|yBsAjAd?A=>7cFXZP=o1b?_04yjSdTd4qcU9+hq9M6z7@Bqr{I zw2Oh_1>D=Qz?-rSFJ9W@I%u3U<#;y;E!jT~kLYdkK94mK(ZxJt5!q^x|N6kxQWv-Q zZn6~b*^qd0B&WYAd~(oH&hlnmejiFFIwI=};c8p|F?brG_mXd%keC-Qc;Ds~kB1>T z*+T~V%f_SGvRel}Sena+Ws7&zO4>#0l;r@$H|_T*^h2!e(OW%MHm810 z3IUC+QP0+9>u?pqx!dtu&Dbihj&5_Lr8tg2lxlCGdy11#c~N7#WL5~it-p&=Fl9t={dKBg_0+lZ$M+!AQh zS#r5dHoBS$uRYxzFY!^9bS zPYuM?z}-6rGe;PA#aoiMzp9+4l>gE^v;E$9sB`~(ldFi+C_WqK+Kn|nmd>nY!-H+Y}CwD_qRB1hBv;#Mc>TS}CUGe?KzEmqT9BzIKo)u-#7jI(wp z5s8&7a*u&U(Pv|O>Ku5AvAXn*R!^y%J#Hqbx4GLN%258smQHCa_~Ll1v9m1{20y&b zH0k#79bU|M1K+?F+Uz`a*LOc6Di}SgNd=|efRxzC*^RZ`V)F^9CTk(XExS=V9x|Og zEu@~VCOd%UXOE9;NmUk)a56LjXF_G9QqSh9}GY}Y(Tr>mA*b1XLX z*Oq9c3VuS<#yae1q=Z({(Ho)0;+|DHx7$Gw-#Z0Ael@tNRLK$HOs*8YOf3P`)z@vG znmk)qB}=stczpte;S>EhYFX{@@!(9NXomdwJu% zqj*wQY!W?ZT+lbVumBCvhV8Aaa? zk&6=Ff?p57rOg(PN%yl{sxUAM^2|FpN|+L`%^pIrp!$c`=|ATbb{mFRpUFl4-6uLKwK}rNqE(=s8|? zc|y0G*mG~HMwFq?HHLBUafTC_`G^)hxx2=PpMl<{&J>}5r!9F;9!AE?y)iKiWh$C? z3U3XAY;Zws8+~;Te~&sgcd>J$W}ZQPNynWl%bV9ti!a0uf@u%k9$rXwf4`wud!7?T zi8!|yFsKxCy(1%=k_2*p2!mZn&GsEus=MAGBnC^H91%E~2cy{gM8)E#P$VjsIj z+K2d~;RXws#kA7nkIr@_PFyXo0?oQ&$^sfCmQm~64#$K#*XJn!qPhxA;}U@7;&}Pz zbTcudMeK1d)gfqm^Cfg<+Vn2R!!{&5gL+o4k7{u=Hq~L8%5d0U z^kN>)t0of8u!EBVw|T#NG4OdTn3$20L^&S;&hb#*FErg=o3!AkUyc^JT)0(Yj;;LR zzv_ZP3Y=))3--(Yx{b?NVTcSV`JY*aHxz%mgB9QCf=Hgj^ERXZ){bbbj%d!p0HYi+ z=o8yo&x8tJ)Jn|}shO28fpsm?SGG6VDs1(~LPE6&)2Nc-4?HE3cnt=+@cHu2^~Uoc zWwqoF)U#F2R&~6soU4=Zy}URJLyPt+%t8!|?KA`cu9_vhGht)t`05qrql(bQSqthQ zAbhd<%pwX|MW}u=mn3PJC1jSB$Bx2sDv*SJm_tJRJ-`PyLN<`Q8LL?j2ChhbQC;!! z&=gjhZ?<_+Qc?{qCpSm220HUKnfyMgKpktMMppjH(6ZMHrm^zsTRibZF^VR)B{b>n zxwy^E@O3zi3YQ%Ub;RpRF7chTiAHDqR>ezZtE6J7W5YK&FfAb&t_CtQC$|1syg`yB zj*Xad5g2V(Ss8x>EfPOE0ep59NPA6Z>4|*QeOG(xD0T0=l=HcFa8P&6d7`hDYvNbC zq4b15eh&^Mk2ySAE3!bYx`Ys-f{i9_O~{XXo7{k=U%ZWb+Yb4nM3S z8CVaBR1UZBb(HP-#Mx$Zj~k=eUr(+)84i1J2l!EM{8<+cOYjAJdqSUje-yXtiK_5y@;x*8(2THUwA1~y`HG(PbHu=JhAn5(yhy>bYn88@m$VUKG19ec3BUC_uMI- z>bOk+-1CW5*dE$`2kXLFA}O>n{+G8(&!1JF6_N`gX7yVhbasOz;<`PkVT&**6uIv@r}V`^*vF# zCJ(Z9Bx7Ej!M4>dKo)-R)|t2QjL}9SDN@aILPIYH$X+ypiXlL-H*VCq7M~=ou zzT_>Nc-qQLE^G!7H!W=??S0fXXi3E;)Aw0QEC!+)AaK|2rMPq5cPsobH}k@iD=2+q zcD~k;$N}8|zw6mpF8v1{tvF&MZX8c;7pUC%KYjcU%mJT|LgpmjQR5Xc_nt6bv*__Z<2f6KPQ1 zNddHuH@FK$*CT~udmR1a_79$&5ds-lx{gls6wDaI?!dTSeRvz_ToAHyMXUdiVEtUT z8WbR`MO+ah&%K=cQ6o$1n`K8kX#GZfA%*9BFf6MxJl^LhP?f2Xit(q*edmuL*Sjw* zACComw%_%l9Peo&$sr<@OErrjRl^#1Ym{9Sa#WvEnOj^yx&&h*Vh6Ng@!766*+_-Y z!*Zs?`<*}Jv9b_=ZiMRmS2DaLx)E^tz<<2lt6(p<{sl!Em3FBy>R)b_08<$FC#E*x z{B!H3zJetlmgk0J!v=;hEHAmOV6>cx*5QjOam5FOV=2kaj8%G^E77;0A1Yj13$UU4 z8+`o7KZ*~AEp=~vBbbPW$_ZofjFvwd1t`YemJrn{xNd6JuhZI^cy{I1wU*xy>>Iv@ z(GpRA_^7^qPtsS@0;=gd>rPyj|3D+htG^CU7 zPFMH&;7ss0y~PT8hV%h9ks@vtQXUyYzEJ$2=pJLHj5C**1G6Uw??JQkf2qW3zPEfw z{sDP}6w+X?2Y@Iq*Xe6PMkn}G> zEttl@6}9wA-Mc8WAA_C(-P8YG$pj(WbRdI%WCcdH3-_?rz;Cb~tM#d0d5x@uIS1Y> zy<=DX!PvWrNY1Eei_=#a-1*rY5*G$7o8)^dMr|Vexq(X9T9QgzdQA1E?Az9*PAGJ? zH#sRdR8I5)zv3`X6}m*R>k2V|wkdXcyA7`Qx>3{z-+m8WynI^WxWR$rr4|x{Q}g=# zd;PQJ&$o4o0M{ilKbS%qC)S3)>SJO$Odv$j&lOY!w|$M$`*fS-a({4vqjQJ&zsUc~ z|EO9eq2W2SY>yb23;_l=t>jrj)+NS}Fad*V1hgVJYT8kG{mT1aaki;)!zFQ5?jo!`YMtP}(nu1>Js-Z^`{tNO?HaeNd0-u(>A$-gl^dUGqF*M5T1o z!eKgX6;u#UfuU>lN3_2rPE8oOJyAwhE>Bp)ZG*FxqI~3n^(3S1O7)~cSyT(Oil!PH zzKj)Yq$NR{D$HKtn+x~d&9LWM0wAg;{j2Nyp-bpD%`6Qlta&2~?x+40MF=+|egmgz zMY8Jy{(bjS8Q&#o{2yWnTYz->F~!T~7LF7!ytrOxxioI>pJgU(|L=5+mONJdjm;hM zf7FUP&a#1T4@s1Q#IQgh^Mld%%c?T24;^YUn@*d@gan_;1p}(@`^p{V3Dn<9cgm|U zb9EdIPGfI+wHxg!aMS)@764JxCc>fmy^%w)jzj8uPG+gIl%Ch$INk4Kg+Bwmip9=L zs|`LOcaVOAUl8945yOH_-pcv-ljJ~4IfyROCHBCeKu-XZ`yb9 zRyYyIW5;tsS_U7w?<6J%BaJ5L8Vh;mA}8Z)Lv8(`)8|+D(0w$_(z{(?Nm4@t^Gn%A z(5f88-27Wt92mW%`XHcb?^2~5Z>K!?l(vX&Jk#`TCu2&fO` zI%*2CAp!S1E{=mJ#J(k;S|FQ@?pf;mU~cu;bjR#=_wG|v{#y#Xm^w7+KREGwTU$;1 zAHyDV_ELlJAKz-{%J;(wp8G%^rt$*|XE1Ns*MbK4G7!Amr&(n%_bCse46}<9&Z)Jh|n}k+SFj4k{G{u0UPBanQ_vaWw z@wFf}b%zw{GZeXOH5*aEZ&HGRn?P{yuJQ@i&+ja8Y{)VMP%UNrO(Ge(uio*teUBrD zjjgbjYD&3#!z+JQ_mcDW?-leRey>US?gWmhf`R8rAl<^|*Tk2X&~c=dA&|+!&d-n7 zv?qiu!i2^TgGCZTWpXQAJPWi<2>)SJbc6rISYR$wgT{tPgqmw1h08w`Hgbbb<8=?K zFPO>Fsh|{3>+q0DtDS30o}{FcOzQzD!R4wj^|}w~E@G%y%M#K=Dsi)eeb9wC%x5S8 zfiY7%6*e&qc|M*Lhd-L1_ZO5!eGaky)p4G3fR z0;BJ`%31sa$u9EmPe2j03e-m!n)bp*Fg+Qlx{YhX1r7c_t-^9jy8ipGi~gBMw6NKN zr&C5@z(fpd%8|=?rMjApu(IhNuz%!T4Zg4z{ngPbma{$Y-8z)RCQBl1DEct#<15tm zs{aSBdM}`IPChj+plpzOLomfQ93& zL?V+9XO;>D+fPEQ-&PWB^{@DP91 zQyfCifZF`wB z@dQeF36G_aZJ&|MFR~l62|jw{M0Qh4k8fC5paJ?z6QQtfz9iPixU~_Dl*oOVTfcug zBJ3zXba4V=dHbCb5?j%`*#dQAKmAEMNLAky=6#5+OVl#)b>~c#o%Jmo<>jxIj5m2+ zPgY||rsOIC8=m5Ri9pFOAC`0OjjwHm5@^r!*a`UW*lYzn+y^q#8wVfw&i~FBUfu7O zLSwrNRZP6T2u#t~AyO3;aofWV2b9ex{&c8yzLu;!sRcC&rNK$!Z-5c;Qgh-Vsn0Ac8r%MD;=KNy1qd$%a@nHQ3>& zRK}99QPSC?#x9Cft|6HWyD}doA@H_UyRtCS?dQONu z9GB_j*owtWKc5`1D0#z&h-Jy?{rnFGxAA!zI>SMWH|Po!e@gZ1wqR6j82KfV85uv< z;WP2E{8LnfMl?1e7w!9&|JF;3ukI^y%7Bdr_Z^D{#at@^N2db^G4+#!m=BKRk@4I* z$H)FU3#E4=Ds6BBGA+lMwxye{(RG{67a+FEF0CvoEe{&=?^ws)SLcG=ywMi#y!a~j z&g8!IwUybI+lU#JNFDkTJjAqpM>^^46wrMwP47FSjj^7@IxeCKphsd>^G7GbA7O-fk9$Y->KV4-aE(p7L*9|nUxuEMSx=>iehg^#Df}QkUQB|oU9Q>&*I8>3rQbF6cKJTCC zz?9~p%Dr@ro&Cz9Py;GfgfB~v8=ggT!RwEB=|a+O39Dw^J&XZQs zjo|&MSml91YS*WudQPJrQ4NvX&jj^i*Qcp;EQmCxy70c7W7O)^QbN9=N>Oyi(s+VOI% zR3E3AxBq9XSJP+%Ih5cLv}-jSnGhf9fVaW@e33`ApQ-1bd~k5sXh%qm0!yM_pvNmV zQ^=w{GtG%7A%(%G%@pi6<0^Zp-vWoiKlzcA-CQBp_a^S!^G7#R`L0U0= zi=zrM8A9ce=?G%4FPc@_QOTpt26zYVVqqiEMEPGsb3zVm;3TjiMX3>lu2FEfT}X#q z#*5{Me|a^&>8T10uW*P!rgz9SnW;Sz|Cp0&8V&vJxP>(mIdKkq@JMH7h?jcmu$yr& zzipw4K-eudz#f=t7V8rpw}2RL6$PV1qlCbv`=9WZ2|cABr@6nPWMjv8u76z(-Zaq$ zP78qTgzPs5=X}qV@jqH2SEpZY$a&-}c}$HlXdY%wKJ?5y2G!VaT5ODYuGnx*A3K_Cp7eeJFXbi$x=;Qgt98H3dVOqv zl1z4G-glDC4U+TL_2-$gdHC}Vhu`Cct@S4{vi@OU`j*75aHh1}X0%)jHfg;tIRGO8 zyVKs?3e#Ea^~yy|$JiUAYlEACzI5c^H>vT{SP`SKGsO3=d*8WIH~wy}0iZD=FAEtz zw8d$QWPq5Ho43nle@C(2!ov5Wh0gVW(Lgn@-tX(y(^zgcST!KzhH=4-Waj0f+Gi#v zrq|}8A^Vk`xM#TynWm7c0TL_qRSG3cJ`9lRUUoikkL-J#=CXp863=dRfmWVF)#QuQ zklPew8CF-m@W#0+Ykd8tq`doFypu>ib=f_hEKzid=>wQZE+Zp?h~xxTIYVQg zm${PZgErhpx0Zh}Gn(2!NihnaZ3ppmO$%e#>DJjE3ZsX^-*Sm}+5gthF+nn=wdj(Um|of9(zU^eH!%LHLLFg9 z+odZ#J+0?*9WB{+7&SVZHTYIq>N2Ua{x#J)p){wbNNt9#D z9n%6GsUxZ~ps&v1)OYN9M0<|_{3WCIG-OTTWjzdD`_+ONeQu;JQ!L8Sqkd~Qf1nKs zoa!farmTjp2cN{#kIC55la8>ENKb8TdnjScBZ_oTHZgw+}1K8s%omaCSE%mhDT^ZhJQeUcO@bXQT+V{NgD)BwAe_zuYc<(iKR2 zvrxVv7bkL$718RHjN<#*mq3#;A(PKtC+N(Z#{qCah+z0xCq{TMx4$h`War;NSo3|T ziN+wKVO^-(&Jz1icsiy_;WMpABK; z$UC1YU~{ZS%%3vKY>0Sg{SUzcyM#6eZpf*QsjUm&Q(*KtP9wl6#JLh1; zZTE}!5b@6)=d$g^KgyJA9XrD!F6c)2y5BB2)tOnFQ9f$mB)IPRk4gc?7TvOYX#{u2 zGb*TQkpM7Nzu@7kR)db)%WrOHOX%SdyH$sr-@8#qS!3+}q$=GEnMNdy1$v9m-5EpO0#jFHW|zF8Xam-!fZ{JJTaN(Gqcy^ZSq}Y0XuQ7<}Qw)_?~6%0ZsEf@^;K zX>nkBNCdk{vHhDHfcEy-3j5EHIA9pk01d~a*BSC$RyC3$v4Opyi( zMGzP8>v#@K^GL0~&`T-*kUeC+`P(*5R=u7EN%pRO#ZUQ}ts(GNZg-0u8Xu_F{}~;6PQAM}vvc~~ zw>Uhxy$m8Uy$FIY{+hEjG%1M{!WdWO9JT50Q7h}f6?~$yj6=iEW>7X812p}FjPsaO z>HI3#-aXw;tpxjV`1axe=qyJl=y!*I9&}?&yd2$W{9U@NH{6fyi6S_gNjFpP?IC3Z z$~nLFw8VT`@C+yG0y-r%XJn#5d&|!T4$9YbI}pO;^Cz^&JxyO!{6-pzee%P*F66!- z78qAEZ}gk1^^m}Ie@8eLh!j$-`A%|QWo^aU)*&dp!*NKze-LLuB+Tsb2}>I6FN=E@ z?_E+({MX$dzVK!XGhnqQ*i;BD5uZo^t`p>0URsP4>Q{p~2_Li}Sr$5xf_g zxvImgSGPAB!`TiEzBO8?SUW}K@lT7XCJF-YXJK3a!5e2$wXGcfg4X@pN^6 zTf8im0hNc&y1GIQM+auOu#1Rxdf7l@Vs!}6sGYG%O9;Wj&!^Id7=t`XY@LX=O!q9s z{h(o`Bew%88B{XyiwwVes3|_Xupqj|jJ^7c*37oPENWfq^D|rY+k?aIJ28}P{bhDW z;beXQXY_SZkA1n&hX1AK{BL2-XzT}gaT@+50>SSJ(L*K(nc86-Jkm_*exsJX;8LB$ zUa>JFB|ng(>G28g5z4FS>eRKUyy;xmA(2h;z^}3EJcn9mYTa>I^$3F!7A5sCu)$%y$0dOQ)Zd;5oV!Ay##A6)*Zq2dX!OV6QvVEKv+s)KXqceaJXL zdu;lEbkPZmFZ#Kx?}g9$pfZ(ZPbyeA(3s6|%Mi{*eM9Namt}=DJsjP-jME!m=`5)> z;cJ|xBKGh&c>{eGq69XgM8p8>0DHH{y`jD%!eFk%ge3q)wA)`u^K)T;i+DuOIKQsv zXh_$C)`Qyz#}sc`=wvByL9^Fp%+g(Fp5>@1wVU@2ayG(YPgNHFrog;o30QATqtaoi zI{rnA1aNHb(V;I4y1%nmLyP7)iw?dS$i+dT71JjxUcTRhY;a-AwyZD$V@JZZcDL&zE!jCGaLzjJu0{-Vak=pww@ERe}=50e`ZV&O-wG_#% z-Fwjp@TmgFoXw0;v8RB*Qe`Ajqm-sCb}gLqV1ZoT zDRmEZZ!+vTsh1=G@_+LGwnz?*o(FbF1vx~RuWQj9fCjt-Cw0`e-S zn4>k{6fR{uYOdXQEf)-2dQ1&^J>W2rF5~OER`*;#`E=fU;1O5mvKvlUbuPeMa1SVr zPqLZ9##~;J7cE%pXz1)pS|C%b270y^QdI?XHL;0Y;9LRf*di;rDAEUE7bHt}>(;k4 zSbi5XM^p0lzqP3m!?D;5xv_G}(xOWyjvz41SoJ)&!`Akp;)>r)FXLw(%>JU4Ch4<{ zM%~R~;)Yzs<7Mp*y83Wuac_n0-igaUZha@`w zG7QHR?6Dip&@s{JUdFG%^NqJ-;GmfOnqRT1{tyAS(6o!Oza)TW_2J(cGA+_7La6v( zTBMDnR_}VCowFtCHM>v9SsxogOLc=lUv4j7&$H^w=sZ{fU7mC_jUEDoP+^gp8{ zV8JFpV5!^=++e@yJ_Rv@6%O4_vu)<3{I>X@{UM%*!2M^j+XXh9VkYk-R3>wsVc%HL$oy~vgD*#Q)i59Nve)H_?Ggi z017B24orG!K)R6y%PVgE;VDWSFZAsv|pceuMtXqjKe zBaF!>nVz`)pP|aQMZLBDOH?&NxsbY#EUSna83@o3Uav2ycJls$L)t5xm`dMDB+#Vs zw60D)-yk#X=`=eb!4g0Gwr(umq%BFJf~0loF&mzrGZK_+9Vo!Dj?(x-5KbvN)1Ro~ z_G!4e$h%&-WzkBPwTvPRTK)0qWS!m6ov4-wENE$xME%lWsS;8C6kA^769kOS?3uTQE27$S&G8WAyy4k_*ievJ7T9m0|E+ zE)Bazg!&0~7&WeG&v_N>m?28oM!F+)r%cE*tDGTYE2Hq<%R4y5Bjv5mjF_gDY0dS2+n=r()@(1t?y<#3D| zvL)li4XOnpkg}|syFR{ae-)5JDf%#u-;se46~&Y}c?A1zKQgRxRNI<3dMh^J zxy>|Im-_>Y)r`&`NdQKdxE))yYT;B@z3(plDMoZEuyJo0x|#RLClMWyk!W7_Jnvo zC--MV+2k8**_Ftd7JJsUk-pLDV-I(5J!%Fkv(|(GRbPnFoBecrU`9uzfv;VW8Z1?W zyVTJ|798t7IZ}EztLc5FMI#l%PORI9CmTm$e*VhT0-;-PAt-1YDnlzzZ(?{;BG)ob zhY6XZeYZ|aMqp1hU8-LDwOaTg*EzUSbB}h|2aQeo5TI`VJ}1UjoJ-mhQtZ@(7_~2`7VOV3cD+U!;Yz3vC+_NpR*@#F|L(uq?9psN#J`f>9oLix z%}^|Bd5bCg3ke+3@NZ28a(u6d@Jg>~(98cUmK|Z`z-6YiHC#euCgy`gWMUWv{?-vs z9fLo61ZOWipZ9v=)gXuL?<{zrXQHsE`Qvt`t@hmJ4G>bl=Kgxy{v9gTcF(=IG`bG< zNtmah5VK6UJqvvizptePM|%d;&v>~&K`%=R9h%-tO)8!^H}ST#jx71BdQaVCHH_+; ze@GttojB_WtNK)mGOB$an zcyxj>&dDS7x`?bVRk9<6Eu>vYgGYHi$0-v^c(}tsx0qAAeLTbDFpuy3uZj)(L?QU2 zBxf{#BjuU5CS*c*ktsA_Wl!7dcfdo}br#-NY*+vg<4Ong%<&WO2*CP&%y@C~w=e9J zugM7u_I-FIoMlbqny0L;kB)pC`N;9D*pebyeg&2eTezQ2&G@9#>y$2zR{fdG0@BwO`gS)>}nisOf z(VYLvk-*LKY}Gp9A`eJ#*~~H?tKeFBxMA)reEx zp4^a8QEhh-xTq}kuo7NWyAeYB-`X6ql53pQ(Necg%u1g=x+tRa+l+W#x1c+aX0>^X z57yXSnDCS5pX-4do=8>F83KuD+k!OLVb)xpoS5qUW-d&YLMkbfjT8OQxwPDLyoi)z zi4sk8pie}gcW7thq|n`2BEqmEoUW(m(%rBDK!JZ+3P*At&GbQB%9W(jlF7^t-do!> zy5ltaJklUPX0sHS&=a$Ug<>py)A}jEJ2L0FBY9ckP+@2}k(0kQkE#tUywmO%FBD_q z#Er#G2BGeon{4-5rka0RLRR1HPW++ot+3l~V zwa@ZZeD0BuX2juT?v{U}r95-cN!c1OYdEu`rJd9l97~^hkMRr^z2H+J1Ix44-a0E2 z)PmX32oi-ug1WeDF!I6gA|1DENA^ypl6Yc^sS&3s`oTlHXM-9ArrW>MWHxYu`U;&g}|NJEgvW~xLAjx$+xyj??#j1T&Vq&KnHjb9cTFT z377jk&uwI*_x>6XRl)=R;V;0bCO#xbKg@$4uoWl9P~ObwFAE$3(9f$npnL4?O%=Dn zz=j-%oQcaD*7&>zLW8~#@Fl@t`NuB1fz7MiYi->)7WJ&0exPR`@A;PK=pq$)ruLzi z?rg?1z+y}@wagY;;Mhj@WFl%Wu!&M>yDSXQP>@5&Ns4LwnU{3>B#GQOABY3NBQx|! zAQAt~Hs8WFQ9pd!(_q@H~~lT^B*lYkF^ zx454A`EHt?cj)5bdNWPTAj|BJjmKm+OiafK%>6kARK0JlV!xY*Fv*7LPIgR1@@HZNZ zjBiDsN10&a;eADvE|pYnP+qqQd+HpYL+*Pxk~|cBQ1KmJuDr;_XP65mEe0aGMhsRO z%NtEx_7%77{=g&pZ}zrUfIgdr)nl!q}tm_L_0p$w|Fb^Ac^y9 zm%VZCJp{l=`2BqXCPV2K{SqS=|Nljrc;ncu`?uZP?b+s9iPyK1jd#rTfaC1nc8^)T zC)#UP@x{|@%nUj;}9X~L^3Sl$70iW||p&te+ zpyQfsJzgO`_+am@CB=#(A<%c?CPIc&XeOf}I*uFnY45Us=om0lk{({;rj9elm{w^B z^jwaE>`B^YUt9z`lr1<+q1p?m#!zXAdjme6ZJ;Smpqa03V%Aq?>|mV#{M!DAY|$z z-bd={61bbaj%liY%lNyJ1Q|4gC4>agc-D=7ZK=(9kB4_%xA4i97BH@e8 zc_KokmVpi5Z@lkZs)dagsUiuy53ocXIB5TuR`jtcjiM5aZGFQx>|zbLN$NONj?2=O z%rr`#*xcW(^$8g1z}1BjGmksd{__vwPSz2h)eIa0wa16X)0zXP?Nh!hnqwrL4fl)M zxQ+XjlPB4EoTlORb8Vw%J+l5C1ZMG*zQuc0>xiTCx4Mp*_U`t8+~;TYlFKjA(VK7Z zHH-JIPwjRA9vc=HbZEtPTXCP(Id%02XB>IX4w_TlroH@Oft*9KD0T3A@g$``Or9!2 zhf%}XOj4GhnPVzm2$p8WP=S~-0U56sjQdpmFu*$VEeN#@Tx zS=0!WdjC=-00o>-LBad7H@P30`My_mkfamUClE~_Vo~~WOQF3#_2a8zlKcu_7xh>A z?}{R!<0KggVK9i@D3AO)v|@kC;!+AUcogC-Dd+{i4dVFy9stI7tljou=?;?mRJ1ZL z6;{cPEG;n>%WB~)c`>-2xg6`yp5BaUK(#OmM>FM@2D67Fql-WYi1>O7(<{zuokfIB zS#VZH;*Ei4T+ZOfm}8;E>z+ibI_W?BkhM&!YaoGX?sLB-9=@H?;h|!Oa>K)>t((LO z;tb_K3#0H*F%}_cX6fNF=EGa{Rzvn56q3j2{eQ6^8m}G^(L*Nq0sTUv8)*-KK_@l4 ze2Z8@j0n^~#WT`LLL6c;MLY_?iJ(-W2yUC#x!`(|^eIAudn9 zuhRu;BBkqvfidd!pE~cae6rWwJ4!s(J&^66z@KK%Ku1hJ5)G!2FV;@Z?Su3MT9myx zs+bZXG(Ch<+&Hm9I7v(Ej0=kUWeIZBBxCS!A9;Bj63tlS^znI6$jb(Qu}@zsh!hoKx14aw2lPFvLop94GLLq~b*= zk}|%Qo=3(2VEE;5YDgVVnCy*vl>67jO&q*zFrqTg6hPh`g*BB)cpsmXYBk&|;rl$V z)ud=1q21i!AKN2ulfCDi7PP+iOqU+ile|sI`G6y8MLf(gOITKg)reM4)h~tzTGX0u z3=3Kg`1dW|KbDUDZulW1dX=-2)9n`jcI?3PER8=Mysu=r7Tvq~<&S{fzb+i0vYSNm zXu)+6HG3-EWktd-hJh&hzmhfYPg(j)kN2%Ar{m>sgU-!@h|G~6KDZ%>#gf3Ac;T)FU-G2o)1W^$tdTnzSqN{dM7;ZGgU)ayQ{%ofeWfNkdgd#vo?#J$$5_F3Yj z=mC$lO*>sa96HqiJBca1IJ`Ih0YBumL&g>JNafo)sg^6|9m)P>Z=(*MU(os;yg=UV zGWzjI-JOu&52+T@2&OR7OFNfwr~3l*?z)Kh@4G(242<^@@>GQrx8-J^_uIL9K^^gT zl6A8CZ3R5n5;NdHvr3D#SjkOkM;I7-I-7N-*2}~oX+NZHvZS}||Kke#|G5r18hO?0 z6YR@TS?&NsW=SNTB#ffkzep=BA&)F@bsSao!8CTO!H0FTy2=mju}m%hAJn84tJ)MN z0Ww_!g0)6d??y_4d}Ltjiw;vB01je*HXIZ#G-ss@Qt2Q3WdGH7cDX9R^AuNQuN@mt z`gEUp>lfT~+JOu#b|o3Q>q`?3c2q!0j5-@cdhL$Zhi^E3V zkQmnmEP@IfZz@^^@*R)nAZ3Wrf!UZn_19Uq68(%^I_n+w1{)ks2Y|5z~O1fnVGsIYxO( zDqWTmaVm_#4M7)d!`EQZ*iLI*h>mDDSLI?6aC0fIaDa(5l&|jibHu%>iE6VTZC#f1 z=uO1+iZ?D-fb;v@h=Wn@aDDxt3rqVAF2z20d`CFE45#n}x4^otsQOH<*BCV`JpfB; zUw&SR0FjikE+M_bi*vko>?1wRWa%tLO`LDffAXb+{}Z>+!Xb{!5QSE-Fz>uS-@o(t zioB600J(kQe<31aC~NulPax{$glb~0)N~y8OoQWwC0W;Nt`G4%0!1fcFnL`;(<>@r zc0Ox;C>MQg_F(k>7d^fmN5_9{CU#K4bJWeJsZ{qQj7#0skD74jrz{N2Ul|Gc8sIDlx+{9h>2_pHVn8~tx7LotN9 z3vHiB4eSoU9d6mr8T_9ltjHp6B&8);v99|T98V5_odmr71U(3HBpfC?tm6X(=S9h- zTE__)k`0>>{RLzQ!RfaDm(F8%W^nR2?v0M+1)TekzU^(i(#&fuz`fbA@cd`B|30=e zAe{cueOJde@*NA+m-4d3r4Neq@yKDbo9aH~+YmJsa8~`6tWbmCAj5sP#sjDWk3VrN zEmr;mv7U@xJx8bCe&@xA()q+w>F1tq$|6};R%juT+(;*@09rgnf|=$@@cD#@BYL!Y z0isZ5T+bbdzWf7&=&VHV zhb78&F+vLRuFNUrWz4NAudz3SRwL>ws)oWK#vK6cO+q3OlT{+6%uNqiE#HO&Z?RnIC!zXk>-=u8rw-KOu3nsdVqbaHqf~gvEhbYHT6+eH|;&JHw*t5|e zI*yjWLcaEP{2Tk*LLd%{V475iB|_yg8)7Ty)!$|}deC=TbHy(qh@kmkC-JJ`cqQoDAJ21%64uqYFf$8ZPZ#8rBUeuW!sD^)A9R8QbTlt5x)9bY zq)mf#fB+^<7-b{uD`bWv&u!a&uP6A9sN8rp_@udt4Q`P(!bCFHMqJ)ACv@NAoEqET zW%Z}%Q|8gNA3|XTL^o_~{||tpJVCi^BKcmQ5TI% z<1=oJdnjpu`7t~=uw zxj`}uycqG}em=HBVgZ$R*WqHnOr-|%jCdy6!!`6Pfub!rku%b4iqWha7w+e~l!z)U zS?CXb(-jeKl4wCW?OlGg36y>NfxT|5st7L*b^9aqJOaHXR2vS%j~O!1d-klC4 zgoo|l;{1It`2PFE+S&aaEhETtlB&nR^EuTIyQZkSZJm$jch5zqT#jd}Zf&>oOTVpj zV!bv?p~9gr{ua<-!8oxk`5a&TvhdvXk(mnJ5_+@Q4HH6?xN_sZs9}J z4z;SFv(MH03K4IORQm!~Ju&7h_Agy+$3rVTW^EAFSPeW46zzYXg~6UBHKW7dI9A8BfKL`g zPV*5_U@qTn&O=Gw?))9wpM{389}Q%Oq~Atu+M$GWlmIq^rlNWZG-B1GLX2jKSx>1d z(>nR!<-1ckJxf#QF2X>h`XR&>P*vq1G6rbtL@&9B-pX&!H-C&b8~D|9zdizioT-}# za8BK8ZnH4GS+9>t?~y!)p8gkb>DPk-Q{xpGJ^PLWB=H`0wb#&*eA2x?_>tDH-@4VX zblL2C*yJyKh(9JZd^f=X{$*8z!;bSsJo2Kzag5jwHpkl#y}*M2k1>2?jCK6FB{+yy zR~)JRkjeAr?n@qqwDo34kNuv>^K-wGqz{TT=OCCLN&L;zD20vKy5Tml8T-$j(<$+k zBY&@H@#2r=kWF;Zl(R)Jb-sM{FXq$9!9-y}QJ)YqM)_lhHW0NAEO5%gbTmT?@XiP;Iq-KX}ZdS^JXai}j7kkjyzW|PH??8NmFWAscvH>t^l z2JyWrDob;hR(}K;eR?BF!XN)I0=nxyYjwMSu7^<}Gbv@BBIYR_#6|B(V(cM83erP1 zX4pcr98@9+zk!RFF0RW}-=NAqG#hlf^|@e+q`zGpzLvjWT)=7^tMvMNw|d$oYhrxZ zugOHW)OqLP(Zdf6ro4|?G}J+Q8E3#vSRo;WMWVTT!>4VD#N(HYV)?NF8^baTj3Jx@ zMn0aUnUM8Yw+4U<5Zebtg9-RXnTR3H>#WQ`D94TwA@wr8b9HgL876-8k4_{ZK}&sY zYQ*jXuklcVk2a*vcr~O3p#_0g{b+(bkIjXTed_Xg5f`?esJGksK_=YJO!%Hd9?_{R zf>$3-g1uP=>J(QWC)cXA3>Dbnm#m1;pHi$RI*0cmGhTec4bnGOCdgN?M4k3Npr|to z6XWzS<*Co7;ABBJY#VSf8S5}UeZq$85r!G4#;E!h(za2f?IJf9o#WM}Zgr&AXM#~r^Y#8wB8?o3Otey^^q?a%{wb@LGuuU#r z1}HfJae*SA{~a%>=K+#->7e)+(F8cw=%r^y;yq_N9K%G`0lB{D+} z!petif7Guq1mhC0TVTYI8TG&38=+)rrTmkNM~0IBPiYWK5knWZ?GkVyR`o}Y`0sRI`CZk-;1ch3>=4d? z8;mp03q!?$$if`htxr)ySi0ufha5ye-o`vc?;Y}t>(*qt^_+U<$@<}r_tN`hB|dVfyG`KH+g8UcK*ePA#C zuUuv(Y3)vE^jNzQp^h-#2#V0Hj|M-+yhnbuxUmh1lTt_DkstDhof&s|UCD+D>~i^r z1ygNAo+pJxY}gcgIL)vQe!)1()M*R{ET2nvd~KciG=PJRD@53}wOzu0<~lo)xennM zPpQ2SSN5=2L%Mr>KwY}n`&&8F0d7Vwrt<;r5{${NaBzx`QRW(L*E5U6TV=@jG0Wh5 z5aFdw++Q*3k&`^H$m^%cZ_CJ$bScwaq|9J=-u(Iwb8#kEl+8eABnev z90DKb-5H^2jNL01t^h1tlp0^^67moXnX%;V=Z|(=>j%|a^wDAh0`o>ck$s!W|lmKlcK7&Ye(QSndBPL0bf4aDghphV_CIoK5H!PaStRm^w---B z+RQ@non&?CPAt=#;$O}ODnb)0$Z1r#27?$=VHlTZ ztv=vW=PS$V8j&?CJiF&9@p!Ij4|BXRO2y5@;K>3TBZ7q7HyU0tp|LN%&ycxs2ZSx3 zIy$f03(nE8)M9h|0|(Li3Gm{`!ji~@=gtnk0c5kXzGMs{mM%o#xwm$UJF>mFDe_2z z<2z6@JeZWGyv2lZ`tyIPDsu!LUg3B6jm{}fx>|dA^0<#WAyWTH9JQOL{r7Enz4n_cGO>{U^}qzD zGw~AY@KCsf?(g(0Y;;9bfuT33wh#d;{}5V4bP(-I@fCU&J9}6ZmO-E4uC+qNDh==Bz4Wh<`@YV7`M=c*{_7Dkj&gdooM^IQzZ19; z#JBgJ_NOlPYV75&LZ#{wl4$CTvAyXZIy#r9znb2%(>hJi33rDfr_rf+iv#)#w!Fsw z#8BzJq_4~Pj&E|4;HaW8I`YsYHy5m6sVuRij~?9CK$}q_Vu>PLV6A1pSQp(f zFBS|t=|4It(oZ7CE1moM#E=pOzvt%lr_Hkg($N+IdE$TmDy9gct~)3+EZOq zPDmr2vI27Ec@V>m+-$WB;ehaF+qvz+PsN6iRDFuW?rNQ8A~NQ83U2qauq;O{joC60 zC#^mhqk$G)XHQfh7Sa;aWz13o20={wd?*dna*^RL23)F4rYg+WaDr8w@6FJ+gC+v_ zkH7Q=|LckqQ^bo^i@2enaM~$|zr1s)`lDt;u=lfz+RZXlbwpF%alb2j!KZpw^R?K;|A;`-8sk{a z%}~|#<$gV|Kc<3Kl}&vTD_-6FC*Tjb_W}zhcTP@SJMJs$769@xL^Cf$QtNM|t2*xu zvi!87QC{?yycz$z^zA}!yl#r4V zB*kEJ7R_&wZ^t%9UAMPY`CH4nb|gO@ag|3!5JwiLzm_NweyWC{$dmfetPdS8bO(n< zLU_6a_*+-dKU!9ii^gyO%zwrCa!e&M1aSI!e;-aQFPAo6mnG>3>}+Z@9)VXiJV~?_ z=C=!27VxVuOUDb`YB;ItaPud_&coL6PqWuKfGgk>M&dJnU{aDzo6*5$mf_*g9xX#8 z32eu~%s%9ocJxG-58#Toua0=LqBKz@0XnSI2fK#i_eO7p$Z`Z;p2ZpMkj)o6N~kUl zh0h}t^qjBmYI)uEy$qC;5S_zfp?8<*^*fy5?G2jYwvIDh7=&fvofJzfjM7EJA_|ZoCSmM zzXVSXc1KY?bd&i*uYyje7+-Ek*NXd0KwLk`NvwEB|6eTt5Vfd5AM&M$xi#l6`dN*7 z`{nsATL{c}ucHK<-uFpm{DZap0J&DLbgu#llw=X>WUh4HgkjaBm>D$Gj9Xz=OQA@M z7{9ebO=q1QPI0mHFA0PoX**ZQat^zZK|GDS9#~SR_}8tZ0mqeg{2OjA*ur#Qtw{Aj z%e7ERjPGWTN2vO~yKc6XzpZO~(&Hb?(wu;^t2+LU)6Lvo8N$?sfS_71rjC_c^;*Cc zbbOaehkGPJ2u6rFEB<$AIP8b^rAA}AJb7A#Z;BHWTZ{o$K7UT8G-vd|4W&E*cIc@E zJjno436lpYCmz$}`3;Vx!ylW>&sW6Pgx2tVc9n_rrQ6c+WHqDrm=@rIi3*YFv1Q8> z#5JPW@+2&iQT-Zv)ZGhdTveikZh*d9O6x>KXbGoZTxuk0!v=|c2Qsw077Fs1%;F-K z@y{n)QmeOR&-YS=EEIGrxZR+hmnjLL^r*Vp62l0{c;nZ7@$0{~9mw_=6X@}>ze^Bj z`XLpwXHDvQq5gxHif=R|^564+0SVFN;*P^ll}J_w8iZ}*#1~sEfNhm$Vy9`6CWCs`$xY zn;N9uNu6x%IlQr_01Hax>*m8~JBKjVIeOaEX*q`~_*e03$ zI^NBKjund*i-VLPMs4ewyN4JTbhJmg8#O^uQ4~~oU{j>hG^ZWmz+ABF1Q|QR?a7^@ zHL#^>P8i!*V(xzehniA+zy}0%l>L|#x^eA3=*gRKJ&%ABcTY()JzNo$YS|2N1FlSI zR+w98rYLTt5s_NZI-{vVAao-zJL9u=T2ytgvV5t9G$p8E@%;$X{&Memab3C3v8g&v zQ@*ou4&FBnxw6S-Bji~uU^&(5dFvl|o+v;MyxglQf^lZ2WWYg^dbse=8kIRWx+Yw?%=LV>6zpNDnVP^PaAMDI9B|Pknkh+v>C|!U9SY2hj$b9 zTm7<|6Bp$`LkKy=-5E7jp!F{U@8YRN1-)4d{#xS)q`s?2s}JI<0Z}Q zJJ`VT1?ORB)GA0BG!L|2nuRSLPfeO57PAZ~c_-ziw&l5xMN9NqE!SCi&-N1APZ4BN zX=TmYdb*HiLsjWX?D;GYhPYa+{xBp-cL13Acq^Y{)|eY)*9V3prf|BtLT%IFOU+o! z*JRxuyB7)RJ8X3FyqlZEwN9zgy%<2nZuY&e_r4jGVXg-dFaO)x zYth>^%frT47;5V~I-vIHHUr;E@d}-D3HI}zkANR>6(>pulzJQ=3ly3jmRAxjd?`A; zI$zC!h0LQQI=wsKS1C_aGO{+T_V<)ZySA4kqhPsP@hGuGakTbQF@xsb;oHnoTl=lN z3BhpW`?VQ5I7b8YaxDi_lJdmQOU;5PcyGSL`@RSPgeln^f;@&I8O4Zn`#-U2-eaTM z)mcP7LQANJ#(edHS25S4cUUm49vkE+U`8W!@Xg(7-aqdOLGK88d|a3Mk*%7%eIK;b z3BF@{YA+cKJ4fn1_I+n@K(k*oUlF7j5->nN<3K z2Zv29k=Wmn>}-Y*(9p4h>8cPrd~7*3(Hs>7jy901!cd$6c%wfQ99a=eIsVHfuwxQX z-v9WKzB_NxfSw*J`Vo)VU!#M$orkQGb`y z`AKETxzNMN*LwF#r!d!Z4qXe)dN3FZK1S((!kG<|B+;`$Wfn)@xHVlfb9sb9QfJp( zIo(DedzW|}csO_P#jVnakDKnDN+4#;yf-fKMv$=#fErmmW8ChKl%)tma1~!Hj`GRz z1pOnAPWKI^slu)Pq4|?bI`gfNRkyp^HIW*t?i`)@{gruU&J#SfoAZDl<8LM%WV5OJ zt*uiyH6>c+)2&t3g=p4M48gXrb|bh~52NS4uwjQ~9p}EEURiiWMB+Icvq=ie0GwQ3 z!L;)+cz`nL2S2qI)22eeP3zz%-0Jqq=O(R;;pq0c{pXU2Nu^ZV+jb z&L_~zYiNud(S@%VJEoZJzY>jX2_g3)`(>*ncbTt^AWUK|qF|JFG>0W_^KGUIznx`c;TBp9;%9shhD%*`InPU!bb>KXDBN#Wj^o>1VoBt`!Kse z+EqG%fLteRY}i2eNW^)MI_IHZ%js_&zdSa8N42SFUakam8Y#KQa0rzKJQgf@KC~J} z@EkwXEl<5pMV&nT0Tzm^ymGgmo=;R;YUGy8yjNbg2{9cz@8=W)^oshqf$^9ZI&-uZNy%(wUb5}cls=&sN4^~ zEIxB|3SL9MQ#9Y3ttiQ33tz2nTAVy7G>CkEl5cZlUjX8C5a&PXyX20XnNb8k6>So{ z@H@=-n#aAY8_=X)@(wfu?2(33_T_N%&SX$!0QVqEO7{H`q6YKe+c3Qia)AGXj=q!S z#dS7kMuU_*vO;EVpYkbFoT3oyj6An|Oty<704E2In1eER`CmYoA^(V2Sb9HCBCxdG z<2l9ALXEw$tvApBK!X=4o12hzs;s?X^vq``M|c|_o!mxnXC$)*xv#0BflOj)tR)$P zv69U;etF^GPs$lnP$)uTRG8lOvE=@}-wdc$ZAQCk$&iA|(CBIW?@q}!=TmTrhuP*xfFv4-_Smok7mtGjVS?8e zmM&GBDZ{F^F(-ZSDNl0x`t9fuNFtrvQB%`Fu+@&CX8q5QzgdKWE1hc?D}meiE-jCK zwmhL~^hhcxLDCVBl~6I$Ma(rmMWpqUq@DtLNKC62W&RfIp2!tO8xl~3O|OKY6WBFN zPZ0hq;M}Oo6#f*G*>rva)Kk)NqeCq0rD*0;Bc-hEc%Ia_5e^Ja;ywNn3tKOb`+m_F z5U-Wv1KE9Fzr?PDt$yud1yhKvDqUx6`tsR=gt(3mOvHnyS}rg6u$lQM+q^$R|D@-i zR15{>U&}|j)o&m5ho9{6W|{$LcEN+e-J=IvA9I0fo4)_CkR#*DXX;o$8v@{S(2%sj zV06+v-j^}{2BIZoW{A#vrMByra$eVK1f-(BJ=~dJP%Y!%iI4Rxo&0vyFJ6aYWdX+G zO)8p@&_+beZ&yy%L+E%9MJDjNTx1w#hN;17>9B#JwPV4eRp#%MnWDoH7I!~A5eQ&g zMc2JmGs6JXPB`F~uzdbHO2zB+tmCId0NuNo6Y)AqV%Td5zRhIM|3J)?`g>#6J|r(g zx!2uR!+qFF<7;bB{M}M@I=QN>nr#LC#nnvJR?fh=xV5|Y-zU&NdI#!%c5q2E@ZNj} zapq=kGGAc4Yd))hV=Hi6Ol$?( z2c!~RL%XW$>u_4i-<33v5<(cZ%e06*PfNhv%>(ZsnfO@B)p!m=Nc+DYIJM*koj-=Tsy)5{Lo68-nT7Cw&Fr*!Xy2gc@XM#cNylEhAi;)cMN zW2OsuR@i^oRS*lMN;7^N-2AlCwETb=m|c-6i2?2M+QaC%Cm=HFpIQXn55s1{rwFh~ zXdJ$|2+VKJr;r-xO`XR6d(euw4x2lA@m~Obha3%bTXg=jl0i8iXuJ|YyM~o^;0qoU?J;Ug8O|qf<=6N?Z35Kv)bh#@$%F6QK z4wMP=C^~*~#cmHRNV+H5u|KdEef7)RKeVZZS9L}Gr% zm58nc^>IU{`fhNRHJ}C{C)jWAx0?sva3}AEw!(FaZ}(`ZM%*+&WFauuZ0&CjAu-WC zt}YQfo$(Qkr64hR4FulI<_#8t(TaN-jKXkmA&?VyeLW;bUNyP$4fXZHxI3G_{T!kg z`O6lYGlYWZ*%5foIIa%ImM46U+JHJ^FMO;xf@mv)b39V+xd%+DuwUFHX;h*wHy##X zAz!sSm{jJNg^(<-dhJIN)Dn+&H`3+)q(s2F7I-aO*_D4o-iOvS<+5JuO6$<}#36__ zm~)R3@TYofQhN_gvh#Jm?iyl-adN8$GLFIAVFTJYyz-U!;_Jv}EHvd`(tN&`svBVr4sC>`*Jq>3H!2FfXn;U9 z`wFhcGh?wd^UzPS-Qbi3Ib;7?z@?qP9o>D{1r-U3YIbssmWcL))Oj>}?$^rmJKms9 z4nGAFcx%eF=!wAY!v&g8wDY>qt7-h$`IPa}8p=8k*+*|-Or$p81mF3mAhvVpFP<-I z87inDnUkw~CH#WOSZ>0idQU${?SP_zB0bMH1gjf*Kl-_5JA=X;&89v8i9+CRZX=Y= zwXNNb;Xb<-sR@#e`n4j3?VJ2TV+4BDR>$)?nePELU*XYGp^IQYu!JNgEOyAJAcn0P z)?Sy*Jw7pcX!MJGziIovtV5-Zk??I1o#WB(>u4kP-8ThQ*q@A)a1z&RAKFSJ4PN6c zE=V4VQB!Yf;joIUq3M$XBCIH=L(cDWcQ|O|2%u#Sp38{L(CWjuzT=XyBht>NRK@xG z>5M#A-k7yn4)TYBq3Ks#kQ(iojeS}pBS^jBi>4t|+g?6C82VWHHN&|oesATR0LIpuyTNPmKlf;wXar$`tm97kyw)lhG{bgpD zL&gD&zWVNYkxHN7i}z8Aza3`gMu% zrsnp%A9oCDnCMJIh<6`+k`paEoW%0iA~*jh7$osC*-5 zLsvKlcT32_j*tk5TOGA^`me7`wZ4P*np8y-%VBXmgx>hHnI2!PP^%+xrP4Ue@M7g; z6JLhOzKs1ENv}=dc)ZTZ;51eg+MGy3lV}==TH!$+NU^Bs#$1e;ohUR(=rbG6n=Wf5 z3#9)sP|C{*+Y>9or&%@YczEmKcz5Q1nKdE57+x^j+u8vu(l6?+LOsqfQo;Jsai`w0 zwPEeKx989GRNQ2t@jS7lS(%U7bX+Oh%4+vbVv^{DPxxseHk<9OG;CUx&`jfNx7q#9 z-_w%%mG@rDj>zD(fc3G_@owTxLJ(3;&rRNrag9iDqP3p!@M>8>bv=tp^P}d$ea=Fl zd?6Q7OvxG4_3to$2i>P}u^}d|BjHf|w>UaqKUG}Ck*=+z2r4=UB+jQN!-vkjVKwuN z?i(DuxN$0L_|L=)dW?%rx1{469z3J(x$OezaXZ83Fz@hz$!R^cHpgeB#1q~yQe zRvy}~oZjBVo)WBJ3&edR8R$JR!WMWRRes1_TYTr{{=zC_+uQGHX&bR-=+U_5Y}C-Y zn>x$SBwr|-xQ!azcB`EAiLz0ZgxQ%BakvrE^ zC~3ZUdFy?=vgB61vD=#g0yDVj#TVklHt5m2j%*6;svY*PO+;IcplPSCP5mpcaWvhS zooX5tqhkg7jz_2`+oMcq>N|1OsxpS&xY02~!D}^(7+KQf$tw7T7yCK+2NQ5Nf@8^; z+O5QNP9Zi1fo3Wo2@0FX>HZmP1IMprmnuB2WWi04owKdPRmIv9pr*&p>l&I*e4j$t zP`9+>%L9)M(yH$HQ>*&mjqw|N!p&849>FSKh`*Yn$iHyaJ-Db83<&92&A4pxHnsZ+ z6c~Ol+T`-1uq7F(wU#C8znt}intB)?2*vh8plJ&@HAZsgxK)fjo7o8S)r7bkKaFj< zARU~%o1ldYq(@{c7DG7C;e>!dbo_Yu(9ZLV5Cwgt|>c&~)*^t+tj;G?2*^J%gZ$H$4vzIMxnN^ols# zue;)CODWj{f_5_lOg3tw!`Tz8yYuI}NkMr0wU^7H1ZlI7M#TfncCML9u%u>R>CB7V zC;0r|P?X!f=le2>c8=janwCC_%0m_;M=a*GSJA=|Phcyfn3N9Wro1&DfoS*Rw?sE+ zdMVd8)LqKU2P=dH?wG#Qh-`P~nq+*|K+@%vTQ#HN0xWN4R{yh{=up*IGCTXOQct!;+9U)@sgehvWJ#ucg$W|D6?%rudnE zSZoX=^*C=6x=)+Jnf>N>r?X4Zg#v5=Qc6gKmH1@UQ3FrrYfGB!R@oWdfr0q&U#{0) z9DBgb7ITzXzH>Xo@lIcD)f0PFc<7zg+_}2n>*{;2Uj+nx`B={Q^p~{#c9=0hHyoHn6SsduIH8Q^2&h)l3E|}=e7i z4N;rFMDYk}O|Mu#(pj*zHhJysYV>3|9piVWC+NjHWc=%{gD2RZ0rgwZ2V7bI?CXyX zf`(oJx){1`@piy=MQ(rmz&uYp-35cToq|#C#YqaygD!tm3b$0U*tETk5&>Wmpkk+ z)wo#vtu`anAP4x8blV*;R)mcw4Z#zFA|-_IMA)Q|ZG~BcjXdH%IikEdtCEPxb+0I3 zolxU>b?tw7UT@_sg1Il!qt9ryxDsb`%r$&=xAX%wkat0hZ(i!Z!@Vie235v6dAWQ& zNKo8$1Kst=Z4S77R}(**?WjtNIpXN=Y~D8gYvKWF7_XUI${0}CKMTHoGOP;CymK@t zxm)W|Bu2pkRy4o~<99@j*a!=q>aQt&&7BC^iMSkQ^_y$W7ZRA6&pMm=z3s8s|4>f` z3Q;}nd|g^dJWB62p7>lE?SYKd*b27_XYoArX!uOM=e01W^f+D84BdE7Lh&~>Bhgl& zYwlD0mI`;=&OiwX^wj9|YOzyZw&C~g+JmS!n%J*o>4&##{vk0Hif7B|t@~d);u8Fr zHZvr|5hx0U5cM|KQ;14&GI{nElzzfegeL55$w=3>o6Es&jOBzMN(?`=b9wEsP?8`@ znyy=FMY+)mBG-|Jp0vvrMq{<*h9pl18??c;dfE)^+{~s4vSic+%LL(k^5WnL-I*sv zO*{9E-ME@dQ{nn#r|$1_k33%IRQcTZGb{~yW3nU$I?{-5y0J%4izxZwXuc003HfmLafUVq$1!NKmIw=Z8 zTFlPLQtRaH={csmg+~TGh`Rd;s}N6Yj*Z+;=cf_^qBzlp5+ZQAKw0DMCuSUu^^)FO zEOp(o7+C}g7}J>5N#=ZNu9vAN9pJk;HTUGh9#YfQ{ke%rcSI!$A_X%u9;f45Hw>j} zN$6GR!zU3-P`f9Hdq>(CA#4 znOrwkSl_CTYJ#>>Sy}0}8G>#o%HKZ5J*U>qeYBDq&K{@2i}HD4<&lcq+$c{J8F-w% zMIC4KpT;@;o=G`I*3TPHKdz5YorYpe2b;&h>1q@O2Yh@zegH2BM|@ul`S$HT&~6C? zej@k{zQ>Gp<~umT5dSf_sX{oB{UbzNY^)Fw1@+5R1``!#6>qUzRi>6+@a#~HK(*#0 z?#B2AQnv{-E7%v>yYzAsYQ=U<^xJi!*UOjvv7hCT5C~yPzPGt;fsWL~uAi5sn}2ja zj4rU%-Y_tYJo}*81XoJ9htxaa>6M5gLzHT``rb^rq^E=Y_Yi3+hzqT#ty0D2xDFBr zQ}wQ}#C4I!eqsQJV{!EuH~n*N*t4&bp5A{o+6Mpe%1FSY1+ZdVxv91l)ze-a;su7+ z(#Thy!DJo7o?V`ep6-ytpXK5R)>tT_4n}C%*t%$FM+0~{vd`_|c-s_)B`3tQ{}*oT=YQIlWAy?$uZLb&ap+Y#jmcs|Xb4Mm3CL3xT#>+|02?%|S$D z`qK5&KXhaeDAuO|vW_JAG#qAvgRA|)(uI)^@rE~iXRV$ zxxVNrrZ#YQP@=hnzH0<&O^zl|+1XtSMcGTKo!ub>tM4~>@{jpimbV9jw>$dzVAhDz z80KMZqKOk1(&f3!<6}ABi>_;Jy>dGmQ?2$fwb9S8-qc7^MRuVG)>6-nAC(X&LOsa| z(|Fwvus}9U972t${eQ;<{J%)vW{DFp1CON$VWeD4d^_T{&%*br_TG2GHs$0rD8K%E z*g#wt%B*shnf!TiS`DkA{XIOQ2qt<-(6+o@GuE*Q%9G}t* zi~bca>+vh)A`;tXU#vc6aZsUOG{3=-fdAuTsJkW#WgOmq)}x{_N+l zQ(~*GhqGt-@VuSrqJ6eUT|+&}DHgTUU*IKDfIR+}+(Bf&_QB;KAMHKyZ=}T!RD&?(R;|;LZu|?(l7%x4x=V#ZPu; zd%An>zPd;1bY}ikjt8r+XD=ad3XkLeSpbW}c~PsB1rc#^%0kzV+LB`OjF9)|DXGFq zD^VK*iutg!93Xsj;Nxu~5B1CrVX5$l>Dw6ctv|lK632eyCi}x8@pUVEn=*jemtZ=i z5ySWN4~d*yiPL=C%vkww#m{MRKTv6CPHW>_5~A3Y)U0Dk#t9R(voL}|^P13KI}I-7 z59qxtRX#@fz^o+--01FF<;9P9wGEM9n`n=*Yawq4h1wCs!pN*ag!acA*Nf&1Utr7} z-<+rwml5C${%tzLDG#)viR{o~-uWNAqj+(quc*D~V&KhBbB*YBkOTtCh3z*@y6^`0Yz!&#w@f@E06%!na4+6oLWWdX6 zo9mQg>Vz-pWPDEM8}B6rrj;ZH4K}0ma>4Tk?W=Es@dZJ}gD}4sDNoh^g+RJ3 z=b}BV1ir@Fp|XtTyAjW{IWrw4o-oe&_5XR)LWYy_=&vu8_F9}l?+B|+`_wk9OT>Ov zDx+OfO@HtIQ{h^e+OF!VgjlMYkGamzjQjowCyeskvyiNKmB8z~d^8;2&V>aARG4%> zVEO{f?S1O6R`|Ps~ zyk}rR-#+oa=jw;TIWB|xt8J!Yo|I`Rtp(AtXkm;doEp~h#A7~Ozn>hD zyUmQi*u){kq+smB@SFgw{J-hlhwl|2?;5ZG1Ac&GAFkfs&R*5NCzw+8&9L4yZpG(1$eT_h$`pSp0Dg>KO7bsB#_&`B%%6?KL zif{Q^!-c*gY5TI28$R$6j|vfSh;eGP@ATnt^2U$-9r!dU@bv{0O{p zpQ;~ah_by-;^oX>xN?!$(PadNiLTI@ZH(|rY&-Yl>3;!aiNkLjQR5}vIa$ozhGc23 zBmUDZv8L^Np8sBH*`NLLh02gnwq`X7CNOmx>n`ZcMONGOyv0)C#>@P2Uc^>~hSJ|T zkTvwi6S%INd+<8`VL;480wd(d* zja@r_=50fJLUN?8Nef1$kGnZut#A9o&*12Q$gra2}`x3sA@ zyHSl*5pVqAGHFr3%*kqEU7Tci2l`QN>mILO~o5Oy${U46w0fQIp_#F zLniupBK_H=)lnzM6mGpB9yau3$`xioj8F=Gr#Q6)ESZqOco>G%cPsC*FxlUO9;66U z8k&@>c#o(&uGU0Zza1Zs8lFK05mLh{BiYH|4Xlnif`Ye>?mJG$_H7nGR-)`mb6Qz% zQY2-Ezx(|^vBvXvy#Qy;`QI6>@_-c@Id3hBIx{@e!u*9tAzDYfdlQd!hQjGb!p! z@!GLzq*agB0l&%TcMFbL~>avoD-!pChT$NmW(OvY3ogK2*_;WtaRi|wADvOs}b_W6-^@yH$9f(8r$8ao|y zJK+B^B`z8D%1MawDIi=jY}VadSB4kOG8UE2_~)C=e)Jx636`A>Pps6i*q_edG*Vvl zImg{!_HrGLCI-9&e%@J$kNxCszUOz&Pb>OUK%s!?8~pT5%b-N2`wubm8Swh)#@&;z$4|Ic(;5cM1;C4}Ce}O-5v@9s))L8g`az8qZG>8% z8N>Hz(u+xRJv3KBOK3Cs>%0chu@d`JW;W=cgahv9LO}q3pvL`Y51t?HCvYSBQde#H z(f!KXCFyGGJ<{tT#w$15%QdN%-FYNzH;|4Fn7+a)X}TM}`sb&0&pGUw6XuIn>N|Yp zQ%N}UZnUQCsNZ%Vy6_>}n+S^QLpTd%X64gU22#jU&X$Dg3wpD!wJvk2Qj6=Nxi%l4 zTn^688f4wDmZWAWfHcYHYH~xO!2;G8ul8MS!}3H{!vyaZ{NAavm2zotTu~{jqv@=XL_sjErEY}}QXAU|}H#1~{iNMbj6Kj==KpVPL z&VUvA)+l-Sd;6+CN{Z3;BW*~n>FGhM&92Q(gP4Za=mDp%G(oQf;t|@s;g!fs4fqdV zoe+l#KGO?#-@Z>V6}6)L;?nf_GhmPg#~+W9Y!r~j>dlfzt1CK)f|Wcgw~o`td=3T@ zG0#r&wD!r8yeRjXlIW!C82)Xpm|_QkpjY30b4B?soYCu=w_g*i+s?21!X>ylDz3T} zgw4-&rkhW}=ee$Tqn^WFL{8M9B`Ij_H`(N7PUa(X7kJcR6k$i$@YK4Pd8R^@(>J~Mbn#4JBDXP25&y&|F*Q&5m(hb4$O!D- z#ryzR6d<>oZ{jl0c1(2m)4qt$2rJl>UphewQqg=V(KuOU6NAydsS42cRPRizGToZk zxnk9!W>J~k`Wbv_Jj5y$(;^~vf0VnuC!V5baJamUxTnn<$GM>+Q^M969LLEZR@D7> z96tQYChtHD&dn7`)|GRA*HVrcESy?(u<~<@N74HESy)`c&(2eKhj!JlPeitq@JhuoKU^zHSQ?tb*b<*&M{+F=Zqbl;P3VurR$Df= zYOGqOhFYT?negh;ZR9v<%|Qrfofl2jvJl9JhSz3QBF<*$>RXfaniJR?oKSqnsGv;e z9hhpC1S7UE#if_KY-VJkR$qe#Li zli|4x^w#0fkXItr8T+_?8(R^4O=3&XX(DPvlBFgT^+aV4IM7BVB?^~Y%JEiN#I~x|F+Wv8bLySOjDPMJ( zn+KM`#H0P8ctjCCua*Rw1mDRWEWL<^{z0Mfp#jEhd@U!@NSy-g$WU-pe74q?3uU(I z`_!ho2Ro*^tqYZP=on$YDyh{wXl z7CI+--%HUnV$I+PZ)Q8Rk)rVQq3lMh_Ji)Ld7%;Fn8=g4WTEY;Rr@(og#zw z8y(p(seBZ)#h=z?DZi~<=$Wr1gc_^X!oq#@8L7-*Ac$eBC2(Fn%Q{Wf04e_fbT&Vp zIPECbVBjE+nTK!Xdijj9zklN9Xaj;?DVqD1G|W=f=h#<)8^NkJLBQAGpzZXOw;NS9 zK*a*t`nv?-+kM{VI9(G*>~bGcWu5F%qaoBJjs4o|CGN@|T6DuZ)c271ns6ha^n6upUZbwdI*e?EYf%aKFpZeLcR5XvOzX9{F7xX|q}4Ym;a=YXoa| zW8g{Rlf731YBOP%tK}6hmG^i^(wMBv#kTsj=Qss%tvzqxA#t+X&jk=eS=dD9Cy!gt zJ}y>VcVAp?-{ebQ#I}bzul-gq&JaOOYetCv+9R>quP+tSZk}(aDKuu<^fheRZZG1CeUTRA>qyt0VjBMMh#HtyI%W=3TdHjVj*Fk z5@hL0GjmZ*a9;9&e;72Nc0?Te$8lx_Jji-r-12&mm1~&N#p(Rv|C5Nrp0j?Y_X5TiHqAYe1eCs)4WF~diy$=U5=38UMvfj{{?UYmsw z#l`Hi(spKK}QRthzJ}MsGL(#p?q3_~tB(6K^>*J9vnrOwUN~-1@lEUJ!!` z*^r_w<(Bq$2WxLN%idY{@@1|3M$b>gNDaIGi|X+iCSO%DuK zZa@(2GWAXxkWOhZCY-R`k;3|}7#Pa-A?BeL!r5pog{&{n^dU-;89psCdi5k2fmZ~% z(p#Dft@^S$#+zb%Ij;_rul30vGr_-WPO(VM4R2UylmJsj00B;vhGh>#w{7xCG~QOe zH}zO*btp~{h&;C#gM@4WkTF6Lp5?{p!v5=%i$>JiYGsrGW%%vr{WSye*%oJArsSLv zrkZv?OpK3-eP9^VvBN5$jJ{Hy4vB=wvA~!krmXP;+;a7 zKp7rRiP&ie*|NJ1o*yo;Js$-JA^uG8pa3fPX{_7v{CgKCnh;w+F><1(mQ}3*_m^K@fhL6h@OPE;yqnE`1d4g<80Itse59T{^h<&CXIh+wllOO+5R!`t*hl%OY3|iTTdEp6=3+1U44Nsb zLiguOg2#)ex3y9gNqme_roOJ{d4|`4VBW9^*!ZibXs&-c+)|U=2a=xi>F|FKX$``` zNZ>cg$NypXN5)pWx7IA#)>Ia|U5YM>{N<-}!Bk{9CXyYzhT<=FmV&gAd~Ykn{LgK; z^T3`{pxz!CZ2DqkYB2CmKyR>P1w4=i-`)}*_ELSq$kN{QsU$v#g4hRx&_=*xm!=io zPkn-4pocD0DffDN_oSkUhoVAB!{dsY8X;vmebn5u0jJy{o5R?#@2E&hQeLRzMkgb# zTq4_$B}R1E_JXF;#pBk4GDVr9DMPO4@1z%x@N}Q~{uakqF0f)voLgszV$14$&vPwO zBf2_naFjzV$ka46IXf5-RgVb?{ZC(p}*EFiw;5>V6uA^E7; zy#}8pw8Y$luoFSx!@3f|0*MTqhTb`(jo#>(l|JxsU19ZYehg~d2=S06OKPHbD6Uz@T|!A(nh53H!nT;?Ni|XLaXhDVjJwz=8wAy zRaAwxV~bzCxpz4&L`q-hmYZYg&jKy?0B6d<&$%Nh3Ziq;by7CRd-0uUYu#lAIckl; z#|WO$U0kNK;O}a>Jc<;mE@X9inVK@@bbyMC;TI>I-c1Oicex;!b`GVpWL3_dJoaOE z4Q2=cGAh*KPgT`|fKVWW;i+H#Ul2i3sFks6ckCbdJsIlYC8 zeJy)Vho?WBA<-4KJA1Hv_Z;nB9kuf`9qFqF zZ~3{u0Ql*d8cDX?_aAvq4`TO%9D@hdied$seFPHdGbpCE-EG>=$zN~Ymy}&O%xEQ; zKFolMca`op-tNg9+X8=B5q?ukUgn)_K?5&5ZW`6}=$!k;J(rv9E%C9ECal|@Ra72ZAdDiV2duCenQh;@2s zk|gdQpGwI$U%VhTu?S;(1!ynrcyiS223{y4OtoE68fi~2ZJ-RcJ1=T~k(xK3;Kz=Y zjOQVfd_yhGD=ABmwn*RcRPbNB+D^Bi@Nn6)j7Z{$M=m^n?O2eW*wgYPSNjo%!$efgFB>K6y>4N(D}zf zc+0QS|W0vx|%%xv=zPDJ#ST`x4eP8=bimmPB zoN9pPMm5n4#D9EfoSvSA`{+a_pgGqOooo|V5PS_HTrmowAzS-)*>@pOFDYK>E8$*q z=zIFgqjl>jOr7!B{O_W<%Rm=dPPG$@%5N!0&X6C6#D4IPc_pvk$zx=?g`1phT)H%w z6hSO$30Ql`k3(|ZUWDzCEXejo2Uw3QRF7-xag}A}Y;ll@KoPSjJNIfX#+|;)#7KQg zwEoKTXH=irYHpAHpx}0C_DXZU?P61Xj*&Kpj}CWF9^#MqB{%xnH2$q-LxBod<5UwH{_y=m*bV%nmWurk>qZsCCA$Ipx=<27 zkWXDQ8FrA9itl!~$z=P@MPM|jI_h`FUdLE)WoIal+O0Dt8>>XIu_x|o#ubUHy*ek3 zdXfpH4B6QN15hCio$(lVhGcG?8@oC)!zn*S*$uhSD;7ZR`*dk|v)UX}l^2+sYJ8eR z79%tisr$?53Gn|fLi5PJNKVKdLZ zvf`#ioB*|6e@bE0*l=r_1rD^qd^ObaP*G!yO&O6q_}+o136;3l)d@EPHo4yn zhA=HAgRXOCr5v)Hzd9Lj5?9DQwE2mSqDyyl`@Ux&sRlN|M;HOcP`BUwjl3VM`yt+>y>5Vt<*2 zw<*Eg0WS?=&s`h-As!QFX6?&iH?{&8vK0-wxF5qWhI)`2y5W()hKUJ#s_=p?{t&&V zX=pg@(z%sdpdBtd)cka{Iq;^p4Kb=Ccu;ZV%Orgxdc7L&oc2%1dn3;rg-sS{u)p{e zE2d|FEq8HPsky@J(+6b8L^eDvu6&yCHPsO_DIV`(^I(g8X;LIcm9a|iMP@Hh+b0yb z>I^WK->PrUDK)n}589wa!c&eU$wkoC1fQEHnIZ{$PjyRG(?(sFX+F}Nu9~SOGenSo zb5JCV6I6Z1bI1SXwtTfcr-z)N+kp*lGoC8=aWLDo4Le3sy+aj=RUg%QSEPIF2Db3v zC4^!&E0;G;maM2xhZjv+euy|hoj0BdpWX&4%UeW;E0_)hI}18kwbi^Kj5u)Wlbkhf zMDiiL)x68>P);q87wSIwz0huolQn5ZvZY6l+v(d7St}n(7DE<=UlEMyPOlL!7!FmXpq#s5owdAK{>>0OtuSM1X@;oYY04qw|D8J1im&q$0|`lUwzzX0*WUb0oNS3 zp5D3Nak0N&PP~w?lJpK=^f6dn>G^QL%`Uc{vJ?v3GPe+iZ)1Lm)+Y2E5{_SnG z0H&uTLD(g{R=}RQe9am3+=KeaD4m1q=Pc_POi0imk>o7L!MHU!9;zob(yLt0BT{Q>o1{9^}9G`wW3`;QcCISfabjtwn1AD zUjlOiAW;P|s*mHTv7J7P{;r&R9L6GWeTcyiz5eG9ycOnn`@IqU5E?(Rqts~g$&nTX zU>Txa+h;_wzdrI$^K;cdctE?W@j_SZA8C@z@P1*D{F@9Uoh&; z!0}HSQ1TGM1?zyzTekzc8t}A^79;=dH&@3Na5(Dsz0QCKSyGLou257T*)-uT7cQ*A4Zd{8w^6I`r)(7yCTo{N@+K-m8 z#m=M0<~06kiv&x?HmcE(S^`~>Zaq9@WDp;rvTa$+)@$}k!+{a}!s)scpQ#~_8gDs6 z3flGE_z!OVCscvpv{Ff_HAFYF)gauzc})0!<$U65vHo_aMX+iaJshWcv6yNrX9)yg zW$Xs#_SQ=!9xk%j!g&3wttv9?T7dIl#&|g2%-|b$+O0=}idqR_>8zCe)21VMep1|` z(MB}W7xm9vlW;k}qi4S$V_#^SjvnkE%CIbj?i>jIVrP3Ig9XTzLQf*=(4({9W4k2T zt8Y`kbEPbG!zvXFG1>5IL<+$k0T28^c%pqUXsHe>sLpQ|nC@5p+?4XrG?@{e={s>E~fQN-(yi%y2fyG(+_(PK$WWC#8#nTzye*<_iRS_Z|*X^A; zP>2Oz;@pEQp!=I!e?(uJtEkgoNePR7dSSqAnl$Rxdx2#4UYaZQ1hQaNQD9Y>Io9JZ znm$~1^&TEm>EPqn@HKtD8NmBHLv+@N;x9#GL4jK)rS4c#77{mXqvf()qF#52I( z<{uIm2b*PpugX6VYBoSA1K<)P^&BE4}tB~86d)4|K@=VH-7Km@60UzvB=dv#z) zedXFOJEnvIM*Ze3LL_wyE1Hq&_xBI`Q-iN`v98QUoad^~@6JeiM`P{`pTF+XbS(Nu zJ2C=?+Z1K9<3F6ZGy2c>7;n$%mW7+mL4mN`b!)=(22K=H(0p(PJX9p{o81@E0xr)} z1-VEoa%|a>pLpYeGrLB9hy@+OY`t2A7KpJ&8!umha7z!jMur5CBATB@8c4^4f-I23 zVN`dg_SfzqXm+Uqs~q!7h6K9R%^E!t?4p(#Q2&E<78MFad7~7+XspBJIl>lF%9Vz# zq*iYCg9$K^H4Ac&E9?il8%&M*l}z6(rnD&wtrxuzxnpys>AW%f0#oxG)_)FIo9z=F z%FF8_UtttWjQoSRI*{@=C&G2rSp1WQT4g!(fodtY3+Fok>r22Db|#$>7mAwqVGfymgz7SgQTrm7MiYGn;v5-@)B}_QA5*TJhkSAZVrFuJm+<~x9O4K_X-6yFFPD=U8 zj<$LFho5sQ5N)lr&Fs8$wjj!rM8p$y$pi0b4x0t*1}KLkQoeqs+h*8#mur;t6|(*p z?k~zIy^aAX0Z~MpIDBeFyHem0_KH<~^5P6!vge=XrY7)pnGID@^QyoUDZU z&pKna7fVm%l&KR`#EHOxf-2`w#zvL@2kAv#xek3~)DtIzBO2*(TgV?XbIf9rkoX`i zeP~;XDJg@V50z(w_NVS8S_qs|59oy4;gu7e)F)=)pCXb=v>2Pq^`}^nDcid7qH%`s zzc9*ih_0RZ1&d25xEmVk$%$p7wGykyPM1bY5Zfd(H+vpvX0^NEQzAD~_#Z#E5lqi* zgzMQn{rXDNk0QmCW-1!x@k)VyZ7M^Pd{LBTr6@1;Osj*!POU3)AgzEv86i?!#zVMP z0_4=;QRrsRvxaEd^3cuVf#~T*Psgki15~|(xnU#o`e+>+3J;EQv3k9OEgKK`evt?w ztYZw{^S%816lb7m4E6*yM|ZxMRKf-B%o6>bB?3xlFd!{sc^g%NuN}q;H+K}+v2glx zkuE9W2_zm~HV}jm(O)8~*e? z9{2S3Gj{7Dx!JxMdvmS(=!u_;iLB|+(>`LNCF2vERz>ojHK5UfXoQ$JJW=MD(7^N5 z%U`+|-Q~@R<5mAC|LzQFxUNQMut$p#jZV67;?NQi%*Cx}u*PvWDi$aC0SUfv#UeEX)r7|1psS*i0UtL`dg#6n zmM|$!G7kse&!LB4A580SR)Eqys264oYrw#h#f^i^F0FZ)q~UvQ5H0`9jKI+#rJp?L z4$8#8=H1Ys0WZq$SIG_(sl#p%Dq4{`6WHY~NL(2(nL^r~d2T&Z19ZTq-fNadPsK6G zIeY|{B#$-{6XZ>^E zxnqcQq(pe+3v;kd^ow9ZQo%k7Q>wkl4u7J-hH#neQ_Ht2B1v8@0qwc6!{Gh`xyHtHaMJM-eeKkaXZ8CW3wpQo}0mN@W0)8ppu zQ5O+MVW5fugtzfgn)cS-ko-=SHNZ=8T@fbjup zgKVKV{k_ZI?l0lR&|gAL^oqe6mDP|AJ;ism9u2qT%5Z7u3OLmSdA7uaFoZT{aSN~T z?%A$kIZ(ePGgfTCOG>(*tk0cahg4k-6`)JeNtfEAYt0LQ34LMucKLK(8a&dYj# zePiQ#3uZKWxu&pgr0CbhMtZUQTUNyrP^_3AQB>-ST)P$Oz<`CV)<$I0o-vTyHWVf_h9Y1Um*H@u#xKyT3IED+a&7m>0J6J>I9IKPch zfCqZQc0UYrJ6o%)^LzUV&6mUe#SzOKSp8qDx}2O>RLgeZ_g1P+HhZH#>-5sH@+o5B z)sx^ZOi|zr7GF&;P-558vWR7hq)gA~@gANb_ z<068JwyuD}2MP{1CLfyGv5Y#Suxee)+a@dv^F4!I)%a?*gjlwxSP~}2?{)tW@Y5{t z%$T((Stuj|UWh-%g3+V3Y^LUb^c5#Y>ZK=}rcIMj)E736pN#N}iOIl;gPla9Y7#gV zC~4~Dq!(yiMAV1q7){tYA~=VqkT6S@fuX!xgNiRcQ!M@2g68vYT5-i z%Mn(Ie9^PTO%IUOHmz@}8y$!R${WH`1}Zf8ebK3=-TTqhz_!Dz#rRc87gi}Xt9a|N z)g9fJ<4BvXZ#)zqo0|u&J>dU72d4eS$^vJMcA2ag%|-mpX?UK<`LBO{ZU`*!PeUgw z$$KU@#1fAd5-qIRqzwhX1xgZgOX`O5AOUP;KMbC>loBSs ztp0IIGWOVP-EieEIAc8EHS!}8gCD&BBUJ$|mos1(T~B;kN(pOeF=@XVq`%JuKrUsY zF1SoC^l$idOx|IY(015BDe^PI%n|2bl&!pS$>C0HRj<6eZneHWtpAd7ZG)cUj2}D; z{kFoH8G>;!SV*nJos3rQX{5QRt;GEZM(Qs6<46Iox?Ksc;RqlM9a%r?tyiAieSi7S z&WcMSwaiEV>`AIotD=kn*Y0`OZX|&Sm6Yt7<{Q{Lqxlsh)m$@apc09)T0k&9fR4aJ zdss70gUC7fE{fsf74R8(80V!9{HdU9^2RGFAds#=1o6kian20>IKVwKub4&!BipV994FbJ&UyPLyjA=pLH{R?&Y-~aK3@Y`Q+rX_a zyL81#`o?`zU&0Y(_l2k-8HCJ7TMuN_}3+0I5 zvZ;FdaJ3Kj8g!JBm|zUXsjz<@z+~780&J?JKuTOB%k#|=dYB6bl(FHTb!30aUR;1u zhfxbfb?rQX2k&j1dZig4$dU-Dke&v{a{|P%Jq@uvjK!&`v}($%uuC4UT;&3p6f zc)m^*JW4AEpjtZ4M$y)qkl$zd+1u;hgicog_T)|(aVabrb#`_w`HP3N?lW>LPA;r* zd`d4K9I_3E%2=Jd!G7;*KYg_da;+^N0OY=6yrP%8#{$+^4`MW+FM!)4u`y{2S@k1+ zXh4m55OGujX-FYL$!h17FyX3z%NW!=Ny{pw7kCNrV7$d!8X*rr%UElxt#Zn7@Q+py zBa>NHtw19;;6@6uzM6aThJODpGsR0;xO0$?3A9g!GRGt67pBf9>F3YE-)LwXY~j@x z`NAZf@PgWfx*`B3rqIv-pA$^~Q6ljC{2lco83 zHga9`&-8aG`GwP**awfnpUaptKgRJW>ff4z=vE3=vm<~uGhCJ`8kd(x#0ZsCY|8j4 z4^rtU`FtOaX>HyzJ=5j3K=?aqb}auoL9YSIgPAzMH-> zwIYO%Y-)_-x$Ip|l)D1WQzMm?koCFA>dxkEhmg68)SMyy;4^Oyx9!i)Kmu=|M2FLN zFC%`;x0o^cUUf(w*Q!QoS_Zl*=!!hQpzYtcK13dv%tO{d5ol-t-o;Y}XWi+YqrGWp{u^Dl?H6h8$K&usPS=xz~~t$_STk2%P3H5X%9?oaoUo>>4WkpP%vD;r%sZkxJm$8CaFuUrc~#^ zkRlvb36CV<9gJ)GI?CF9Jwrn^-LX<&un4`d(W#t>A$6-)YHRLylWWF%hg^8=%{2uT5O(V1~Vn#Zqa1>9cL`(^dXJ<cC?Ql`SuT z>isuW-7}hlQ21ZB{v}(iid=`<*is5@|7(Q|-7E|1k+vj5*TbwTA%-)6rLCLkTw)>n zs$t=_%cA0kAR#3+YR0|H0YX6kwdGK?(S0ymH`UOwBuC#-pD@tUpOY+$=!-4idM`q! z8-yckIo_qw9Hv>-{@M9;-P!W`ulmL)0FQj^7vMK+{x{D=fSIhVj1?2=l~vbb@LwtMY2aCjWCoaFV*%aItW(f zrBc=SQ=#kc2G4OS^76YS*flFo(A$9Msw#k=J^tcRhb}!b)S^;t;p~(jtbttaV7Y&i zvwZE&mVE{l$4TB54m~c5_<39NAq*<6#Rmh|dqWbKjrTzHpTvmN<4@7{$|}Gtxg)qg zO4U1xDs?DAXir3^rQPeol*`*Gl*kM%pTJ`7;emHIh;U){gP`%mIqtsShu{%@R4w@= zTzIve=eGaN@3;0tT9*R=?UXdG>C9LYjIoQ~N zAqR17zfJ5)pte!ndenydDBVB@p9A#eFAj>d|ItU1pXc8alm8hVzVqui1d0WZ1~9-?QnOu zVE8O#@%N&7$7)>5gF$EP8R(9?Ew0=vBzF><01{@@TUEcYs`7wQB}vXf2hzR5>BPl= z4-wZE`%iIO(gYAyk4M<;_o;?39PoMbAsSNeSrVRf`8E0k!ma0^i3$BzwbXEW@0)>M-|tX!!( zLK&;S`Hk}tKY<#*6XR9JB_0z`A&NiR9WJJLUL0|JvH0v|*WFMpO*2iBb*hK&D7#bB zYrh`Jw(M%2D=L9RuEl8SA}xR~YUv3>jW=iQhx9N*nHR3MKM1ZJaS&GMN9_J#nxt-2 zf9LV;C?!>1}J_?6;gox)-@BI#10 zxbW~h&Q*Rmc&O;1Nhp;Cmz@d>FA;=2k`%ihuBI;2LCx&@)g#oaE1a|}vT!F&K6a_$ z*MbrzfPRvr!S^qAzG6Wd&VKT1v@_r8srSZnl$w?S?xdTm%CGzBKNhTuiw>XwHJXN* zQ1%Mp$=IN9wLvxYV3e-|&!rwXOjd4cT27W&5t=`{jX8wX9FX?7_4gnwP_rBqMSXWB ziVAl5S`3>6!8bT*o_AXru|K#XsEKL3*11%WQQA)G&!a*YoHCjv)$u%T?>+^yuQn%g z>3h0vctV!^>oVV;PEX?&u3@yy4Kc$N_PqqrcXWu}|J^$~@lmF+2$fvAT%onL)MxIS zu7+^dz{)c%Ls8~bN}hDK8#dgPd$ECC$JbjhlpNoLw7%#2*CRA$FW-vXXy7Is&j`&h zmkX0Eh^IwZ%jG=UK?vAjq#1B~w>|8JAQ21&_9B98^pvuYs$5P9?;5z4-mz-si+$px z>Ym1S3NJ&bkTybhon&l*XQI8$ad;B16|^YUh+g7C3`$Vh={E5;eh4zlSYjSK%<90` zXf?gwL`+0@3X&zGAj_g=J#B`-7=tftqm{fV&oLx!nw`PwN}o(pgR9mC(3XZ4Iz3U$ zV=n`dS3NQ|q3rpEgV&+>ZSc%A?s;_gDg(s-kVSmzyb~)T^uEbX=?uJC^ArkXGD6l} zNY3;}*A*~%*%g=C7*;dZX8c>wjUS31BJQbIze|_evXa4X-EWiY zfe5-@Yu;gRIhm&Y(i8d9@e|Sc>9hv5wCcp~8-KZ`tzG(!Hq@Cc=s5kZ95URgSbA}8 zysaXg^b=uQX-lzwk8VJ#Nk{wThl1j`)i=`5=pbT281|ueldqv4>)N2&pFpcmY`tfi z1BZ0yk6GbSPp6_=-a$4>I~lD&Ez9_&`A>$>ThJ|cSSGJ|Q*M1RUhlOBy~U`%cc;x2 zBB=4!e}hJ7t&ugYwPq(y@a}uA%tkrU3u%axXiVU2E3WzOEPTmVy5dR` zH%TfzA`-*?;s!4&N-pltUCPs$=&a2;U$U>4o*wn9RUCn8207u@c%b*t*Xr^eiSf4P zUg!KqNwDRk!QovMyPBbRU+$wrTTV;xT^4bWm-v%;L-NT8&2^-GrhIt?`LX6pkgTY1 z!}s4JtAVAFyji~6&{CYvgVx2LHaiG{6ExOE_q{uSNs|)}{-%Q7Q{GmXT`ve-QMLhB zkiVBpERHKL?ldvbG_sOn1%032KFop9O|F`Q-`S5K?)TYzvU7uPnXBL1fo@>^mJ+*@ z!L7NN0`?Ai=3*MSOjz;aubCGs#xPb^$DE#8hx+16E?{vOd9-6NTgSKQiR0)_rj8P2 zMwFQtbt+<$4o}flAvE9OY-X+7*693pTq8rCfcp4N(#Ffpe)g<}s3m!A_-w_6M|Zut>PRhn3LZXWtTF^Ra{IX&aB%_PhEY<9{6%|b=9xR64$3W1@;YZEcr=j^wS=b zFFNNm_Fa5_c5vH)qy`(iAJ6)nV8DNRTaB!WYi>eUD~>D`s)9uH{xEBH?_T*kRE@BO z90Z|e2sBrt&h2m|4L}Rry|(U!1?}0hZlEGN!E)4nHbjG=d-uyiZ@>x$$G^#U!pFbemNq?BOT$}(`MY3J?igqfD6JEa} zs4G<)Z~SMUumI3fa%YUSvcjPCok0ua6FdpU-0}fV_~Wiu3dz}quE|LAF)u6&HQK$4 z2YQoI66xKDxZ&iZyNY(%S+9Z7$NRCa_6URo_RaJvpzC^SxuK#tuFi_Lz9@O8R!h!w zDAU%y8Qk(cD({F~-0-^hF({JW2VN>1NyoY}%oP|M(M@_5E?<=N`Or5JRF@o9^n_*A zZ?5|_X+~nPI3Ij#_bmm;guxjdYM_M)S*x5lZarleYR6#3d*-*DnH7IpNjKn!dTYWf6N!xwT`R{U1%&7+qJ_bz|GM zt;R-U+qRv?HXF8a(j-k|Ta9hoR%3sseZF^$bMMIglX3PrYwx}Gnsd!*uzR%q;n^ix7rT@niM|pD~Le`F+EvXFWj7aW73oj$v{R_MlC>FRu_V@!gaJ? z5OW@zt>(Z)W*23&hS_^X`LNhYCiCv)#}&(vGjkOSd-&agmj9HFvAh9VdjQ zVl$Au`y=;F0UZK1cHIw=d&{HP;cgWxLiy>DsQU}t(y&1ZBbvm1j;&Iu@%Wgm?F|`m z*T-6cX&!PbpMZdDRX3gEd2phRevTGMtu?gAaHcEB58ms%Ac5z7-5KYjGsUKDz_J;}#!NEdR}V>9>*Pz16oc zvQ6Ol_E_Yjk|#5r9NDbrorW&qKb`A}fyVk!=qFwT8H}7Xob_p^a5JwL6C*ZaDsLk_ zO=T|e=m^|(L6IQ(E5yO>mmeS`bn=Pio-z{B86TLvy9?sm!AFh zANDAFRN`Db#V1GuQ)}!nQC~jV7SEZ~ep$YRg>b{+0s#eLW#tl83(~C(9vl7eMxg9Y zJj*5`V*7y#<9jH%y*`QhqMyDh(E^$E!fwn!cQI+n)Mt#5&R?bb%UncuN{LSA6J)4e z>Q^V?nCN^B@h!o_I&}mx0?KXPTxA-V>S(^M3q_&3NJ|kcZ|%WMAz##%y?g9xvwnd< zQKSYEiWinfW4w{y2a`HMpb0|X`&(2Ee^ziOkxqXP#44?&nFJae5CC^bM_i}34tN)E zZgi0JEy-T-`8`j3RP%=xAIcR3_4|8v=E(PP*o;&*w$b@RLULBj?dF&EfmdJlwBnNO zeg%Pvpf*$F94{}JfY(9ntAN*ici)%6y6W;f_q{p-jh>g57pVfmX{-P+MhInLT}Pk! zGrjn!)93PC6R@y)p|@DCwYQwvIrdN{>(hr9EmLqa^)Lo|{w<*1zjQ%c+~8V$JRUgj zC3k}q85}9qJCMt)d_x^Gu+Ht7r@1gG85#ZI4sLtBR!b$^e96veb>Syhk#1E@SWGF#gOzP!Swm6o%&t z=jt)tA2P%;-bWSZI-5l0Auq?mQGUT~;!H%HWwP4?Y2wR(|MPTHSC=(_5|s-CG_v-Z z{E?fA<5q&uI*NQpL_4uX341<=AoGzF%pH7qe$aA4HWKcKwi0U@8yDW%H&OBIJVSlK_Fzmp+LnLrBIU+#<*W=C?hTtWerlDE&y z>Q~Qo%p~b+xs$u%zkh3XwFhrFz(sOLx{-%}E0R1>(IlhVRs4AS@|w`)3IQhJbm23W zKz{hQCDGAQ@wbJ6SyIy)*=Ph-y2AGg{`yKs|(+&LK`?Ef@IW86ir$X2j1%kb9Ca@&aXQ>5j zP?zzbQJ?Tu3OB`*@6m^XA0#zURLZ3EdRh#<2?mJ-q5DHfn1CK8_*)f7NB$SGKc#Qq z+^ec22Q|CuW5vb%;Im8dmLPMA=Pv*F^p0lC1&)+&&HV?J%{10 zxRAR9WPhBd5Lz25A9XsTW?-)5MuX0!?hALADu@vbElBIi`BPF#uWvZL82kk@7P z&D~Ag7qw4dwJNjX<_*A=hv1{`hE<$Ym_d!$c23i;Cr4hQ`zd7)~)IpXP z(eQ-XBFyf0wzBHwK$ZCd$T#q4g&DVj3wy0ayPMT)r-kjtXNu^p_UUvO+o@TJU{}1ASWw8>0dL>)!bv zoRWXT+xlB`4nE+=ZEmG&U2TA={$q>13 z%x_{<66PiiCE)mP2C7C(=0fmi1Sl{uZ0`p=f;P`|-TWR(iv%;T{~6JL%%e84pO;xv zk}_s0!ey*Tiz(}Mn7SC^Fc6MKRb0cus{are6TV=dPNMo?B4qh3eO9Utmj zN{BeU+*%I+!mer7#ujD->k%*cRytGTe;;O40nF+>XI{A;?C#8qK8+cCPFfqj+nxJv zaxS>qd>aY;#gxpGL46iKVsA9WO89mSL2cL@@l`L57==n8g$_z+!lh<`SxAr=hP@Ul zbavb!2`!wNMEH-&H`+2h4B(GnN@8?#QyqRhh2^{Rm+y79c@j=X@4~<=Mf_JGy-vYy zdvz)0FnB$9Fgk)V>ks*y#E2>mghfPY(sf>D^XiJF>c;bN*%W=7JDAP504R2X zV7OO-U`#<$I8MBPFA{i3ya}N6B%3^%*{Q*0;%<#j+Q-*#M^u9FhXYzprVUal<%u)V~UbWo6ZmloLp(z9+lYsxfR$NWmeR!{J z$F3Ne8Vom8BnIUl7a{@-6H`b}=lO(W4K!x1UYFR8Q0uYZ8Rg{2Q_uUh;k!aA<1-^e zPm&vT5W`r!4!ED=2}S7GL)=<0TT#0XKW!`3GTD=Epo*i$54QOYZ}bvE)7RYqP0_UzP@I@#f|t(45&#@M zJz;krpG62zr{Y5#_CV?LA`LFNfgl*Y{#~6<;txvM_*6F9Qd~M zNVN0k@`(ATBH*1!ercw(CvJ0o5?e~cbYpL1NIe&(Ta6zGr*vCn-4a!ysBd5_K%6X8 zvleNb0@SMuNO>cytZwYE%{+OZr*QXF|I++=*zP|nMO3o$@iSV!z#oTm^FqHY6y@Fb zhIGABIJEoW7X5yg?Nx*+?Mkae;=fC^%nRq31Y@jifv7~vjj+G$D&5u+Bhc?y2VifW z!T!a~-@vDsBu3zu-ZJ4gRP(5T+807|K#4T*ZPWuoD-C9~#q-?k^qxr<8*lYH z`Xhhae@m@(V@9Lo-qj#C5KwFolm!jcg(L0y^r)|) z6Fq|U4-ZD}4xll~bu4t=Q{!Zy^k%L&Z5*-16P)!A9#7tCI+N34IQ%|fTpKN+_?LRY z<`*5^T%to4Q$A-bL~pMpBr+TF+r=~E%^q(Ic9sG0FYWwHBW#SXXDzu#uLF^m=3k%L zE0m_>1Fc=wvWB475q9_hfHyR8J=_&)6vJ2tO-?M_I*LUeHjQ@u>18E=j6pWsI+}$M zwfXIm+p_v>{AK)KEK)c%n(qRu2{piVhgin|6Gpi|3|)1otrcEoi0o3Ke<4*e^6Q4I zMsq71A|i_f12(MbmD#Ah-)und3n0@K;(!HYz0+_LvVy3QgfoLA#y9L8L~-mVA=%|hi3zMU43-e zFm8&A+mBum3tTD-%K|CPTv5+eiO{(eNB1xjRQ~5M#qA@plItE>M$D|UGR`uWX z>e=qbpX>}g#y1sd3SE=H=#XuY;Y`z(hhB%MP52fLI?58_5RQyfODof**qFc?J`k_L z(bzEA|RLMk!NaQo3GvSkcL1|(>+a`XtZ(cRB9!oOPy8Mdve8TRjU@$4ikXq`;B z3jZn0eo{?^a}&EMZ*K~CWgB2Z^wA)?4i^r>>ZISZGEaCcQ7KNT4^`_A^pZv2VU!=T zq|3-sBujND=q~|}2A48NCeOT-kQ`O#7<2?3>*`P3C=5B`^@T}Jz5(Q4uLR;~NzE>& z$l!7wN7AR4rcbO}xR~ROYhLMd(prd}C!DYEn*M%{egX{*Eyf67b=6sdkn552MH8Mv za=RAqSmrg{R@{FVg)_x)(q0w{j6WB+1q`~qOJkO&Q@_@O{t0!=iNmK(FA9Vu)$Hb^ zcpj&6IlY}f2++oOMX*8*&`kYy3}XQHt`D^lU@a6L%0ZR2;!b`92{S>MWe3;Nw}&2& zAeL(^G;(+%rKpRTo_`hu&aj&&XcFPQ5$V&bnFB{!$QG6>w5dX*(0be|-C<)F~#5WA?QNGal9btCh0ewmAhVRt+EU~aK^Yi5XMR6`s!yZi z}ZEB<^7 z@G|b%yMpio30zT%`-VsZQp?Jx{QPB8T zv66=Sj8*}F9j>;nsvtwYP)`f~7tKEWPYl`Wion_{C+Ic0)~@oEhclMuUH`GnSlmc0 z?U&qhx$CtLM~9Dquv|&dNszpMvx`X$s8QCDE2$G+kxZGK&9H1d4UZDl$3BXn(E@Q< zY%I)7d=}=kQzf%+WM~M#JImrm_%;}UV*OLm#%Kp|{bIo87;sx5Wr!oC>O$7mtFXlv z%}0wz)bADEhh$*ds$=^h zK+qi06}e2w!|1sQT$3NjiX5HYCd=KxIfUM^PeYcVa0b4%CcHxcG^=bQD> z$WK&T-0zqk z>d1}WdjBYEyDKY_LZ)z|9EQXsdkjjg;m;i~oTD3&A(2BT#PD^Tv{u z(N;q7ntSSH;(tQ3L%g+QyJN}NDDjd4w2tN;pv)h=LXe&p*rnfSl=H$i<+O2`f*6j=l7!=}1M#=0huhgH(3iiICWn^Z;s!?q#xR_HKkW zVz!=OvdOMPl@zqJYl2hcme)cLuP9j9PAzLehc}WnMxT59w4|uok{R&1-FM*dcJA78 z&pyeaphOLlltmw!^C4Z0*ut*i#CaLq`xk|C{M<&Vmx9@r!a3fjs2z3#Qb3^Ga57TM zaMaKChxS2GZz%U)ewq*V*a~q_wVA-*{0+qgSvt-6WEeh&QM4#s<9es56M8nU zf4@T*g~s~VCPFq=PgIvx)7!uTq+S+|XkTHVXsv7by4or{_=Yzf1jdmF5|g&_ly^?MC;yTq_yzZu4s0uJ zTUt2{3|F5oZu&`hAaU1RY|EERaPE6}3Drd~dQrT&M7U2FV1+zjfBQBwO7W*gQ&&Gy zjZ^OU0=jPQR3ID8A=lMvW&i0PC-R9)_mxr;i87!*{Al;(4Z-ewBE&KOF111rF#_~v z0fY6glf!#eclGR+kky3tRwT#|jM48t*tivdS+1&=!g-?(XL;I|Pl4;t%M@#jT2DlM7K%~dSlIoQDI8v&?C5Qs?RC;hA)&EN35F>~MS<_9qV|qIirH(<|Mk95obClMC>TTnqjlrfx6Y9de^WxP}jXbrpJ4L^`ZzI=z-kQHC4*x@S_4Z`X(q>@-( z40VkMG{%8MIfgJ1Cx@u~4Q25({2FP*e>fiRQk346(ARV6|_8@6hXk-+V;+^R1kEKj}F? z7VDkeo%eIZ<7ng2QDTJ*BSn6MVnM0=XP;dbwbUHLy91|7EX{!`1Ia}rAvF7OBhYdi zeXj%SJq=ZyHs835Cm*#)?MGiY?gGz}Cl=@;0Chqex(S8mTgAw_;ArzAuoAbm+m1^L$LUfDheL;5K7YKYp&*SFd zjmquxfC+c49%v~6d;-KzCExO}LmZHR1VRPVlN+G}tV2s=ztWU1Rt3_#2&_ZxbCF7r z_H+;7!>;%xQY}fJ({87&^)JUjdep>Z7=ku4HN6>^ zcA)@c^2WwVONwck>yJQ98~}q(ywM%!S(%rzIbb6IJ9gRB9j<}-Pg>wo&f z?Yzyez<&<{aiW`qcSooFI@-qqsdI*Iqt!bsNi05BXv!mGqU*zK`t_Gqq{L!8y1gAk zUQKBrJuw9edH|HR-hIUezGnFK1T)ib6{HFYj&tP#3ejmbnqN@LUzLW;^aoRPC@`d| zX@O_tA~cAahtC%Kibhui2GILrqvK^t5ej|zA`7&_d$aR0WriBpVCxg>Ss*Oo0e!e| zvb2RFpElwq6%f^?<#wC>13kmuW>AqS(4Ln$*8(+Xzc`9i5^H4^ueF+e&Wx@18~Ab% znvIV$urku3T78H^DhT44ch-`vXS_kVpzFJ17*81|0w?xUyaF>#jqO32_+{(GGHGGd zU=ZQk#}3Otnr6d?XcG_%7z4w5CxS>5NZ>rZCiCJl8I0`YW)lQ7oq~R{vl|tMA-upI^ETNY8V1A!1uJj zFw$C_3@W;R9NS3F4-%?Qzbc`^1c8MvCUEq%IY$>v(|1W^f^91v6lT8C8ftJN#0P_K zIJ6>Ld$fXsKoaDFcQkd8opWHM@@4GCTb{-lK3-o-Q^>W&h#|Rcql94A&sj5VR7p(P zsb?3GU@)8_RnM>(JB=h#5FyxWM!>Z~Kiu@7=Lu?3X8Az zaP$>VEw~|m|DzlZ4_&MA7Q{eH`UsFLCzNT`k$)uF_cXn*90n@a=&j~i5y-8b_$YN; z+G%{%RcLYej=9$A4L?h+dUSO9*(ZR@%)Mk%78U825WUdJ7wNxS=j7H^i)uzEYy9b@ zo`l8St{^42k%mTo%iPftPr$&O2W++bVohA3W%oB^%azlzO6Hn7brzvY>j6+d_jNT9 zxw-59NBLKWUCN(hzoWNFTsD;nkt|tSVA@6w*PH{ln<7}T?&rod|_RYmL{GX7ge~LkwBrAum-<2 zpoG=F*eW?4@6J=9CG6ayACl5TnCpM8cm%)P1_O{&l(%q-pokX<3t`$A#|gdW#{a z8=PO}L;$K_j+VL{(0zcc3$+OQIKHB)(AxP>YX+hNF$T1Cf=ko%+Iyt%@Hic;AAIH8 zcX@C(sU{Oo5=m+A5atG_81^#_HZ@<%&0H!+ zlcy1L$IocJYR;zv5nJ&Ogl$fe*gH&?Sy^(t}u=lwy z9HObz2&c6f%WMyHb!}xrK4x$$<+5#Yk$pzg2Bh4F`c%8)#1ajH6>hM-DR-CiXQMs% z*8HZWhzBvQB%aSS&bh1OA?J}y$tjAvc_{+><=dfx+UmAPbW$${#td(B!@D*!JzMi^ z#5vNG4Jpld;_|`%3*l+uz{>W~Y^J|qBEir63a;Q``^qZReVTeJ@aBC<;>nHx<{{W6 z$jby1BRTNoOGIA7QK#tyyUq`f?tT{WVNqMpI|QZZ;xApC9+~z!IBjmFC$>Ot2h4Gh zsdmGRCPw&KE(el26#?7%zr-4}6`ePHD1~*(2ECv{X1mg{w(*3GV4A2SK7X7LOGUDo z>JDkB(Ybu=vIqAkKg$8Qg1{hENfxI+Fb4xvtgi=c8N`M!2$FbfTzoJl1W36n8a`#l zD&R`J!3EZ3)psi|84X`eFZ`4;2bFcMI~_ojR(l^HS}6M9-hZBd@)Z<>ORacAYTGrI z(>{H{M6;1awmE^+^F2Py!08NPSJV?O@Uz6-Ywk_T%I%+VyQ{JAaYU{y#h~kt!`6W~ zhcQdvj?1eLbVaZ3K%_bVp%{PjuM+1at;M54YLZISb!;-ZIi!e)obTsvK9>J@cJQ;G zzZA$~55@OJ`RYLg(`EcLjd$?%`%Cwo^yFz}Q7);Jai1<tMAOV{ z6?MoGB7u&J(=_znf`^3ayJqmh4E=OtnP|Y<)&*pXg)YqfAt+H-Z4-+-K18K5(3dmD zgegJK`+U;Z;(YRH824yDK`7+wLR8vIWt;Ezh9I*gDMqb1ck#oUPeTp9!}jvFICTBM z`6RWSf@m67t0NNDj!_!2tw!)mhK>r}^vWu<(?i}aP82ty{?^d_2v!^VoLCIixzkil75h8p>}F~+3(inBTYl_S=NW1z^83`1i>zu z1dhrD!yeQ+okvVMtxSPmo!V%&pZI{}M~kAIE*2r-PEi{;lTM0|r=K4M5g@qIn6Vw* zBY=-rb-Xc9?SY8FrVGPsG4=@`IRbIe!=|;d7g5=%?Vii%oc-|Q8m`gYbf*_p4k-b^ zobV$Q2qndAZ;ErD5}W}7CaZ=jNYpQzY6RC_*}RG_eEYX`DMrTK=gdp;Z$N*t|~xizRr&}WtO(kYbU_`8)sSoUxFRu^_+ zg30}V&iHS?A}8DQVW*E|Z>=uxD|%p3{%~;e_evGqAVlIk5vIUSV{rkrj_n^DL;7)g z*D7d%KD}U9f5%41PAsE7<3)^W=HUxahW)R(ZBMqYJJZkrL~>&4#? zJc=9xQLIW0c@3GX4w(|)*R~d)|3X|hgw$8x7tNDe_t4d!4ZCBwC}pHt zjU7$!(FF@@gR9YLNDmSfjg^(FZN=+sj&tvI0TdfsowQ;xp(LXqyAGxiahE*vFkfLr zFn&$g!W4k0vj@_BQ{*Nv!XJd7A;p{y=T?cCuQQD*2T`rMf7yJVL;^7)_;nyiWotKW zl)^PRQJ=l}b`F(S(S+}6nyhZ9PRo>+ks-M*P~`ei-U=dAMl>taOSdV zw#c%H3UFf7kp>op*c(4KHktT{!boJ)g}@88gjMCY-pjE+37-B^=DZ1|IaH=g>CWz0J|v-l`R`PPV2WV)tl1SL znd5IV`f>mK^MSU~W`0WP_tTB4*KS-PO?rs!pnnNI6c!d&{M9E$-2MWe(EF`!<39Yi zD3gz6<~8#A&8Pm;M9hH7B)Ex|&f-MIypOA`;!SKnxm_8M!NzM@ML)Ef&ksKjD(F%J zyWS-qY)9GTX-+)qV4duEj}8&`qkZV?*Z0RPY6S>{Sr0q4j=2feC7%IkjT)%}W9@Vi zU_-z3z@zv{E!(Yf%J4ks4*-%m+e-^Gor)GGTpasZrp_i1v=_Xpy23XPfq!7Om0pYpxyQy5?o_JcPXISE}zi zwJL02U*kSe<~?&zX@7IxL@k#>Q^+yw+Fge)ySez*s3JQW8QT8w1};28Sw{ep5gw*h z09ml-2hwSt;iPvV8QxrJkj-gcH_**68m%yc(>35FRk^=m<|h79^{=U?fk++=pt zv56iZmPUuB8#1M_Du}s&fnH-ZmIiuQ91VeZV*7nS{#U|vXM7mahkvCS9$^5--f;|Y z*A>BP6X7l|tfP;+zP`_fAWo)(ND2mdwOFl}O?tF_S>}gG6i)8YjQB|zm-L`feGIhz}%T>IcO*mDHkTZwDu zLC;7aIypsxX75i>+U`e2FJ?p;DGEv!jS@;GuJQTIi%+~1I2MSiV8UdY*|WHVk6pTg z0dRC;TM9g7ipv)a7alVW6`K7ua7LNeVRysAV=2*Bk-r`{E`j_v^US-`hTe2X7Iyfi z!eZ?RLC)Nuj6-LhnesHKmrI<4r^2riv_!)Oz1ds20^zCMD)+P$@W`a7M4$Ox2+7JO zE44w4#zbsq5p*&wlxRMgIGdxC${mIu`$s(>NCx&$(zqkkPSc|?8J-OGdEqN$f0wW= z>sqGDAlaHaHa!yX$3gFn$)khVV^pscL8aDQ>Zx^8|!72zY5Mhl;~%iC-Zjk;!% zQ}pa^q|LMB%3$A>;;UcsnM(a5fzag+pk;owXOAL?VcnryIp<#)^79*TXR=M#))Mso z7KHixaYrz5_rJn*kmc(sCuVnr&z+sxf?~Gt16t<NeP~TC-1At4Z3lThFVGJ#5zP z!Z6Ei6iH9s40xn%+4k^{$BK#-r@Gh{29m}XI>HrXp^ssI@l&(hm%n@y!}l4Wc-D*F zN^5M~$qJ0jmJG;2`2JD!e4+y78gY{yyQ0Kx!EBn}+r}Y-@?G<=v%xzu2nh!pngoCP z;3Eb9AQbISL-`u4yR`>mQJl#tv>4jc14$srk0_C(|FN!M^*u)1}O##U@)A8;uHp(<#^Ch&W~r(FoF+&B_-QLF0lv`e*cgab1}AG#YMLcTjAr)JUj}n zWTDpQ8Mxil-=uo8y2j2Y5tkPB9s0oR>KhqrFWKjf51iH=1jY_Ikh@ChnI9KcV9ep^ zZscLce^iVj>QR$OMOq#;G&AjKmR`dc?n@PC!WkmUneci}&JXvE0Iuo7fC(eSfr`{D z;a^`ga8Ud54C}kilcebnopx2Brpj)J_xY~X#Pa7ALq&D}VSbvk?x~Z=a6kIHsPF!9-v%_`yUlD%f`NpcO>s(gE3Q~>#40> ziNo9DhXLWm_Y1A&qz(?)*DafG@(glgTQj3orql13IS9##&L%u7xnQ}Dsw?iXte}&RG zz&hE05Kz`g|!qG#QuHNK(yzYZ-nO@$dWtxL6!2?;P$?)tg0)fe;AiQ&=c+4Pr$v(5Cy`G z=tAspTM(m;XDnX91jw7h9p*Y1ec~WNg(ir5Qf2tO_Zb|HHX($eW5I<}DGSIQM~HH|Qb4F1lDo_QMBG-V1DSm=jHe)ZZ({>F)(Sa4``m zE&^<4z(qc;@Ob&3OR z$q$nhUUG|+=Q;Ymqr-&t!bkv@iIS)gSR6q43!M|wRy6Y87s0WB2*(XGme}I9om^PB z^303I7y^Vzg#I5`{icQ&@J9TB@MMQ1X9H8u7)}a?VW!OG<`(%uBa;gdrQ>~hV}Opr zsMAYdpyV>h;&pZJhFI^B8lrw7OP`^E> zX5FGR5V4q0_+#;qX6*hQ5J+?1d{D>x>jAfnJLmzh$n*>~8JY^U8~}557*Yzae@}If zC`^yY@FiJDk}4Icm6ie|SW1M^f7jPD`vH*g>!vNQB;JXG!ZoT_)9>23b6}Zu-Naf1B#8H4co1ZxR*AYX7Zu)>! z6s86FA4j#NP>W{AHsFt8qFzDD3^b}dZ%wM8pEhBvL;%63jKa6v~b#Cu%bSt|g zaO)Tn7%Lk+3DsRXH}cq2Ghz)DKbEm)%Qcb>yf2q<2M+POOXP>s>~1iz^ISu!F`>3A z=TcIM5Ivv&?&I}wJ?V-t&{zW{EJA{a&|pfGIr_>7p<)u^JMu7LrcEJq1xmdut&@&6 zK?5g1{I*-FxdHK%q^I?nDK*F(M}#X1h(w5gcrzFXO}fnEbHKAJ!}wnUAR0+hJkm8G z}yNk@2Qo(G&N&RyG;XrV1qI%Bg7HypDNoH&kpb0CD44`f1WV8e)9e{wtB<^** zsp;#8`;Rn@h0bmeDv)g_)NLiyd?naz;Bo>5zQ3BSzo$PCKLD)#&_}=%2e8jOaFi$O z$U*?7GfFM>e{Q=+`*5A_x$j^%vvq$NJW;IZQcbV$ zLu$`}Tf>7(n);%~T}$8;hnxMvPL0B0la&psk2up~`Zk~|^o;wRZ`J8_8hUzW`5>Su zHs3T4`}|D+=t3T>C|gWYG=Hs1N5Kv@Dr~xeTG1Ws@f~ApVrzquPMdOdL(!o?U?d1e z>x2wi|5Kp=+=3bXNI#iFrw`;4$K5pWlltGJL*f=&yl(nae>S}FFbl3K_6lu?!O)4wvZe& zK1uoP#Vo_buzN@Ric=ww&3(PJYh@SrY(Q;_VDGnXb$U85vIaI#wI=M5>LL5ph~oPv z0)cxtwT2@feIPC)KYe;MKnAv-TEZ4JJmSuKBD+p88NI?Z8ICa9#zM~Mn7T?fB1t6OAG^sh|e*fTPW(9@l{DGYfn%B^V zUa_7n#l&DrYaLX4C*48wJzA_JKEI<1QP{8Y?-9YQi46gDal<<|m;qQ1$p0-GKH|D{ zVG|1Y=|XA%m|M&E+H2^Gh)!;rlOowp%@Q7PgC9bpad7pPeqg-%PRv6JQ*h}{;1;X= z17K$-u3$vRX+1lE1`9-A^!WGb;(^;En|H1VX=vcp)Xqd693aFKW`1s00L329wzs+% z%Ts%zO;e>#r1w}XGH|(Kp#s>G$l%oBBqJPe(lDfVJ5CDJ#TO>B@T?Qw!ni(Y`%b;D-5A#OaZ|N@5V6QloA5|YfOg&WflSRhh2E3vcbazjjnN9U zKOk6G5>UN_S;i~W>*>217p~Jue53s)w>8d%c66lIpG004DL&#}%2i%rl6Q(tqyD`n zg*VK%1|8%sDUu8CJ3i}ew{@uLJ8=@QCF~i@x>D9-j^|~Ha2lu^k`xxx;3%xVGrx7Kl>@dHNVxU2U`|XH(;M zMUPJtxCaM1tX)&FjYnlTyw)V&BNvM<62FT8Ey+jKl}4ZZ5GYZvxDxPzIU_pMqw?z( zL<^=B7kGeG|K*q}=la=?AwutBfd8c82w?8vWB9?R=XVJXw4vN#Bg%U1_|{bgVg21; zj~Ibt?0A1+S)`<9K0Yc##l0!zGV&-utzO7c`I~uzfe53BQ|M$STGT6^w(G9c`#-ViAi5K7<=rLijZ`+gZ2)i=E0&tbydE(4fyoE69vGebk4i|jjL@0JY9lEmMOA$%xTUv3w0UPh|xqg zi$d#y;6L%~&6uXTxbbk)jnH%-%z6AX56JN^vQ~wzhJQ5ZW%;#4O7wh$j*Q$X7wbV& z&J*tiqT={)W+jWvU7+pibNrR&mYOf=Hf^h_mzuwMOWN1(>@{Vw^lF|tgQFt{W>Non zW}H<09~S^4qsQii-SPJ)GKq_QgXxH7NE@2-E*k3Y=o?EmrMu|w3CEx*|y1G(kZ7UWeOYl&Xju`8gs+ry@?Q&f2C5gw(pv?TKK z9OChL#keu*K6=kTp<><2^2by$JY7qtyFS#LsLPALDLjqlF?|Z18O+Eiv!9~mm_m-_ zy=9L1@e1pP?=|Lg2g3Q+@}1j<_TsR6_@7yu%nLgFsRkEsh(b!4RvEg zxw}WlyRnmU=Nx5Ce+txWd=yVbO;BmnWm4!QK_VXspYIXCeZn*3HRK`}*Z6O=>aBke zn=dLGupZX;eCJ%EVRW`z8!L+QoGh)YcZ8Ou=}^wq-a0G0{IhXtiJSRd>hkp9vD|9X z^t}gtESq;?CKZyY{hDa~enL}%)!3U)3^m_wP9aUB zNWWjJfGA37)n;~-w~aV1yi$E8$uSh?v4gk&(RJszX2skry;&fPtwfgxU|y2%Yj6HA z(5%K8zOk$W+RrrE&j`hL!=CA#GUw3rlje!G-nt0Mrn*l|3v{v9EEcD1#ccKL9t!zt z)$X{}Y0X^-YT5hUIudrA%%&?G)eGkbmNH*-(}TQD1>FOxS&RLB@R<#+Kr_-ZdCItZ*F>6GE%yoxtqX5S)bOi#aR=*^!~NCQ1_tycT`i8?<4abJ zZgQC+Vk9G2%vsjL>9wHGPwnpPp(9lWYdsRZi&^#Xxi}9_?K;_^76$O&_Ay49X&**5 zez^*^*J)1Vm{)gp?C(h`_+_b#XpOJ+Dxxfvt&SQ)u@?ToBrSr+C@Wm1TegS$CY3FH zQqOUIdg!W%kFlGOGJDX*^EQU8T)MYeeH^B4;6wj}v!ANm8W?wD*r@RZxAW@Z)TsB> z@ENe}c#PYKDlLBsRL-usz&;>L=3YL)wzp*D`Dk*u}17pA{L+pIOi5 zGXoh3g3lO4PXX&_?8!QZ7^AAO3UNJ5cyqg|$-u&WMXW@;ZjcBmZ0?JsZ@=~A$*Ixx z=ZX2xJ$@A{Z>oU@SCLHyLdeT3HBpaZhs-KAd#=AmfSqaeNjIV&;l-@AjYj%}Vb5&!W`!F8xH>d<^cWUaq_p+ByBa;4;N?&IaWVy-_z6{D(Fxx{GDG2&m!IAlY(hk zoi!W_3pEN*&5R33)l}wg>(iIHS(!USV*f|fS3pJeec^(IN-9XFDBayiDBa!NB_Yj# z0@5JT4bsvv^f1yL(lB&LcMLEL^De*td+V)rS&PL2X5W3z-sk(iz0Wx^x_bRCc9>-3 zN+V8I9z+~yggp}lQxaiMr#0(x$fuIpCm)qc6GbF8xQ<#h8M*k9MA*QSLVQs*^NgTt=&j{C zC&V*Mf*$-4LMtypvlWca{@Lqs+n}QuaW69UHFMJS6(m zyHsz4R-dv=Sf+R&*5t`d7u)1|D&ksy$y*ss57+VRGj~eWeby#6+2@Y zWc!!xPcCx3_U#Fk*mN(kVjJXZK8q4xOomlIuMkWirEaVF%ih!KRoftL*rjH+q~8q+ z^u{_uK(i#nqE7cP; zb}GC`njvu2>Qxr)-0|gh#u16Y*Crc`k!N`PVuKNBd-gA<>M;{w4A zCY$Vg?8VmQlcZb$^-Qi;K7=t8A2woHq>gH540;-G*x!lRftO$mL>2f7MTa#>3-@zA zeDm7w)7hT{bzdzkUS%wX>SEG_^gBA5XF?G$X#3%zB16 zr?eX1=ib4to|jP##gn?YQ@MX$sDE!T|M2(bi1N#D3olqHK%kL|k63}9^ndE>yKaSE z?nlQKvwumPRxku+hnZwy^J5|bW%ll-9iyd?Gmbha3hjdH7dYm#;O48QIu znN>xjRBN~XY-N29R9J6*-~UQk><*9Hz0QA)J12iKd7l|zSmXp|BDE^|Z~$#z%jSmS zNn-u&pJNDwHwI?aM4T>;-pn|xYzwouC&F&J@5lF~{r?S-Ty-x$&8mG;(I4@o9$-Ei zwD=Z^!(-!4^>!>(6Lt+*M_M4_?%wU*L09K;@?y;$4ql&#($gpc%q26MLmY`bjsuo( ztmW%}Ub;>GNkIPVn!DJ{E=EP<+`OQ(F7jT(H2K##4~L5&gNM&oH%n>BGyH-uD8+gn z2RQ<2L8>~B+kZ3}o`N}a6qd8(gF8R z-;V*VqFB8_S95ve&2c(+4B9Zbu~Ns%0$0yq-SFr5=6H>^BEM;%n+1Mmb~;*=(YFgO zLXUozP0w)c0m~xiDmb1KR`-egQ1xhF2v5iUjVJUtTXLzcv9NFtE{FKQ#rF#0Ow`)5 zoXHpImDY$b9IUwXr-B;hLN?f0`CH*+^~ER13y9x0^LT;f`G93vzjLb6#6sf!ltrLF z@Ubsr;~!jqf^=JhGDe08cqDiyQFOq}BBL}H&(S66ZJ|2+s=nJ4D=A)RUx7KIkC53) zv9o;yP6z$c4DHEv&K8b|V5N&>)RtG&`4{mkd`3SQcxEiLzdJhr$Q{E}Q{Xk+f2j*;V=c?#2M zYATCqByq4fGS>T;S2AT^YBx(S<8wX0EpmNrVF>vg?*iI&XuE{yaMmQ|z}~#%;CD*R z`Ff+*bysg?J@{+7${hiY`xUP3u(74Xka7aK$dhJ2+4b`CLQYn|bQ^U|_YnnPx~?)j z@snd8Ts_U(_KU$E^}pgCX?|bzfZ{nmxn2S>WwgiDs}pLvndZ*_igOhnJ3kdUp7A`@ zHq(H|HuC4RS|<65UZ$#7)YcHeG4!;U!0j?=ihe0Jc9>ef-`wSXhPAKhU7aYm!>Oug zOxJf}LFbS@$F{X~j<*hEW6O@)1rxc*3ohG=yp=;M|JmL&zcKkzMfe9hC4!zEtXWXq zEodJi~C$$6#&>vY)V@IpQI-iyY>Nwrvzj?axj6=yHlM&$vkm?6=&pA;mXS z%xTK-zj87{WYiY}i$EUZb-;Q^WnIrfiP1KZzkJdKD~Ds#rxiz|E6+0+di@z!KmpHA zcGYoA;;yeOf69xXv)g2Z^8n+H@2f{T<`!0ozm@Y2{#tm5J>G=6Zv#fXb zE@NI~w?2^wDi&R5cpJH)h%W@^#^ix%u$Z(2`C5f8%rR`)-~MTsNS_=N4NWn7YukFe zL>ZM*MNf(Uq?b6)MAk0EGmnXR%; zAm0sCDdF{3lk0bJf$KiY{=33$sC3wy^{X<;nhycy(E}SwdloB2`g+B>j!ueD-6qd~ z4RJf)EVe_eglLzxYqz3-@x$7gaYF@MAt!!)f+3s*^FOQEXg~cv2LH&#TNH$r1MB#N zW!ffNoMx%u9&W{oY~Zsl;~ewCOvWmhmAO>aw7f{~xj*QjSX{0qF_2`(Q`mnkPAtR! z$G1>SqWORm6vWYSmv=I!<2Vor8`Um9;Q3i4{%0ZPz5E+~WHLB0$Rz04|L~)6;EkX1 z1d3XdX8_^SK7w$8Y`puDKqHU`J2-(Ch#g*D zPHh+?{t1@|K*|rg7uI7gE=;^1I}v6Utn3%9%&zypDk^rKMjwF}nT^N+$0Dt_(|;wD zd|uO+SWH4fmf%Dx{TpoE54{asp{sTNMtD?2jujH&$B6ORIV|fDXkA8FhnvvG4Q}gl`{P zu$bAZ`du_EZ*G{Z1sQH1s*!@O5}dNVJwBAx#Z=&h;Jy8-PG*4Z!}Hu1mEMnf9uMcy zZoYY>izSn%X%27~4Vi!8o#FpRa-+1RfHTLElR`flBc0=SHK?|B4q(wSEJt>?p^{${ ziYrh54D7S8D1N?Qd^I!ESodh`UZ-@{`xakZwxeV46A;-U0^ZN^p6CPLF#orR`AIu` z4Di?d#?syX#R1n~Em>OMa?9rgQ+)d0g_ObZS75noEgX3p+Cjun!v1<+qkEY<{P5fFpZ(OzzeDw!}2 zEiQ7oyAPFDObdEBXZM5-kn?$dwy|`K9++nwg#>uc>AeCB>_+E$URc2#B49Wrw%088 zfEEtWE8c)lIYmr<8`Z=OsAKv`HP{ZkJ7I-h@WV2NUf~EcONJvt!QQ6`;CZr^W7@_Y zvOLM4@{F$0Vr${;u|Gm9R^$RLUjx5ubhM~`o0D(B#_{4KOS-nr_fPx8F;{AxvJE8* z3KdsRT-xDX(NoT!@A?g6WQm-vKj&^RmN}roG&f z=8B*7E1{ocrCW=6#~HKu%D=f+FKY4DLA7nZ1X1SZ7fkvYdH+7nL2vu-LeHRIOdfi{n$Bs7#rt zN@IuEt@6Lm4)sMh_rjCWF>Ie5k63?iU5buLHBW2|r=5%3Rrg)G(>LEP!?0Qcws&Kr zr4?1aE2@Mls^Fw%-#ss!=*ujAfN|3Fs zF7Q}c-zg2pzY-dev8}9}G&HsvPpK$3G%(1qatiovdWhOwE2bk!BVRcec_J}EwJ@|Ba4oxPFY*nldbBO)u>r9 zecc0eM?|a0{RqW_=l46-rx@C7Ixv{1UVG}3Oi4^EN8p*jp>=|SOS=rg$F9)@8bIEz?cHiL z*__+ecvy5wVh;kuW$k*VYJ7@fN9sH+(#nprZLHRw%@pZ8k!SqW+n1V|ZRzHlK9FYD zTTIVL@bXVBVi@2mc#>!}^B4gPG$EfiZwBAo_YCXYY|nzytqsZLDgVO&BUZBm{

    0aJt>2u=OxppJm%!C;IqpmuZ4hn`{!X?x1Z9WV7 zb5fSt8W6fUqoeJ5J1d>@)a_GYmIy5w8q&9e4)cb=Q>BzAE# z4%=tt=upy#c5w5)J_93%xhSdnm8$*#kEG4S&a8T~YLy`K~?ianXxWFI_z-g6DDzfHI|C)|GFEoRrjPRg1`Ve??$el?cV1 zP*KTQuQ?D30=kLL_Wog9ROnxGlhg}1e+SECGCp;Z4HX`nHV#*DEA)~7;30l2r zi5KRj`=z%ec`^CcN^Wg89Bvyyv7@mfhKQR*p2#?JXJ#j%&Q>3r`qMtB;HrEefqp}( zd9T4@Ge1YODsNk;g3;}w!l{l3kjXjb(C_d%WBL1oBO2m|G~mmPAKw>XJY9j0zZ(JAT5yB4DPDhfBV zV(J1^nd@-bAN7ozO@k~hzKo^wDt0}E^I;8-23dNFua!xJjQ`$(;8PY;&;1_aMrK3t z#_tS~zejDkJQ6{84Nj!$mA-vj2weOI`MW27+kXpESv@?@sk7SAvpBhTY%DdEp(39*yBhS4lv>Q`~F4pp<$fLh+-C%qJ4vxqKazjd{zMh<@kgh7;- zRq|Si$>Hg?GGw%|ym-GNFe8p{5G8My5MPxUz~++L%j~4Gc~Cfxg}+-IzXyczr`n>> z6$+hFPPLFOTv+?cpiDA6RZ)(XWh@2q_r&u$@Z}$bi!~!ZP4s|1Etjti@`bij@VqR;W2T) z9hB{^4O0%$uhtN$3>z#l{RU_ttuAF{ggT6Y0rzO`WLPY!3C*o^7DRqDE?1Yas}U(% zn}44{69?xiXJlcBKT#cbbww(|yvNDrnGyakDGpW9y>Er$sh%FEO48BOdi{LOu^ljRuom=W;#keY>{9V43d!pjwP zkq${Ix0YDR=iI_+Np>vMDqZDVIU4Z(I5YBM0>nC~_f|Eis%vS=EEFaZn`*`8!gn>T zTmh=iOw~L;<K@e$~qD`6&G!N{h9#b^w=d;s1gXG@rXF<=KMs_I5wca zqec*4IB9LBtX%JHUVHEutL^B&Y~1hhmXP259_;*lZnUq@8u$|99np;5-BqsM)u8>i zXLP1Xly{mVgxYaf|El6G)WMH2BYa>^&dn!Z#+P4a5{5OH%#2)}ysnKm``opsOk-hB zio(gusU?7?H3m1T?lo+1=(F?G@6X~z^+Md#c>*R%z(W&MrKu}AvjpcbIl%rydW9}c zkuyIP23L8Rw&)2~onADHmx$%=&d_hEp+>CBZ93XLTcPc?Y8DhuEC%UjEXkv}?KZ~l ztQTV$J(Cjj-bZUK=0-XA`%Kg!k3%^BJar0x@;9(Mn}|W=y`8^aDX_db0;x(Atsh6G z4oFcm1{j7r)Za-RZ!u$WxM4(c|DF(yh8eiaQq3u6puBv7M;h;1-LE-Jz`&?0sJ<{v z`~a{gut

    ez227Q#iX8H+VQmpI5p2f#=a>eyu6+UdHbHyW{HD<@di_2wJr>G;kC1 zBl`$IEhcCSe+M6wel8`P=EZm>u~TQl0cZ8p>VKH@3Fc(=ONFg*%b<;jFi9CWSvMtG zbWt!zLNty5Tn_rIw-k)PmR-`;Z+in2Fgir+N7{IbkwL%FLB+cSmW7qgvg0gT{vFr90C$O=7eQcbV(S z>|>Jpy{jQlm7Ce**Dy8+OmNcS-gCI3OJdzM@2Bgehh@cGo!+9#RQEMd^Uxcu^`3`h zXAsd}ioGyuCuT$lNm2YvvB`O)FJ&=g zznLqAyJw*mTt$D?(Is32=xZxpfSa&?yuh)h%d;`=~5{Pk!iMna^=vnNWUkRm;y#<0MXz&N)F84G9#rM3p zQ3k_Y5UDIle;P@J>(zL@a{4h=nVcyu*Db27l6#WwSpcL3T^9JS)ywf%B#Ci@RpRY5(}Fp1u95(5JY!RD#=_6J zTrkZ6p>GFc zN5*;#V{lKMbggkEU!&29I76~fakC#Wo)oryC>^>;ry) zjxPxU+IDcRdBb*-5}gerWIWbyHHSs?7re?JB8L)nB{eY@nk+Z~jxQ-Q9c)*>YcjU= z-M`pYhUFf-mH)(r;&0a%=cDTVV?_a@#fGIz!u%Q)}t}sxu6Rb zFj7hl#7ylL+uDUyd@xABIY%9V)B$u=FrHp}nPo%ci>4!Vdvy)82f2E907eOrx(g z$zP~jy?`Vx8{qoLu7~Nmbpbcz+wo8qCM`ZpDTzz7LIP1(Uunq#DX}opc*G1T9(I0v zJv!go?I$($RfX%tnux#t{4n-cA(DB}d%N5Ewv&lP@Bd@!+vAyj`~Q^=pH4ccgiwi+ z7|Hq6ksKm9pSGNm^I=XiLkB9yC}*ae&x)LFlv5FN+;Z5Q&5RA(j4^(1?$7%WTD`C7L{O9E5qiq#zsu!b2FQF__Yn9^Eo_$sfR+2M21yWpZa%qS zj`FE5+F7qjn%PJ@DX$SXWO&Vlu|&nR)hdl?+vf9pH7K+Dr0wU(ZT3@E+rLl_@O&4| zyK_uskp;yw)iW0g&*b=u+?@Bxzlx#MCEaw*jtnk$wy{9GFZGQHsDw3ruDX={&Qca` zqN+{$&H7HkNX~P$=OGpUSagfxxr{BfOox2B;fEx&~$ z$3F8|FR!^#vn{*D@{$jx6Ii9Y`#f~L%Hj)H!Mbnjsm^rE@ZSa2-JD7uekB-M(6XCd zG9AY1qJjqjSVL*wPbk;(Sb2<=H-OiZY z+W6ZNh^f(#6*>#Vj7#!DXTQ%A?TSsgWKvHabsn{MmHoz!x+;JAM#51Ma~Qg~c^sOr z$#E*Osw(}4i=qQfU=}LCYi`af%O`g5?ma*zazy@WYMKF3$;X)NbgA-CHfYKAXhOJ4^lbN?JQLs1^&tXaC~ZPtglw?$_rF;p$d zsw@rUCi$MP{BeexO0Pdzc1)pD^TRGF*L;`9yf~63fgrAQv4{{=K1;m!5H4i9L9t5N z-XGgy;RMKg)mgNGR7+P9g2}b(r0njSa(*%~LGQ$VT;iq-0fjK(j}3u3JecLS>yNHdBWPWzkvQuWG6Ojay;x($%xldNU3 z>H*x1Y`vj~QbiT0OO6+tD&0S@=9$4=YJ(c&?YA$=N}uj{TFIA3H*&E$_J*+r&;;V- zfNw*z67g8l33%f4gBxc@ZX~33&MNN`4_X4CFVAI4tA<`VSAD+%cHy`vW%9H#&ZII9 zO@R^?kPSfxIQ||?eBC&Q%8JS9`i7NwYi`XIVI{Ob6w#vrFn^2I{O{LXMekH6NP(?h zR*m9@gFZPmg)P+QT4Dw??uFvYZOBc$4$3Sf zwG9}TnoNz}k7Nu(8%hBg#!f%rqVpDP_!1))SGmM~COh=H5(m8$NTf>aI0Ezfi#$u=T z#iCx!`N1-i0%YH-9ed8 zM1f&`H7BCfP-DFPxLF^fM#9@e0Vx0RUdj+HInnX(j=FS{h<4}`8j zlJF3iqpj=MRICLI+$ei8!tdH(IT$k zto1sF>&I8qBy#RF%M~Nu$+uI@Gbo@HdmdBZ1PDzN$4k4wcjbCAz<+6-HYQ8g(KT{9 zcl93YJn>L32sby*{$3KLd%WfcHY@6efoOPwjj{;$OASpdfG}&JRJ+M)9#H@h3Mf;G z&0hTWy=RRcE5CH<>#nNMwLKj&C{rq}nw&P^nRQyH`}wCqou#{|g*JZ=VA_mof(!>STU%hDLB=P1;1w(39~c>}q&2-uL4M zRy~3Gyra$_D)!XgMnnCQ)=2rz?ef?z3eb#|>RoUF6pX__oT81#71CrAiqYDtzs;P% z=9FEAyuxbVzR)sndq&UVD?(=G5KgDV*as&R@Ao(dNI2zLQN4LzT`4 zYNxIfYKa2+T3%Pa3Y8q!PNJmd)LEY_)vPKhejNZz zp*W& zd@fum>4Dg?)Sqn#zA}!zA9P?ZXx`1_(9@>uOOY7E2#!f{Spt++^?C6=U*B z*sfGE!`Ar_htFsO4Umrad!gk04V)aIcMHltfqSh<4(#Ct6iW*l-Yj@k3p{h(C2BP0L3WJm=$s#s$ND-rXCNa zm;u0t<(J0w{ji#GZ1s?`HU8+ho0GLQ8o^_^A#rvA8~%{{{>td%R(Q)dcUlO+3@TjZ zZZz!|Lcs3izrf!`%fDGC(0`>J*l@3o;13bFyhoNO1M(6VSqKj?4InAJx)>_z{Tp@R zBf3K^YBi2j_p4UfKDW>(Hh#Y`klYPn>PeKrc(ie#$;mm82WVG!_-3h=P;oIYZki9+SJW5sm0tgHjn9y^$%^8W zLyyb)L>fy{ooq`=`T()CHhlWYH;@NC%R+NxXNi8M3%92$e-cNy8j z_zJ`}s_9p+2)i!7tU0z`D*xBNxP?Gb9@k9P5c+uNks_49`ppTgxza4T1aQeSG=6%hfkQ}m@gXO2*Ls6Au0Ke8Sq-!%J~ zAnVb6lhl>V<1@lP==~u&S9Gl`5**vJA%Z_wdY$a*HchZd#{OOly>a~phg60C|66f^`dGntB{Mhmxf3AfakRL}Ewk}@^+pSIjgvw8Wici0MRk$e}kYq2m zg;Nxa{(4JbVtpKPvjM%{1(QP@wQ;}gA5uYoZY;I(M+Jwto4oy4eB-d)(R1Ui#*3=H zY5mhx!u8iGbCd!3%(mORtE$7v*!MjJBd#1{rgN_Z5%47mi=#(bceY;v*_G_47uRjB z9K-_P)r}9?B`XPDW#JLUHrkcJpd70vc%_Bz^%T$=@hUVs7K65oO zl$x#X!yL(;Yo24u98#0MJWkknhc;-+GR>3ssj4VWB^5d76#2U>6y%r>U|kC( zc(c2EJ`tSC=26&#OMdz7D1<_4nv08@o2iV#7*ZBALd4!PSUfp5UHTf6|HJ}P+!=L^Kz%6>h8s4m zHZU1OxEhVGme02I+)8RtIBaGR^nT{fU_|g1rnJ+33zx+X)P%qgAG2@o`~1u$fz$XX zi%1yKMt!aGsvm5SWwUyUokuEypHE64d;+ay@;*JUkh0r*kI@?xpXW`F|7N$@9hI!2|4NbFq%4HnEOkK1ZQcRls;izjcm67J zcM0rA4)_#iN6ywei#{-S;C z_Y)ry3~5$B8yEMsq{H#mryT+A!_gR``807gZQsh4r_v-dm@vRsslIBZ9_(cRaqUeK zp3~tT4O_a|?GyyNq9(KtvL5`;UXb$ukkGM7H8r~@m)!6DSiH+{!J;@&xVPoni6LhZ z>jsrl?cW6hRe=?R!Jc6F*yte*%3yn7ywBg`^jQ!0f+5O+$JVS1i(cGS?+3FOFzf?; ztuZMQ@}m>j^=Q`8V|F`_&^$xlPovg_Lm`vme}3>ADa+aPA>7fL`PcVrM&F=4lHYtj>A6bg>hJG9So zJYTg^mNh4b=)I(mjL^y(lAK;@BuU3)dCGN=+lM6C_p2+%osp-c@aZ3I&a9cV%A8gs zlusgZ*^OE|FT98Sje3)0=ORyTOrhuOm7_sQTsPGwA~U8pE==u-l3QLiFRW-7#>%ro zHV_R1LzYx(tdnW;jKa`2-{*QBy2qYZ)VZUNQ6P7nJ7p$6+3>>|I{ViJk`U}ypAa~}0#S>f<(o5cle z#W~byy#jp=MfrsEnd|r}%<-@iTQDkHVR8$ZX+X6Q`$u%rY4_kx_!RmVvp&8~3mi1> zmFJ?8ga`QRjmnB`OH%O_)vuin-f$}PDX8<-wANDo@txoX?#&bc5BT#JI}aP~_#EQ6 zB%)JtIQSs5#6+T+E9ge@yK%37I4;zq)3Ff4$(lO<=F84_Wed9^~_ znVR(LNwHR`n<|ovUEK7#wxErBYTV!Ujh}`DDByPTzwaA=azNqKvdEHM|Fo)bamsMw z9FeaGyFa1Jy2{c))g6w zif4z^F^;h5Q)ys36a>Fr>(^jNnB(L~cQ@((@#7Ql(xWe9A*Kmds+j7Z21Mr^9KTvR zUx+97nMiF_GEhDJ7yJ%zBpamz>&)e~V&0cOw{eu#E->qG1xrsA#VN}_A! z|HQ4$XqfuVgUp2*NJ6<~mj23O9_te3w&=#o5Y{`8PBTvZR+kFm^u)8~q*XfV_j_iE zb5)E9h`P|wJ1DhJ}<-?Q)7 zM+&NwCYbW8DaTCa%4#H15}%D<%4wW5uV@V#zKx8>KvpoW#uZnULKRm>cbzrMDjJW~8{AQNw_3Tw<+LF{T*fL_T04m30_MWPC& zmhT}lq&wkpkE1!Im-MNsMn0Qm^BBshk9P14FdJ%be^qZC(x; z+U=MoGRLou@!v3*UN`OZT(oFs7tikbb5M)MyxHy(r(R=ZD3T~|=|cHiLNC9^WiD;L zCKCg;Kd!RMp(@fK+tLDGD`E84*JDvFVnGiN2KD3${>oxMOh`Wfmu-R7#@o`ZlH=8Dp zbM$883k&)R0wWn$S5o&n&*4cia)vIXzW!EXeWR+QLei7q5WRbbH28_Y-tx|9KP7#)ANc^%Z{<q zAjnC7oE*7xPj8&xw9&NeKt0UP5Y)7F`_>@YLEA*9>oDtAh9--`EOQF+5G8W$^#+Ja zIHG!kYl`wS6s^k!jZNg4L9rvpiu{Y;04sBO_NnQt_cm3wLtCUcqJ?|cXaa3H$5M#N z6$%x;(S7|!kB&CHKMdA_)9g9TKR2r`0qPcmZM;@_o8D&lE=lo#t}Jop0+SHILcIhW z$1*B6+GRjB-Z~5Y@iQpoPmxZG5vT3C5OD5#qR|F$x&Fr{i&B{e=cGE(i14=f^y zF(F$|ZfF%3Hw5O|`Rq&{bSnWB;U$$JyQh_-`4SM2Hvc+sgT(*V)YsAZex+#0ofXHo zrpDCO(&HRbH|G=29@s`cAp1qX`aI+Iue`Cf^2cOt4M)1USDm)4eUfqyEyNjFF6D71 ztI>$pu;&8C^o@K(tweBi)@t?2^|@_2bj~Ibb)tNdRn@|-yeu}~b%y3}Y-8(T(Dc#u zek7WBac4Gy8Q-F62T(wKz&yXL_jWK%&}KoJ%_aSP8LY(fNnDH{_(ZjUkObnPJq{_w zK!JlpW5IuoGJgyzG@m}`VEP=jo217N4ll|FySc%5ouvWjsKkxe@% za8Y+QbFVlFxM!ojH82$P@hmZeAccW^BBo!0MX&U$gUHH!;!|(XTW|$bKOVlJb}~z& zVexV|pWK|sB&}ApbJ|vIl=-&y<3mJdDvvsGo)hhwPmLBOD4R<=s~T2Vm?;3U?ctPr zC_541ZqRL?&Djp;nl9EdMf(?guj_Yi?N0h56u2o1GQN?#z1HU8l%JEk6NRZOQ2qF*8DY>xx0di^Y60}FLfG3c8YHddsR~9mC^I_o5kN0+u z#B}D7gV@t+jlmvN2X%R8JBEW}QYoWCPHwJh+vl!nxqD}_tG?x7>+I4cMb)71 zx5LL*0CEgyp6Fr97hR{|u~81au$w=|0;U`3`E${?{)k`c)Y&W_oPM_wlo>1^GcOt3 z{eelm{pscX(HMdcGS&=W_=51aAwpw4-~MpZ9n>U1ax*lZmEo7_v&vy0(a$oMp)(2y z4~6DPw46H?HA(2(@ly2lSVqVe;qvK(h9m~1A<0U))8xzOlMAg;Z_zDGEqp z`ho0^5E3#(O4Yh0Ki<1#b-&8uv$x2T25W-`b8HWxB=tnFqS$W#qxOFT;ItXJ*XHcZ zv`lPvPr91&=A9ZB%X%Zl58s}Cjz{_d;b@M|Ea#B6b;96~iBxez=|coKyC;dHe286z*Mk`S9;mEhHX^a@_g6;uiOpo_gdVm`UfS4 zAFRRx!Kb~zfbY#cMhikF5<#7Szj8o?4|Zq;JXBTY=RdOg$@3TD!_LY@HS0A^tyJHS zKhg7btA`N}-vZG+nx4O0he=TAxYKNE)R;u6Cm1pVHCkKYuj6b_eWK6w#UoWL;)jk| zn7x?q9I3{ZEzbXJWB={Y1}@-o@?{#e1rAwgx)dv0pc?aMXE`4~_BARz;9PyfSrGgE zn__-G`B)&!$DrDhkLkC&p(k{Oca7>pya}V+PpwRSB*dUxubk}ctFK|=W{G95y{gB~ zTe#^Dl;7vT1aow_q7R<-y}}qfj6%(+6S1a!$B12 zgI4(EG=4P{$l*;Aqn;1|nk|HH!UqE3)CfZ0W<*}zNPQ5@)Wt>F!WwT}#YeYxiAvX> zN;^>HtXTsNEaHI#6_HZ55g6SXSs6UGKaA7b0&iH#H^0q}tVk@+*+=|?7dSaM=to8ZDVH0s-Oy6vAnB8cd4jmf?9)qyInOIg z@OX1K_in(GS*XnJIRXwTQ9P^GpCif|JwU5?16}2#m#4IlLM=gka1lEVUhRBGDnTp5ia&6qw2)efOk$e`N z6AGe|;IFN5%OrSqBoj%Mr4_<8N}n4u)vWs73YGo3K>8Vmux_Z%b-`83s^a4l5)?(6 zx(7a$xTC+8jrt1~J|$_ye*9kRSzro=6_^xfUDHq0sL|S;1_j4=Kv)NaLQYsdz_yct ztCeQGKU*x#4`M%CniLzyM;VnKDEic}V3Dntzjbr!KWpBsFf7?LbdqQ|atE|PZ!Gy@ zoyg4$cNdCMvMr0W9KbOop*crrR@seQQI@8`P_iz z0D^R=@IReODi{A*DH(K5805nw?v9&-<5Zh>gLFhJw~$s%xhi|guKqiX(LKOTKX;l|7Z$W33_R{5tUsx9 zdU-<)0aDo(mn3xgMw8yNFSeix6g;;|fLNI|zZ*UHYR-DEz7KpI6=!0y_Wf&b@0gXL zM-wW~FD)s4w`-xGEgnG3_22ev>aXNC!Jfp$d}8hep<7K!E-Gy>t^DHI6PtQ^Pdm|v zaVQ0b!#@fv*fl9OXD5BZzK&T0HYp0Y(dUWSbLdS|321)^Q| zLHaKOp>G!-b@<0WjgDE93@g1}9kl4}H5txnxAk?cBh09h-9&4y`vfR+83^LNO=~>V zvDunBBjcGp>U-`jbT9e)x3f|&>lt2Dj$iiu`%wdDh_feXt7Vzbkyf;GXJ=-$G=nq( zvUSZOA`WA+e1xKJ=T9=cBe$%8+P4mg-M}y`EXd$AWN=&K^vcFR>#jRHt%m|^HkVIR zPgvtNRex<3!X>{!sD<#ANicQMU{fqY%o1Pw?Xux&%}C!7xP*06b)h_=an23A+ZzQ8 zU?0+t%H(Co*DHOk^6~)Wo&PrBXNu-0^B<+&DOXSRjM}(J6hupi_8yC-ohkFOx<;zc zaj~9K5wamD?3saiyT&WG&Vs&J@2es#e|kui_sT>FnyyHBt)6wd(ln!)(4}H<7ecQh z-ETmzsM`1%{UR#WoY+W%2Jk4FMhwsni5>+4GDUCYx^BBh$3tb2@0eCNZT?M>Fu1|A z=4py?r*)~-80gva?4hoP*1%@oCzAfg#lA+xzV=bZ`G!v`&5iS|W7u4~m4i*dm~?@M z*S@GJvLBfiZ(2yo8%bNc9gwl`z>t)q#RCUZ_?hSb6CDD-zUwM#+VYK!@I1$n8@$DS4JCo7yrm^YH@EJ>p%Ucp z%mSd(q9?uyhQ2qfFv&zB3WPF4AR#ssPL$bbzmM35s;8PFcn^t%ST1m{&=90wh&pcc zxxcpN-?$$5HpaC^jUvHuU(fn8@f5MGG|mC?o(y|O(>Tp!#M1a@qp$peMsuS|NKyf3 zY#S=Q6Lq)Y(%nY_RR8=IvReBfN{JL)@ILf}9z0d{n19tlJsM;WhOZ`G(d#*ub`5Z5 z)jJ^?XQ>a<-{Ce<5^IB~$?`V_F11l1+rd#1W0lu-@;`uHIL;Pd_1rcB*426#TjgSD zQTM&vIahdqCWf!-Cs3jU)xlUG81eb4-YvHK9@Ie~?vXNxin)ghsbHOB*9~tXcE+5d zjEqe|kKM>^Bh^5__~ab_eB|Mp^;k{d3wtfJGTiJWx9#9d@ao?;D_k$Zi3%W^?-2l> zkfPe_qNU0`grs@So||5lYIi~r@1)o`vdH+y5VsH6+REZFRt!mEZX z;h$PbL>>W0)U6GI-`@l+!4%bb8u!S<^3$?SmOeQ7{39utfr>5mf3*O1%}H!JY9>HG zzN97q)FF!+=PqqoezIvXrub z?TW4XdP;DCQDn3qUt9M@uc3sgUYnzlEth2txSn)%0JH(_KC?inpmHH*+ttA3T4e*W z?T^ZJ%gNO8pvOC-b1p3KbjAMQrd_|k*P2tFx#^g^jOql4l%BZCv-2W{p&x~ab@s>I zy)tceGQBil=2I0V(#Y5kr3H>NA2Hz9$1<7OF6&8a(x+=${<7i!up*SCF$l^s=I7t# z9=m4w3)B-75msQwI_7>OkvIsP-(H%O`?E?p*B}g^B#n528Lzi`%psbBZ4F->73Be^Pv?e&Z)leLFwd;vlf7U+AK9kP0~1 ziLJ}PuJ!}$Z>Cw0sk#~y9qdPnHo_%dWzS5Fri%H};qV&9CLH9FuWbECeh|@jv{Be*I;p_a;yhQfV^&liVNt95@-WlMT%2mFL znN9s*xT3q$k+n03S~sLe9A$>LtA@bo{>R0g>=0mhgN%il%5mPfZuTY+S*Nec35D7| z*01qlv+}?JHus^l#|c(3nM=|@I#_C{e_MUL7vGTdy-K$H(!@1!VEHlua~)-D{4zLj zlI0uKYW5e59t%29?nCbHH z*Qb2+GO$A&2t-dc0;J&UIzxUU>BnCdVw*q`ERw+tf#{U->87q5D8vL}DM>c;c@q3*rSpr)bzqYo~Hs9=IQ0nVL z3-d+M`|F?QjiwM&QWxe~jK{{sFA0GNx>wt|f>q=6`xx^$lFp!#{d!ktYBA2ou=K-STC{ zLq!W={QRk%r^y#FO0o$aTpZcZjnx=;!r#H~Z!wm3IbFpKMM5S+F9waup+5lyS||uO z-|cxOTy%fQU>$jv2JoDW2H>ITCneb_+W@7ofKN?={co6p)t2h=FAqgGBh?%qv++Zv#NVrR#q& zPK_kq%qwH$jB9vOkoiy5>~$V^xbCS_<7{tl| zF2?+~2|K)g?d7pA{}c5Nh>^}Y9o{Z_AW*HPuJ`&i(VoagQ5yje?&0y&?@}I5vl;=L zmYMX7=j?b2dgt}2`^@NkRcY$=#iPH8=~vWh z4A&!$u3ym~KlYw!TkfxT*JEC(gPX34k@fQ|oi~#V$~ZnP6ApJ;JIzlSUS^NHtSM8s z9vsMzWcB#FJG;4Q%6quKVDy*KaEHX5Jp8e4QlZ~=VZAY{7I?C<%m8+3>Wf^>+>rZ9 zg*PxLq4mO}&1RqM87qbPsS>m5F{mWi8pt>^4RPmx`H$y_FS7&1nSO;`t`)1sEZm_Z z>5~~vcc}DCqyY6uo*vfw5RHvZVX&0=0h~C)IVd9$cm2_U#{RmlZLAkQn z;@Vi-{_3FiAOn|N#b}J|RG0VB%-B$ncgzpKVJ*&2qkQry(F$YaIt6&G{8onl^)VS$ zs3@}fn(v4MzRBN!NwFT>3c8Og_W&aL$K5@0=h`d^z08Iv6y2E%93So6%L<)yleup@ zI;Itw?B7d4^!Em6rlm8hVM7BYM5O(Hi}~|+py!7h1u`+y7w4dS$~||epITwu0&`&$ zTnG?ee(2)MndMrs6*L?^J-l)DyoBQ{D~|VgVLZ`j25Y5en!Prw3~T;;7-HC>;M)$D_=^5cfy*keC+K zM}H-?F&V%^VbeUU26jKWL)Iwzl%aK9g|Oj5T~euiX&=6!7=U5-OKoW9y06P~os3ds z?Es6n{2I99%j^Pgm7CX2?*L^rcJCIWy{(#`u_PD+KbHK&=5FW4ae6-z>AyCu0@$3| z?8ckr2|X95VUf!}Uu8`#2YSn!L;9(!b!X8gbj|kT?90!QQFkGU$(W7SM&dMn&Od^p z`$&W5n@>Lp)}ja=yGY_}-daJzuO=;|B9D~{G`5SJii+XX|`f5KBAX5}#_fBC| ze_HoBfab1Pf!}VB?PsQK-TxO91R|+I+^oGSo&WgA6sPK2FHV|Bti+YxE?!z&W1gJb zXPzpJFcQkdJ8+q3%(2B1w(p&lqwgqq~&if%rHiI+ulpTt$e6teyOH>?=#hjKF>oQ8A&!R zHa-_RVB_y-vSjiQD~Ce9!Y%PFEj=!76H5b@jBtv)??PmmbYLY+i&~TD3wItEZNzE= z?DKZZTK`UK0L%PT z01Z?f-19GGP(l54wZu-Lsf{BuqT;n_Z&YVyg@?&aLjB$Ie5^VG&Z}7S;I9^-#%7~G zJjljnCVJhfrTK3_&v6XWhXo$tDBocjw8NeBTlvQzkH)ajxD!W!FiMls;Ze&Y=SXd2 zL))V(G2_pW5`6NK&ej|syZm(OL#SDjV1?fPr})vvlS0;%;vMG`WvJg zrrMM|wo+rql_s-GJOA67FZi-i9H;YNLya6+9UEM97C{XNi7~KMznzz0tHvqud3dnp zBZhRL7vXw~3UfmIp_Kg8B@pEMc{YsLW&Um<;%O`5qv)U(KT8Br^@pD!f>?TYeCg?% zATJktWm%Bqaa|-xY=S@4?pa~Z05g7VLY4rqA$27QVtb%S%mq;Q-(Q}fHnG66XN87o6?z? zAIjI?f!vzqZv!xXk`IfpEO=44@#YGWx3-5gi2700pII+|n?R2eGN^TgHN!m^LktRNRN z=DJK0d93nxisrAi(l&<_HfY74!>*b3FlDw@-`wgVMa)O%4p&(I(PNJaKYw*0=#WnfYE%t%9`gp1zN7|l%FSL9&zrx3&c zE*HlIb(dUs>l>J8__gI1Qg0%o7XJKB{_2(e4}FUG=fZr-{#OmRr|*Nul-Cq6$G2r6 z=|o`)RBcFdZaT#Yy46hbuRdQHmA#d_m6-rg?{{nHi^ui>n-UPp z+yl;9$$nl$d0mlE3cI%}NPo04aBT9o#ec^eTKUuOr2RXF9%?%Y5uSgR{q6p}UpN`j zV5AwVzC{X9+_?0d#1*c=*XUJ@w(3*S<@Tv}6`5($Y?`feJB7?(a zIsqlbAXVlI2p47BcFhZ=tIF=TTC|1`1Hc=96a2c0~dNOJBhwA zd@_NlqT-UHu27qMiK+YFY2Zk{uuG7HUOdzi{fnbJJ?aR5l4NfrFE9nUR?L~DVNO*c zX~=j0_u5*4OGPVea`Pz4{f!qgwiYA%2bxN@*VY_<)kw#+rne^9a0WvN8QUuX=k3`S zp2w{T>NUtG)nY_;#XJw+`c2k^m!7L>_q@&{Pi;=W%zaWLNNvAbc|LXa9W!08x9iN7 zBC=lIX%gHo2yAHrHCyhv)qD^D;|y@mFhbT3&s`beYaq3a;Ik6Iz%rTcWJeyt;I-$1j>rxRQm~^|Qw96Ap#T5D_Mu*t_}4N* zFVY|C#UZ^e$Vln`tu;6hxMFv>y)9hq;Gw|Rvk$^IP}b98Jze~Bb#FY}L7sjm=f~RH z-gwu|`I-s0J=kbkt5+pxI*gGwr-WmUG=avR`)z1{oI}SP+YCnwzI6pk@B>qOC4EZ2 zthmz}G=nbFQhrFYlb#=04`*^G4YffsWeET+BSFyNr!XMg==Pa#c;7U#8@CCKj^^c2 zf~;;^>5WFF9lo;y5XtnJ-&p{%m|EnZY>lySa)Fz~3W17-OJIb{z*_ExNBHcu^le-; zj;=3>c<7%eZwT=yrGKvc98$d@hA4*>h6?Ob1bgk7m8+)|MWQ(lYUX&c{pz2O3X+%4 zL%FC{9nm7am0#rBV`8o3iL%^hh$3L>lT&p7y~+p3dRxajh>^f3%lc-M! zV8B`pnc>uLwVsrjCDKpT8r7WROEE2~X#iG(-e!u}Jf^woKKhPp66_O{x^edj79i9L zo{|<8hTI-Mt}$c>^)6{ETS5b=sIC!w+AIygWIl83W~gPw@#p|govNp%AyASsYn^T= z@yYT%&Rkqzq=?{dJ?OF6SOgi~{`-&Le+YPBIzrL;%e|r&FHSeAcv%BDGSV&_VjDP5^-s3znzGeOFwmxpIHV{6E*RONIgIo*b)crb{Q8+L5@ zUKvw}%Al658#4RTvvBGm1W%9?#s;cE^?hbVokmk9DHmo$N?>P}RN*d2wl zM-dQ?fN1Ywk_q#+I&RRYRM@Zr(*(MZjaK&`5gFnKq;Ne8EhkOC*GZROx*ko<00yei z@{XYa2q>RBc3PyD7g_2!=C->v0x?kn|8pO}<>!)3UD4 z>mT|)t~Dy%AOT$UIRQk^qMu7(Im`f3Hr^{F)c9eQ^dF*icVDF+ss=Pb=TBW0>*qgC z|Jk12*zKU(TC4jKTe^b3u}WRf2!0trsFeH{4zXV zl(dAI+o=d)iinxQmSgV&oCH0FHBOX&ShG7{Q?E0aBs+iX*oNM=(#6#Y(o3ShDa_n#B#6k z$eOk$XHy%r`UuM^99v2S`lJkh+;=p(;200rZTV5)ku3)Yhs+RZDd6tSU%(-A_V?ES zgk4ImgL>`2IGdGiQKt)xqRPOj*por_S~VU$q}9$(c`goal&JK};g=&nHQbkw*gq3n%xo@116=HXEFyZI%6&=8<^g%B0|;sdg5$ld4!Y0Q4L{Q%V$8g~gR{`ZfO zd1jD<+$LTE`6V!mC0nkqq>_g4Me>;~|F%w$>w*b$>&}K z7L{Ovg3Nc8dB9j6aKl+v8Xh>5tgU>>h1oP{y^oFd&XhcLp)b&mp7uX#FZ75#r!C4$ zJA!N^jkedE0s3#U-?jA^W|>bG(a6w;7sZ*5z*=w&^>{?Zeq)=th)7P}O6WXtv^s`e7d zTIxlNWqo$j@V2z3u+_aEZ=~mjlmEV;&V(GtaF#=Nt5`@7?W?mhJ=Z z06SoJ3_XIjsQrKRk{An157}Fgy0RwvMpqBcy6$!$uhm-adi;>X!Vdn1{tkB`B8VB}ioVz7zD=;l3YAbeLO9_( z8#S~eXz@)`Gto2+{<+-PRSn)5MTmSJheyyjqMczYP{XW!w<*#MzlaX@nc&$h@H)O3 z&)KkSU;}{-ga;9>pudKCtnai^WZasQZfmYHIH~$OZ^cCk(8xp9)2Ls7hz`%cj^(RM z`}(BBzp+az^x+$LOL6!czm7@d;|sV-%J0$D%xYoXqyE==Lv0&!tH|wyCJB5H^)U9^dX0Ms2rq?WJB)_lyq~T`10z zC{~{1$=dxRfaq*san&KgSb!;aHKB@7#phVanIC32nIywX&mcmVMqy*A+;hHLDvd}c?e$8zx_t4IDmaBKiZ;wQh=fXF8x ztXV3Ai|O@2$Mnr=dDP1{Ndeb9g#Ovm#VDj*{zZlh*>vXqPb;Cf5-|Hv=CNY$;xk{SEHE}WXCSw#&O}h znft=*NM4z#zwei^CqoBDj^r`E%M>#$c^IEjpC`_$qyFQVJ?jtNa{le?JjSmGjlY8W z$TQn;I6$&5{YYJ(NOBk7>TiV@Xa>lAtaiWZz-GtPbYtxkckgMH5F6z9bdEA+t1V;e)g4uu!)~=REk+S~91KyGQ&*~YR%KNpejPz>xtzYlC zC{x%93`HhuPa)#S^9^||A)@b^T75wi8w#2^%7_6f*BHV;H6vRGO@4HtgCcImQ6%4-%DTUyK7V-V^C(B>dD63K={sX(D z>xc}UJ4J@cj64F_b4^RNJ0O##r;pQDdw6C2UIguX2@ZP1v*Nw+Zj<#0tAMdf=8;iw zikXovgXU&pV1$>Lp_?u<4LwUMkhA-n?9K1-Bw~{o%eS9KF;g@Sb#<3Od=-W5TELrQ*O_ zIOofB67TfJcNAK>BUW`(eeT7B2v~S~tp>bh?}FXt9APZY-k~rL)aa+B?&;V!nyy1L zMr;p=2QE$X&^IB$Q~%M6JTHksn<>63qJdzArIC_I+n&P$^_Bl6}aUb+WHR*~UKhv5u@`AIvaz-=lip-}m~1nd5NG z9M5^*_qCkYbzXOKgiAc9qx7ACOBYEpOOXd}5wcHWuPs=7TsQmY$hsxB%EdFU#JmZRiihkCQsU8R6-QuG zjZ|4Umh3yYtrE@ibJ<@hVF#m7tJj$WJDjAqZ$j4&J0tPB%=A55-L&*O&1ZcmrXWUV z<3zAT7YcLAG*l0`h$!+5Cgzh=+4;v>M2F~OqRW)}_lPNw4JpFXhXg-TnG%pH0D*}W zAfw#dog*w+-JI-G=GwcrT)emxljCtX{Q+AxS+F<>r10J&f30ye(ugl1nJe#g*fzEJ zr8AJt;5Hp04-fBP%df(H9XGHa&RHscGZ_MFY{V%&h!xA~U|5ig^q?m7buLSIr7ZaG zUJ1P&UD#Hwd*DHVjR4B}Y?$T<;s^|78#b-~o5#<0$JG>5_`t?n=G!)EhN7|B(b#A&rLcsxG#IqA}w)zQ@h%71&zN|XI+ zpr#-w1_{<>D{xpK80~ybm(*11gIjjj%?GL?<$ z++rQlmX4d2^E$`Hn65-`ySI}pXKb82)SQ{XZIKR$6D1)|OZ$Y?#b42~8>O@y;k`gx zzBBjz4^Et*1g}t%X0wOoZvvN$G`>uRvZ}=^rzPH=C>NimjFXINW`4O?dp@8ZgGfA~}i}Xdq zk^S2H=Gt7$I^6OFLdOPw;05d1F4FWzZehRTdepk>3#wdQzkB6tE-jUmP?u^uE~Gg5 zy#R8rfuPmQGhTmkSSzin(ZLUMk_C`aYCQXuMkM!uy+eosd~m$jP=$1w>(T$<_2I)noG8jE&|X7#NILjBn#O z>v!iVB)5{V<6_s}9pnB2R|2L0qOQ2_)=2;4b?`sLIT2H&3>tkw!?*Jf{Rn-xf7q6L z-#uwcXtir`C&`vjle|EF#>g%Sbh5@%(lgUti%&jrx<5yB za?Tpo)aJ!HNe*p(s8+`KC+ct;tEhODmb#}Z#cq3$1L%BrrtX&+N+i$8mTC4``Tu@* zv;o2m;ib#?XkUNnkOvth4uXzWF7K^S8}%HMFq3`s^?TY+e|FpgGrq{`&U2y>Ip?YR z8PXDr1obJ=cZr673@h(b@F+45yc_tVsPHXr{V1@-@&c*v**h0EbhEmFDu(Df4apV3 zJbwRBqEl(7_J!o68z8nJ+l{lS83=v$FLa+gB~P;(9yPX~vN|?fqRcUq{FQe1zVA`s zae;qeMuD6$GyNvj@nfmkj+-0tznmTxxmiXKlIEXR`mMuuTBlKQcF-9~W)BrOFVF@D zo`M{F^u(a!5icFK`?mwpRY~QsoLS5a=Fk=ie-^6uzSrGYP~p}m@yE}RpCyTim6fus zq4WEDooJw;sK$S|SKNy{XiKwlVxbLUUT^gRHW%N4Ty`s=HZu{3YGSY{fTq@$@A$5s z)!M7C@K@h*?3!^r`S0KM+_BXsZ0A@7n~jg?-up*dQGf`r+G9DVdZKs@XRLAUi+p8& zN%re7NUczw|ITI5GR7Zz-_t(RjI>m6?r_GWHa&dxYuyHF_4?|KV7&-C=JkW>GY^|(wC_sf9ZUpuNvkHB~Ywh+gjby}ZkWg~T8|Qh1{s8Ao9Xe+-{OXWWnHnEQ1^K-3iHq)CAa{tfOp zP%JXqahM4q08pFs?krP%gv-_aw6wbK zNbtro8V%nlnphA1g%Q98J6U&sJ1GLuZ~N7pgWDiM9Jo;Gxd$f$q@n%&y%w*E+RhUmISFus;(OmlVBF09YRwD=fG&H9=tc%)=y_K` z%qM&G4H5l3A;IxPvw$sh0Ol(Q50()xQ=vACf^xNMM)gg4a7XT@Fv-xH_`JPPX?I2G z!w(Pl;@N7VmPQwIiv6a8Kz1&5xh99G{k^^vslgV{ywv0~ZDBb??lCL40+eUNKrc-#I z9DxIRalHjsH6VSfS$NN7&p(kpZ8#8=siKz-_dR@PU}HElRKY}f-FEV0ht+b_KXmiv zs@Db%QuKYl!M}@_sl=%0-Fmq#B@N(uqSMvlcK}3~fso3o!jTdCZ`g5rEu`PdTUIIk zp&CM=jZ@?+O!I-g+;Ll^aj*1I^BADI=jdnADvOdjUJTu94J8_)L^4hG!fQs6UJ?Xa zXRSUU#^CjoQ-GR+wy7gYX|fr^qI*X;vhCh1n1}d2%;!ibTZ?p~K^*IHovbq|sudaj zKo*Wb2rr3%)~a{L%nO0bUxDElbC);A&1$D*YVF-BvuS27EXcPV@6-EDW`*iZ2b4b| z;zRe8G31(H#=AniaK!<`MF69sMLg;HdUH3}+qYF}d|KLn1Gf%cD;n<|W8b!SWf9Lo0P&6<(jm_-90w(aFoh>%8zWT8Y!y@Xe_h@?e>_qEG`tl>feowF z`~7!?Ap?85f5vf0uHJZ_olzYD(S;3Zg`1{Fkc=Am*<6f2XD?Kphqk$ihKtX=h3xec zRjra@7x&&uR(5I)z=7w3{N83zF0;(--MH9PSsxM!JFJDDb-h@84V;Iospv1l$yJ`9$1KBAQ&urb`i^>updJX16#;Az4S|D zWwo!CLFkjLVN^7nUvl}T$0%gdH*WJDs^{>^GdFZ(%r|QgJR(C7F{xU5a=u>yonI2U zx=INtz>Ok%h(Fd8S>5vB!EdgeLhaVt6SSO185K`X^v*PNO`V`$Fxnea=CHb^x*R|T z!QzSehKAploDK)5Q0~6n9q{|+rBKrs{&-~lcmLyLOkuOqUIX_aK%!!~k22YhmY=++%AZCoTZOwzoYd3#?K(cu`7{Nto*V?4&Z#x8gk+OG&L7oR^ z17W6aEyz{RQHXofO=-Ph$31}I?6xmYE%fjF$s*ee>6Gdl|A(CNgI^L$?)g`lS=EM? z-94NaoTLD-e%FptWs$z~BR_0rVST6raskqNp!6V{?gU9vt~SME5Sz8%M$d9Bpf>Et z+pqR_l1skInH0no8&+tH03s;Vv=^?pcdLx?uu9FShj7qqj&!3ae3AQ5Lk`Mw z=cU=3Sa6>kYc$YXE72_y5gHE~9BwVVCt|S(kq9jeQHGpEAnISOwn5=^VpqQC`Qsi=rt=H_fIp zra(1&)q=t8V5fM4c%{4d_((oq_RnVf9rl|plXVpcleQ;(4H8MzxsIM>ap-=);Q`Hw zE5VO9ZojMZ^_KIpO@#RAN^gtAVJnvOM2x9VUCYs4$~B~VecwaO!h<6H9fXha)X!%* zL!*X}LfCPk9*>ux_*f5MAH{1*5LVL6xr0%VIxzBbs1CtR4ciVd1waRSO4K&pLPKSR zMqKYR=$)q;Z$CqZ>znU)eYRDW$-v*(zlG}ZN)@hkOemwfzL0tGc=}9bQz~e4X1-2- zTr7TCBGMF?FVojWgd4rpfNbuVnbo>uYv!oC-4HSUh8qWdA}aK|-<&VvDX~QI1Lxh^ z@Cab&iuue?=u1wq+0e+Hw0UKiE3T~|z{GdDq5Nnp@=RUbvctjF?lfxl``WHU7M_XO zUu8hdpiwgCc)0}W41!Zjew)}xlVl6%ak*oc9kLGvYNd$0yIL% z2-XDe@L#;n3!ZP>*p($wF*tAoxI}NJ;Oe-x{=Cf)p=Y{!TX%HDp-&7mgJ^OSIybUpM-jd zFevVIvyW6m?R1(%{Zqsw1Lm-L2h>_b^bQ;7eo>+KR+8FutYh!Anq>5#mep^zMCyhDDJZeUAj2H-rUclRzjm?W2Q82g)gQZIMAKBlQDW5Vj+{3@iS#D?{pao!22PJSD2kMdId z75TO1I*GMjgeUb!&F4oa@NJgBKE92VeL3jG9J^J}`0ykS^^SMrjO(kQ*7HD?%$^`S z@+xdFQwatrvI~Gt+ysP8&HynaP(D2ut@f3)&|5r|(*5v4@!|gUQ>U_JOp!@Kd{O|@ zXO};4vAS8=A=5KEuIe=X{p11@cc|E1)K2AhC*|k%U+?#Y8d;gC^@?Y{g|vp-;3I1| z_R52ofl_XUK6;MxeXYyn#_g2PCY$;dXoDk<2JDMkA#|kWu3zp$o^%GZTB2O7@RW^) z7=}#8FSnp_-Ngj{DfaL>6S*o`Xtsl9BR&{(jVF5@5Oz`4pAkLpokiZx-#{!UL}23( z8@ffIOsjfQ-k&&w%v@~Va&`x)17?^Bb|CX)}WV*zx3 z?z#;Z0CP&Vg(g+K49TPKfoTn_Ew&yWddRxHC!wK1+%bVE4Jio6c$m7qT@I?4UbDe*{)2N#DFYTt8!AgNR`=H|} z&IPy2tJByJLv~mby~`z&)2AnYV;B$pL!{3UX7^57gSWijLB85S{UeGticB=a=(qex zYn*^!R1xM(b&xMwMdUx{8GF;!5jNIPyN)Q?quP(#0TS2!iWgW4<(b0c% zRd0X^wk#l>WU41*`^j7^_LQpccCl6h(#-yPUShh-V=5;I9CaO&pVx0?2HBSFc4Yv_ zzX1X2t;?BTD|T})3E*9%PKgj+6eobn0FwT@Z8b1B17PO|eq`f6>~tu3_>$78%PQT! zM}71k^>f)!_ga(COxNfg+D@{s5I9lO@G=#6>LiZ2RlAsLaol@_$sH3s=>k4N)SI-p z4!Miz5+;$$;pFYD9KFNCsQALN(NUX4wYoM?V$)92wmuO&)#_x0thXE={4KIPNkgOfw)j$ckng>srJV;{-gmaXTa@rZk`$Te*V~kl-@^o?d2vJG7e|>8qF=*XWs(UIZ5C6f$1}i|=1= zdGO;s-KkHpp9i;=3jJQ~hBsY}K`4@TW=-GrP?Ff`Nxf62tQ4{xN>P&8tH}n&mCnB%aDaSFA@b|% z0`zg6c!1~j*j|~x|D;{Mmp8)#`KXZw<&Ru*P`&*)9p&P5rvw+fg(!QD5&fwYoJ`3M z)O5M9OiaWBKbKH~YdEt)D*gtF6rm@>d{|dBblf9yf&APOI4Ue8=TGyiHD109cB!d?{f!6X~*@@}u^K8en*Y zx>Mm$45^?oZ!Z}&wwF8+xu9spGnM%^U9Z5Sw7fc>oE;KFT~6dmfOB3#XrZ~GfA-sPX|iT)sy!Pl_V`Y-$Jw(bhT6Q_sf+k zIY_IPa2Lq5zhaO?APni1!0xGB{s05k3SlMuP#+c4R3+Ryl-TvhiAWz;^D*#e3MZ{* z7>`)2?HHuZRL>gNw|=Vp1hPe~WCKm*m-fS`62VfxFDE`+y$Ejv*kjcw^Xm17Ge8Ax znUb<4$hFN*6zzeUB<`mP@knU6qLEYa6#KW`>;HuE-D0BwM# ze)0G98&l3A4W_dk3OO8z($EUP9P zJ6hr@e)MUqid<_|L!Q^v!GPW%+V|@SL`2POSAHjPV7JvFKi~aQN4a2F zBVWGc8=)${+#-3awFJsJ&&950<;FKJm96`%d$^Q7J=$@Ug0kLDm6gNx`9@CM_P{#B zd%KHw-d~fsaOZ5QLFCEb_t#ui7t$j14E5HXs8fEKj6Hlt3Y_vS(WOTr!O1g1`JfG5}QD3ciY*D$_%8Gy$CTTb| z^=VSG`K?iu8g^8AxG_(#s$2lRR#ke-kWHz}(E@5nfpUDD^!(JR7hD6&gDPG~tX<`g z!6sNmYhBXcE0uNOZW*#uoU{TtKt5NkT2)ZeT4R;Y|BWq@`7L zqF;*5OHfwLc{%wMsk`;@Jb4DQwmgpWB?WR-kh=X`#DRL*M<*sqsr$9O@p**ZWh)z; zR(cR3VMhwQduImXneR7)fQ`TF?S5X^R|yOc+p~q)GJus~<*NDLcw+g5Rx_=Yv89|X z13!dbji#Ia1Nux)zQPIMG8aS@YWqi8oK}q+qm^pB{kA9`o$I{gvv+E3duScDkC~#T zMi7JH*9z3BtkmcfI%5AZ6D$+*XVAUI94}I5g zT7ah$#&9!xFe5hdGVx&IkbNe=VZ>nfL%3fZOOPVcRyO(dmC!*q#u-by9wmV>u6n=E ztZVv=Zn%|jpS7fQ4?|sk&B7;LD=OY{VWxDKRkb+IjJfN)9cO?^_iaD&G}_4hrn7lq ztCO&+sXP17ZaOjMEy$l-q&w*bVJi_J#J8YK!@t_iO5JfwPBs~+#0y=oM)MBySaY+h z!8U85*XN}yW*6-vcA;xRrzks}+k+Q=aDi+D>(245R+Tkoq2Q1IZs=LKObP41m*YKy z9`LOl@Bx8bPi->ncX1Ns$vn1Y{(i`!he@Q@qqe{9jkJjO&HAeSixMjZ-LE@=WAIhK zploAi*=d^i5;?`sjEz?5Pu!w8NLDzyz=rb;_AlRef#-QJqJA60#q0?zX1?hk44VVr zCMQ$a=coMM`F^oLr}7Q3xCXEGP-2D!9Mvc$rmam5q$BcedU~_IDOsS$mb|g_^88K@ z&79r`f?fE;;nl)PiQHGO-+xIjyxM~eH6Oa1Fm-b@!^&ELq32Tkj&?#|(hRsk^a?a8 z;)~Z!DrjaG9APIk(5T0bzS)?hHy%e{iI8XjL$C9l+nh)-*WTiKmK0&ma=qDVt3RrJ z`{4sx$T_Dtj@B5lnv2}uVm8OQZ7iiKH2P|6A*X33^RK{thzL48nZVDy4n#zWJR|b% zsMWg;@`d>Ml>^!tNNbqz@EU(l{9$-)7*|)c)nfDZEnB(#a(bbDAJ+liX@OOXRma|} z8h-Q9Xx!qBKjuWH`|_V1cd``SbP9(Yb?!S?96f|K(i5GgN82Tha@oEW?k#LD4=)S$ z_E8yGC%w`s`}WOwz@(vO6`=AqqIW8S)Xb3;5`>A{?>}jwZ$NhXOpiLJ3NRWAC& zW)*<#iRFRciWJ&jm!3Ghf)lCYrEkQ2xE%Cd@0D1q7Shh%fpzNWP|&^RU?Jj~OzWb& zUFx9i?^pik#KrHcK$sRvm%Z0tr6>GKrid_qOIa zk!iixHCZyL@sejxg*x_KW>}EmK;50M`lN{D?oYbGs_a20d4H~%X;wA+DKfa%acI8w zgTTDbtM3qw&3bp1w*+uL z#~134V8Yxix9&9OQpx*+@J|%p!AMBptRTt}uXt7d> zRDsWYbNs&0=gf_!FL}MvVk1ffL1HHFC z7>n_T+UXp~dsXLPk7u-d!eZM}5H1+_98khb@?kVLlmaz;vYH){4Ax&j^ z&5|_l92J~@msQj2!E4?RsV#RH?PzkXKJf*2-hV2g?t=b%>83<|iOpSj{V5g_KlPGR zZ=UxqV7wC_Si?>6_a$%=PYN24X~&z}c{^PwwcpHWz23y7Qr<*AH4Cd;?VJg{xHSP` z;4@!)mX1-4*Ls{5r;l)%YlnP`vDx?ifSM4j-CvU{HSFRF+qCb)G7VnWy9Eoqjj#d1dpf%iPcqi8Ci$FE_O@s}+06fnqREVp3J*DVPd*D9S0X z(0(10;_NSRixPFVG1+xlH;v7J;yGHpJBhw{_&sFa?2%Ysncg!_ONksPSHgy%A3G!_ zMYYLJhv?JcbMX59kF{i)ef{QJD0SiN7q}}NTyji%eO+)H`8qxhDP$I@I)_s_BaX1b zW0OZXXGg?$nBs`xqV_l?V-K}();;2_y+H=@3V)KI^M`#a;uVys>&W1Ct!SXQdX;OE zn5lURllX6L-of~dUO`^=engGX{#CCVDRJ8zc+8OCf8ro3nuM*tPWi-OwQ5%lh_p}_ zPCSvNGf`16D;xS{g`NDB$4T!pp0e6>h(hU*_5>f@nQ;D{KB+e>tuK%CV$J??;$RaW zu&@^X4#y&8$Zvttf3HylOf6NgXL)Gd*^7cu2fOaIX0PUxZxuPDNNuuLQe(|CxUT2F z#05VXQCYDU49G&&4T*@XOqW$quP6HNNF6N_P{N6)X>L4Kxz!D~%){6V$E)8G>X&0) z{c*Ta0!yC$(ufiCIYcI+v;rnrDcVEfHzorGLvOy`x81 zG1NbB7XeZXthr!pGp?AoZiB5nFxQm1H=)eA)tx{t)mSME6_`HV%~bC~{f5V;MX612 zG9|3bSjsIahf%24VzbjcnSU)FS;te7JkSqZ-4x+D`_saZA3ZZHEEtxg39N~(5H8+D zkmWn3RH5;o_qL+{-xb+aC!Q8sb{NP?Jv?Z?CD4oBpe^+sudk2LwPWn)khFVe%XpPq z??-)oh@U@`LMU*g;;9eo8V>iDMQo%aI1%tS$*UCkh3*x(t}d6m9y=e-DyZ?q~xT?Uq>OyG+*aejmg(ns+M&Z{FTM&qmp-vU%CBG1Ea zk@lHlJrne82T}!pcn$xmn3Vd-=DWpHcTfiFH&l=NBr`xd>V&GSiS_d?UUacIvI46> z0}ijollqk5@hom~qgsN~ZG`=y*33TSDI@@KD($x-Mtg)>NFgZF=%P2h*R| zXBea&c8ha<;(4vbgVhNYbv<|;eR}0;ZZ$YVT_r^hP%_k`xcfw3uWKO`Xu^k~u=GJ` z^N5cGeETEY=}@ejwFQnjj;ev_sEF3!B1VIgp}p86N4^%G5)6;&z}6isGLqqx)h;-1 zmv7HOwGPdD{7WFL z&j0T+8E6=P=jvLA=o$}j3v@L1IfABuVK}cG3O-ntRMSx)Co6-u+cYgs3|(tl>NjWS zA0b%C%a$cu=9e$g);wFlS#cD0b}xNrSrSlIM)Q62l^p8ukdB2Vzo!XudZMsJ7&6wZ zG>L0$PUb*B-RVv__pQw&Cn_v#2}qHem~>;87wp1os7JjC+xf>VXYRNR4B`e3X;t|r z9u!J|(|OpumMl4@_igFX8JvkNe^%o@o_3LaTl3=#SF|vF03>&+a1_3{^HmW4p;P8g zsPfV1i^W?HRE9ndZsJFh(wYy4|>)yIo#=c43V_h3ScqHLBo_T0Gx$JZh7Wc&{;u--L0OUtleq z=pJTSSz+DEk6hg-dla|-sNjbNK&x5qM0?^ZyZldUjRUD1YtUqAY-nV+4_7~=+dG>B zeY;ACO{-DAyVQ#D+|z$a#l!#R7bm7HtNk;C=~xGsE4n7!gYECV>T);{y3-T1rfoU2 zOr~2K$H`}FA)lS(CI-*k>jTpp=~!+RUg)J8uc;6vf|EHZ$c`sbRV*3 zToLr;)$w&p$hTP2L=5k6im!!n5v4y;N}JY3gQ3&kpj>Or6Lw-f+oWc;C z&CG*re`x$*-R>1PpILB~0+VL=gaY=3?~5I-fyp|5=w4WtA{gWCL)$l;{1ER`wn-@_ zt|YK7mq6Y$Z+#dmOvuSE>U_{yU+)r6J_xL8J^1|bazF2y=oLF#cb-d3n@tkGK4pio ztYV|W-xVgc?I*fKd_~g;HH+?jH?=VBN3ctYP3pvN2SP^lVdxd6R&hU=FvZs#{?bL+G@txY9>4J0>-+5j!XTwK(H_k>Q>>1qRzI|bd-KTBU zXm;;LJO#ZfSL&jtFilU!Flj0#-@Z}Y)HE(>W-r$4ex=~Iptg*-SiQZpKgPXaKY#k%!(D`DI7f|=UG5*t3}kw2nBzBMgiZ%+L@##lQR?ZWm!KAy+Y$@_S2YFOUR=9Jb>e2dgqyTN>! z^QWk59`4LEqFvJP#Orz`BOc1Sj{;>p`KbOv_DnvVIyFIhbc(-Og+mI{oq^A%GkfEZ z`l9#ij93X6CB=-H4I@k2CvksaPbkj?pS9eSKy%_!V?WiXQ=&u@i7aR2U@ZfBSu-d{ zO#!!Rja|9@9hgq9@C$LpgRn6s?e?OGPG#OxSqQ6sPud}+no(Kv&w3SZdgrOU*x9u+ zf$W9ChoI zg>;v4+RS;Fxo&1j!ZNNi748gQ)N9hm_pl}7qq0yg_U^2Y`yt!LKSBm?UG1|P6`w)c z|AFg$l7aOQ``?!*8%7H+>?!>gKNAdz=lv-IXEi1IH;t{fI^o>1cCRRkAIuz>op@Zi}^Gy$&gDbKatd zCj3b=$ycz~r%1{3Qd%iD{EF@Rp*7*~DXTQ!`kMm$6%-?{=2@*qm%O6nznlgUaZR)Z z*5^>cO#Hfoxv*ltvKCY&_(U?*y&N)~r+^x~r zn!~qhfl0gRQ9_7|VblsZ-7cBwHToBrPjW$){~q_`F!Fgo?2VgII3}TG&hI)IyDw|7 z&I3-m8DF~<^WN&(U9`({cx~xI``XEg3gxJy5cKB=e=1R~irK2o5}EtByA-C+fry78 z^dB}q>mQa-fg&nHTCY!Qh`y`JsMaB=Ry+mWr~h}VBwR2)?)J6fZrW8wEkXpn z@O*O^mmDTV+Ls?O_D1i(EvndD45{rgUW(VqN*V5PxlhRx6j!7~S!3_8QqnPj{?SSfyuUT9kd2MTv{PYQH+=FWh>*;8uOERR>`T~%zU(Xi)}XU_^OO0rSQ{kMr8 zN&Pn$2eA4S?_5*zHapf+L+kJbNf#iwAMYgTruVB?x>?aAzI-fTH=$_=giaGR%nN=0 zxT@!8o3p+rMCZwAB{n{q6jer2-?#T%ipe)8C?4l7DH9gxIFDm4L(VJ+U%xPJMZZtig=P|R&IkjhL2rb%uVSml!K z==EaYRe?E9y!oa^g{i%H#kWfA@5yPM{$ERV(XPxhGrF`K*i<&DdfzO$g>g0SJM^|) zHX82OmQ9;{Cae`sZ?8JIi#O|?|7)ve57Y-9nK4Ik1kx&W>Tx!I*-i0@Bgt%V#gnve zL(){;tcgW!Lx*H^lgcNBNIk9MuaWT9=m}p3E&sxS=-WlgpM>WSh$fhp7^fqg-g`YmoS)E%M<)i zSUdA-);9AZ<(Q1Th(h?)h^z$k5qU7!njEChG&rEVfVJf757$@~YXvOB# zd03wJOjn+WgpsE*_Jk?`J}B;i3$*qj{rA2M{D3whPMv;$4w&nv4CRJ3t?Vr(kS-OJ zax&G(Smrky$YF%cJBL%VH^)Nbi7&9hSXVAzWU0-ucQvkhd_H?J) zpgH@7U-%~5bkd-js%4qUHsb?Z${6-<{46CYsz@vhPJvdqOJdkox0A2_Wu zR+>B{&NSL=SovUT@$|c|J zI0vAx4B zQ;RA)mG@ogr%TnCh9^y$#|TC(t7BseTl4jxzsM$CHKXFZ+Ml%91ozNX9w~wsfGih7 zTCz&a`=Y6=??gk!b3J=SA;e+(D^N|7s>rdP`}3F3-7$%|s~wo8_hzw@_g;@~7`(hR z$gL-#?L?03ect<`ml-eK?KP@@V^5TQ@#b5;neXp>$RJq*S^0QhEJDHWaM+2I^V-Ow zm#K31=xW5(#7b8S>anpPYoUGh7wJeku~jAkTWcN<^h1KjsK?4$!4z=vS5^yTBI~L+ z{{sBwu5`i6IrFO&I)2bRo!Ce&wMS-;bPGZj;%|`SNSbB*qBDm)c6~J6PaS1H5AM{8 zLeh1^6fs_`T~tLaHT@1f9VRqu3Et7hf*$e(uFdSr?E5vu_QcK3{cyFCV9!b(hxX%A zsgVoI2#}o&a6_|R1`BEc$D@^;Pe)V^V-B(|?Vz1QOEwnn zNkA+cun}x%wiSPduWDBs+t-*eOvdU;=a>g zWa^R5@PTJ+KSxI|E|vYFUn)qy?_Pai4RE+8-Yd6NZMVGBrk#d3s0f}zCQ3+6a7eac z)rT^yRM>PEnH)H0&zxvZL!%HrJATYB`GI%Cad zmH0QR)=YQ3uJ{#bQ=|yEPcFfZz}il@j)V^7&wP1n=X7g2A{E;31Mo>2AxsteHse96 zJZm$9EJ6*$Ti3h){gUn&|D?Y`-s=5?Z8KMrdTpEy#^QAt|Ee7G8UFngApVfYoNFxQ z9F%MRVka$F+5V3Z2|aCf_Me^oXlOyQ{V=Qs1vJa8Cwpgl zoI~|36IFs#E8cd$JuDjQoifWm`}~iU?xugSmFnS(YmDQbch~M{%9H?`B-3gk^wZ|O zUCU@M4~Do@8035@FP`Z>;&S;FcQ3M|V5)0_sp3YbU!4S9JifQYE!(aqw1aN*gG_8$ z1KF-_EJ7nyRk29j!EjPPT>sWjU)GsD%F=?zQ#N}!lG95aBNS0B+MegTui<1rJHJ>N z&}O$CjbU)RWE?0}GvpP!L5_xg5!{#yfBOQMzDJRwW&T=#$)d9raPfoR(san0VX%<{ z8wPUij82Pw+2n8fwPi3l+=NCj@VLb7)$C7)EE+d?Y?Q?)Kn!*d>vfjW2cK7lwdL(F z?j!jw9T{3Fn;yW!`1dU)!y`{j!mj>yXHV(hDqJi4za`LEkQ$;&$f zqbd@;zuP^FO=dx*Z3aL-DL7hipThSt#AEM_KIM(z%_B&s5bu0e*dUu?@Z+ffwic@)#OuJE$*w3zXVBHO?Wa)~OepvICGiCdm&u5>ooQ`~%QL zfyEChdO3hyD83W# z0r(c)t+s&P+j_)%+pFyW@;-zG%a=j0sl4mJHfz6nwd$dytQ+I6?Bvf& zKIZ*;I(a~5^8{Cl@BG;NYu5Lrr9|UBSQ+Y*{B0@Oen?XJ4@2C}!LBmwX!v(gf)Uv; zcy}qoukjZ!y1cOX-^N|}ANrv)Np_-%zy@ci_g^=)$Ev1kvl(K4OxmR(X}{VT=jZZ# z=@VIcJoSud{^;-Og#4)PYuHdM8l8*b(DtVb7 zjyQLg+0yhC7pZ7S^%|`*bf#^?LIqmomd4$)9^UA}k|Fg0$|cIF`|v(SO1EEd;iBIS zC%;_3Zwa-E?E3VRm@(mRtgX^1b1?I;h$KDS0>1ELeWW<-{*}8HlbT$vk5nm2MnUBG z2dUxR`2FYl%o@ZYs8L80&Psx_GY&g?WXWC~Lzs-_2I;RX% zEPF1zs_0>0%q}FR_7Bzjr%H-e;sM2r*S{#qSES?PA7}IDS7*$`(dO*0b!L3D9|h;Z zLdah~6lFcI^zcJoEY|CXwn=_W!G85=7GXY`Foo!3v^3uQDt|NsU{iCmT+y3lb-*f) zWe7)zn_qQs+boX(*`b@ht+efI#z`>gsut;xlEms*&}G`s?c(qQG)50CfJr@mKpVr} z^=#ub`6{!iq7Qq`1A$AYcMmdbGr~CKKsv(1?8QZdgY2kkq>g5x7v0SuGxj(WE4||{ z_)O&B8mHbE8ZXUW*(| zAZ^Y!-35;Jg$&ozR;pnU4;9)(%XMo%W8yh0)f=Gq-P|tr=^KyAZ8kFzL`h_>0noRb zpD;?f@|_}@rJ91M(d$%N`?S^?7b@0l${A^yVO8dj^s>Y5W%{=cbJ|_h`}S!8R&9$; z&kwu7Cu4p&erG(v5#>rL)d48VBMcJAntBsT{A-zU8(9wHml-x&j-k3^0j$VkN(X$i z^*J{n<@61#it`mmWl0LsJ~SIG(Vgm8A^&`a7ux5NRS3>8RUQMs>=&Ah2Mfa49Uvur zB7fZSg*$_?|9^n`H=25%^i)WQoVvf|Lv7Cez&x;A)I~&kPK<${6E4oNrGN(RMgP4q zBCsfjjH2&vv{_GB#uVxBGx0!xnFvYcz_tx?ib)@frCZsJmtcbOA24m2?Qu7TSOjOp zFP;&#-KkSTCma`B-LW2JJ}Ozyl1$cJ4hu(8nW)wOa%5pPo`l{Y+Cb4c13N7HE&rJ8 zoU8wTHu(>u*(=3Wb&;sUWFP8uDDA0LKKO2@UU@v1w4|Y^?K^PCBlVxk!h5298T694 zjc3~<38Z^k5%5Q@OzpQKdoRpC5JeAh+su{-wJ;H~?0VedRg8pKQl?sR+Y&i$>?!A6 zZA}SvH#hn2AEKK7Rja@Mo}92|@e^Oc{=<%lMG4J8uv^NnFL>hvo$LILvEML-U8vms zwU2G`Qe*0KtP0Q7hFq5`so-3Bgv@P_8SdqK9rBl=Z*eXdD`siv#dG06Q;;50&~U!TkBn;Tt=J!9CcjW?+^Pcp_y0>L zwvvX&$HfyZQAwgNM9bC8ioYp_0lp>9`s@Yl+)Tj7POJV5dQ_jwZRzU&^a3DUo5Pbn z1%j-8>Gp;WUY_6Ud~nV^nixZSnY=#uC5J*CIw)a6I0^hTI@nqB7`bABI@O+E@6jMh z1XND3dx3Uj|1Q2`jb=Zoj7s?^U;X$}82p?H986iKh#31x?{v1ao*KN3xz>j5IGiKC z!g9ndX&1^X3}kFyn9E!7d0ZQU@VXLM)Wr}tR!Lv7mptwT|L{P$)Ky;aWrv_&q^YC( zxO+YqhK{}k%v9qU>6QUj>PMiCnR+(4;pwB+6B|;T35OYR?SyP}T+lBKI+ZtpEr+&ZY&jq@tjjUQIHlods88J?$xJ@l?9380TePB+ge zxTM#7KooYtD*xIxz?zAg57_$VBUynqDlJn1A3^CZ;C80`wuSbHww3}{4%GLexD7Y6 zz7neQK$@Lo)18<;?U4Z%LnmRhMp&wZ3azvYJ6=x<=2m({Z^o2LN+5O;&Uj=oH|8Y{ z3G1>a&ZOW9lc?d6jau{OE&AmOBYrkex{&j=H%pWLOFyWM8r$ ztZZ(nfj48o8x|eo=3iS9%2Y&K=6Ziz@vfrBrp-&5OxhGw$JU=I89UtV7h2ox3J`5J z&GlU|zv5#F8MlSCyi^oFDeZ$N)s`6g5l$)g{j9tqQuBixTX7$3)F3v_m4l|EN<%v7 z%XeOH6XVa8~a#@SJxZ(;^cs+20MhvR=92au9j6m z-V`B@8gVnP=Z`JdC6q_z3TpIS@wI(hzB8KDJN!414*VY&6UO-)3Ze9dv$O6UK_>0f^0uJ$G}4(oJ`D;of^W4KU`j2CKx@r{<-1$6{amyf+6nf&4vNQc<2t=yBH1|L}?gkZ%Oa9JhX=V{fr+*+*ETb~8U<7BO zz75Y0dvTF8{bg>wpqUh3Tj?YRtS5VzmePPk!6zSZFF!-sRRv2`ytphE)Z^(7dw72C zZGa0%*aizs61vJk72ZypXz)gFOxtJMDXoOjl6;|DvMqFEEc%Pt1y#n??qobZY_uH_ z{-U>59ePoxt1E$6?5ChqWvE7FCRL;nmUARqt%FNS7V5w7kmXf*oRPwx2pjr;Q-+*R z!K?GqI&wcjo3+cLs|f(6_J6xaaUJwvKA`^42I$EpG~WL^76+z-Y-3YnDWn^jPe(q- zAnz1Jz<3*`bHhJ{2IqW8M0eXj*%#D&5-N9E{71YNrqq4It z%V{8LWclf8>H?aBbRBo*lkke7-DPjg#@8ZFd662wM2fnHB`J37eq!&ulk-Gy`>X3- zfmMAR%ghSvuV0piE#F(a+LTkbke(&C)R60pq*#Dk9=Q(QJK?2s4}!&N{Q8BHh#(WW zd)sj%ais(bS!t(i?r9vDLiPoxARE#fWV}_NJ)VCD3l0D|EG3Cm5ub>{?`iv3oW#bym_~?=W}$n2QzcO7jH=GAj|C@G$uN~Wy99)GZReRUhaM^ zs~d$#@f=1Ks+i`i#_#u;PWd% zEENxQLzPmRYps$lHrL5xtJUg-cgm8H-&s4w>fT4WY60!aD6y$!h(lkQkCAz#u#20x z>{ufBW0a86E+acP@_oZuQ2cC z_^(9J3r#BB!ND|qqL?$u^G{XWEB$|O=Vg!8Hu4m9jhsYp{F4*b+$3dJcHRHYG1y*0 zg(LH$mdx+b>t#rQhi&60b)^rDmMjp@3TI$?Rf zzBBjg-c@O|TGRHO-NDKBu5+(Z0<-G&jJRn?_c!`p_2FJD)DHcAJf7fdR=RMV!+7iY zDQ(KDI%{>Dd#utr86%phyqt^#b*7XJ5tcS@3J+UISG(mOOa+UIAZzbL+eK(6kzZ2z z4ispK&vjth;i<{qec2+A?L0$w5Rb9?Y^4>f(YGN7Owo{RIdR2%JHMQJOL0a`Vt>@E zk{O|3VPvomxu}EDYPOn)P=|I*JflLTs7x8J=><9MhTP2`US6+$0|d?MgOIlm7?=o3 zqibZFTLVeS6aY1nAB&14oaFwwub-~|i{X=1Mn;(`E6W0V_P9iuuCx`f0Yc_V z(hnE}$xa7^g`8li19IUo^)`XNUavD-;ycA0XU`$I_3CVk^u|@P$KlKU$A5XnfM#Q= zsH#e0i$jgE`Du(0$9U8%LF=iJ&}2II8WkJmHP=p>5}ylb$&p033Md^+6@@5f3lvK) zQe4V@8<|cQ6*Z2Pl-(g7l|T82z%cEu=pf{-qld`{(K#iy7gN&@<{svXFRAx^rk~g% zAM8Z4c9mwkuq(W(z|9{j#(SMtdPc1WGG8UYTXRLkpDM{#!Ka$VGJk}EAbk#VBBJTI z>fWO^@mq1w2jk4uo{&iraCc%MmP7cNhaf#l+yM$(e{9I}p>CMbN_NjdujQ)++|3MQuU;LR)A8-FXQZf5%|*-bPQdy#Xhgu;LQ$ds1K>3 zww?g6*-J$Do|!Mu!S*WO|0diMyo#y9`W*$qD)0x#;cxxi)h-DFp6MgYj~}Ov<|)`g z{!WnqMt4W252MJ}zI-~tZ62Tj$KA@3w?a3-vW4uM(@jz7Ggu4flZ4Eq(_4MwOHRAv z;vz*X_l0cAw z$X4r!I&>Hu6aHFBLVKo?8{TMAD$@6nxG1@2+U@a4-=S|>v-lSF_gpy0>p3TM*n+4+ zg_*e7H)Pefy{-mTh)OQo+SG4&;cWe5@MYfxLP`;mcW^jA+)zl9qoi}@A5@q&ah>T; ztY|;;=jCS9iCrU8%lTb2CU#wjz$p9_verUUq&0>r~vBSnKr(sg-5nTe^kEFCB9LTHY2gl6FsI(K#9DM-6e zQ$w!Dl0GSkA5b&>sGXvq{beimOV(!LO#ov-6t*_xPiG%s{A%3KD5@%w+cHs$!Reg0cq&4uLb4V@mGeVE*)}V565BzdE^!@mZDBo78~1&Z zUNcjOci$#v>t>xWg4c5DDy-3FTf{iZJ^!X)?^Ile@HNA6zfZ4Ks4ro!9a%UILZX9d z+3UE6>z!jIHs}V~n3jV-6x(PDm+!j|zm=4(7zYjbW(6O+wZ~gUdVH6Vx`X9~z62F1 zF|q58|0zW7Uiouimsj0`PUk2EFb&5^?9GF4R4OD&E;3-XU;AhSBon?jEOi1m4q%pW zWKBcuzqrYP3%Uy26SsY~de1#S-?mOxnTdyw6!x4^6~Utb=PL-)hVL2Co?6XMgHP0k zsA`;LE)y>l&qW@MJomF7H5e9v3`SW^#UcOg&@x`;s*jru@ROth3ZO(AMP?Mca7iu z;9eMCoOMb+%o@?>yC_kq?J!Ux_hoxmcOJjr6Sv9s&X2{^Ej@X?e1&26`vI>fLKHn@ z=ydY%Mx1ea2nwA`^Tf9-wLZ#A8!Z!}F~@Rmt;*nT)I?Tpy>s=q~|bFsKVeL(>9Y zBLYgJ7oJRzWI&Z?!Jfo)gzA-nW=grSfuiYT@|ap1z-UZrGn5Dm%>>64Q6&__hC1$^ zKtiZI>c^H>()RA&E|Ws0OH5_Uhu@MJ=9J_BkQs&3zTA?>cElWT z_}dfIkEVLND$9N8RdbP{0UpOjM^6sbeerW??YeRG){e*(oNNh^DY z&0gpw5suTzLP@SylI3u2N>w4vl<6*q_-Dd{jB?4^Q3%frFdZ9m@Ev_;NAlV^th6Qy zFTT{NDmas|$Ri0-9E@4(VW+$U5Z+^kE}g4inM>7d^#x{_ADIxiNMq2Z2<{H@fG$PW zc$hl^b0Tukz9Zu&oan0))7Or*qph%g8R6)xV0_f+u?Z<;+bL;r2QlHe@|(E#s2Iue zOq&PuCyQIkT0&c`L-A;EniAy>=WZ7hNxs@ysm2ho@BgC9+mSP+!OGIG88(h#NTVrY zLNZZ-`=jZ@;K5+`L5O()Er48W`F2%``d9n)g%7!`Es6amHv;=!KNQ8n3VZPNK@lJS zhfrTxj~JXu%nfggyT0w_N*}ixGFF%}_ZkpAc%HA2O7hAo2}<*KooNO%he3-?9yCZV zN16a!9BQ6Z)9D)oekf&<^P)N6&>OttlG`O>WA!cGZ|q`3`Z5M$)mWTlDf$d3@3Y%hF`EUm_Yd#R}IFz0#N zcL4L)cRj7*Ng6_>AhW2%FGADz$gh?R<1PY5d`bUfAo2IJn%;nU}%=wVgb74SyU)QlLnGzSgAhE8(T6 zQPs?m^EZGgMJhC)X9W8S>N}KheH}=~-wYJgG{+{Qy2t9f3mSP4FJ(XSdbXyfD7-7boO#;mgK#cgXqDM`@0nANX?p}BiSMgAYM5Y_NJ zU5t)$_ONKV$94QX-1nUXB!Kpivg?;$;q7OCt4!Q`LRm3nj3vv(nAO}g7Q3$IQ}4eY zU$7>!!Zq^Dk3d6iiv|d923#Oo%AK}vbGE+nyHR*pxR(RqWp%~u_o)^)!X=rCzF zPs|&L&BlNDP2i}-_xy`3T9?&V2%&=5FmqTkh)dim}E?o7pU-^ed z>&jSu1%7OAR12xF9{#%}2nWr=3a4`_w&TQ&gM!gp>yYL>;`KYu9bWZYL3I`Wi7H5ZcWSgu6R_h76KRpB+;-@8L|uu7_5 zm$>F^b+2KE^Rtp*RQ=HnO6BRD4}qVnUVcP}#IeuOmp8m`@W-zO>3}D*E1Vtn1rV<% z+Ky*edd&QA`zWSP^;^2HiK_2 z?Bkr~1~N=(`0d1CdoUWqYPU}s6_J2q#CoRd?_FN(E-pDfqsv|;=AZ9QMcS16ke0S* z>azw)gGlGtdeOaTp6}=W<_;ElF_CEyQOvL{4X+NkoqcwbBisj?4jsVN6J)q-^eJEKHP%C3Vslo>DYKtII$ zU0S+7e{A+f=4&vYtjz16wTwz8JSdCeMIQ- z*W4Nqfvfp97#%LK+5Ktlxx}Wf*`e=S+mB3;cMsf;Vm9LN%$0}Rfq82; zT{^u@ZKxZ55U7qa3UrI~oajf!v)#8jnVn4Z-1|q|eV52WyVi(1lAF6D+XHyIBQlmb zW|?(2$qOJtee^H61$L2o@eI=x^e<9-ZL|?RcK%=sp3vvbSQF& z4*doZh4*or7*QKh*aMWPt`U&tk8wsenmS*^G)A96V~K(f$4`%{orV z|0)%H;OG6K{AzN4j|843$thZR6_(8h(?rewEZC%&*|J|yva0#;;%mtht-T*F8q37L zr>#9)2I*!hYjCUf2*~bsv*tU!D)D&_obD8Gy1vYSjxTj`e(USs5r@m|@!X00iaAFL z*Dx#pj0ix#VNvfAze@q9G3%sJ9b(aZ8EdLjFneD@EDFJ^Cl@g}c>@@#+f=$l^MPj8 z>0`3)5KQ-Eyw3nlBN5$S{3#%|(L31MT`4QMKFLoT%#*W{!5{Q7Qx_B<{ga-0oHK3^ zaSc>ep>1xtczXQl%ii|^f%AlwuI=GW#{I=l=}tHNLpA8 z)-^xzQ$%OSu&32%Ry#XAWFwqeQSleAc*pU)y{CKtty;?oO0#NcdK#Ri7AXwRX`YH( zp%-ppWJELP=R0rNClKv7Ozd}kh1H;~Zd8K^kCtTj4__SJW(Nc~Q|xyE7-#D?{)B-b z+;-nJ`WsyYVObcfUaB;~$S>yY_-s^$>JOq@%$F~jiO5caXT=e>M+N*@f!49Gj%}U1 zly2O0yo5mQJ57OE^lSskrq*ls{(-gtpW-EstanyOLj~6yot0dlOrlGPKFvQI=H);L zZ_UziTzH1b7VhC1ZX@MSHF*~Lz9UH)9O=iKTi=Jp=vTz4M1~X-e|kby(Yf$B2E-l*D{UU~5%-9W`zP1FiZZE<|ZY-iXUW6|wB2q-uF^WMzB zzY}Qgi*VJ4IVo9!xlU_+leBiT(S|iHa;INl;LXC`)U}qn86$a+3EkLZ)8v)jk?6g} zvhA1dEEE-A#_wxEf-Zx~drewIwi+Z$Vy%g;#QSe{nE@hJK_$J_RM%$OF>gl1VyJUp zmQ}rM4H5if0`VsC>me7@q0-@t_TLK2hwM!62F5W~mR)=k-Uskr=X9Gs`tzU1Nh-#K z)z4HOroYEj<-KO<%rj}F0`;jR>jN>{goYh$E*Ot3 zjl5-Z*%H*tao>NbS`#GKq8z(5Z@g?_46NMwvm<~_CY+|HqTjs98TFoWI;L}1|5$31 zlsm|o1=m+Mvs+{6v2?%ptEhYxGmxS1KmG>5+NgGk$jI=p@CiRwsgh)bzLQ)T71s|^ z_c86(!wEk8(?k@OP7NyJS`9;Iw2G`OktPc-+nKw%F!A1LOQR7%9F-+}U+Q$lMoI{T zJqGny>((k|)1dH`{zY|p0}MFD#GRL0ZHk$-aWy#IQ|{|mSNMrnM_)N_`YdGJNJ6;4 z=#04fB-jE@$#jGkHZFBvk4SLh4uvfIi=(*=Q=Cra2Si%0K~#f;m71D!rliR15H*$w z^ja|j`f}z?jah!@FA)|G*}BDHVmBs7b=lkn5JeE{lfouO6{y7Aa*H%(&QF$FAsX{N zB2uXz^_Ip})F+gs4sQs)wxDiLAl_LGjDP9lRmffRtsjK4+DK}Px3Xuq?*V3HzIki; z9mt;Agub#)#BS}Ke_!^+(q=uh$hYe-yDrad*GbeHZEcZpm$H#oQhq%gIdLFuNRYqLx5-5#-JP2MGoC#sE& zs@G1>G&%=d&MR}_Td<)5yd4%MH@fIxk;%_&nN(pe0gJ5#RHCt&>FR$0lzE}O6FC1# zn@ynJKhcS5{ymy&q77nVX8TTBG0o``Udh&TT14|B`{{LcAB=wg&r%7eGYd)he@46`z14u4SIsX1 z{gAsUK2CUzbNI8ao05vQ-Sm?^kjzHwu?%?2dX#4D@um*TC}%d~ZQkOSh?)v0MNF-w zQF?iEOP0HbT?FLjdE+p^DM?OvB|??Y@G+DC9GqNO znuDdJn=Qhc$<&5c>d>za0t2rl!ZdqIt(Yg2@Y|L4fa>}4L{Ws}6E#3s<=$KL`jEk- zy98|#zk)u*LKyp|5UjJMy5l8;KL|o{<83Vd+E^}fE-J4AzdZ0bqndt|-*AJCeHHJ{Ue*2w$#zC@9)+rtSzCF|L}$an#_D#&M=v_G46B-2RYRtl z9>`@@K!i(n3}o{te4jhlN-WdH&wLGfJ@}K@fuy5mIYPJDc)i;7Q0X2|^zcmac0%kK2{x>l*+jI(oo8xBf_0{HLCAS6h zDuf@ro#<5^xaD%@g6?Dq^x`#l%V1$qw=ncVJaM5dW-aece8&}r_3p7>Tvly&2`Sv- zqEv9TCd=*yQ?_Csj31#Of}8P7II5W2$n3ukRI7xs@7{^K^+Nm1yNVYJwWqNp@-5de~x`+nP}%#=6<=M4hjp1z$6cD4Fd}I2!G>L zojhV*cD>HShp!7?Mg4bxra#K63@S&Gy=p#LhRR$S&l%&TxeD}@UWXxeTFzm9n8q^Z zGDSgB^?3@<;hzIg+Ml7%{^=-*cmw{pRs|HFwlis-GUh)c6Vt<&x6;{TUs0$cEs-x5 z;0jrW+)kuma|O|=OI>uM@E#OiqN_nc?Y>{gI`na2g5Q9O&u512EExr$!@wfxpeZ$y|udx+kpqx1Z3y%>O+h{xv{OfIQtJOtNJ6` z2q>pWq7ViDlKKfuq@U4ezuq?9DxR2L%fOEd^R;!khS6;-A@#6@GdXp$WvwIi=s}NGAQtmpIS#%uKy3>${OIIDb@1tN&i$XGQGjNvr$OBCAP!M-m;?>V`RA6c-{SyzEr+Z(oy&FqSHidumRcu zn}=?vw_CWHfPDgP{F&wcI_vXU%~epugvCr0Ag4SA$gW)t8hr5~t-dPB4bFh84SiJB zwWMT|DS{n9EFz3?<)`D;F(N-&ckf$H@MRR7$v96T^|1S`*|bUbm=)i>WuG2T1);%G zdPs_ONhz>AYu+o!7?V zEq^PL8F^q{WI0tF2j&QWlr{KskC`6Niu7s_?txSU8&p)h^?EWW^dC1@Ok9HWUB^pU zh`MR&j0<&5RR}ZOV2ZtF36-8$q#5&ImYPwv2MhI-mRWsD{zQCS zb$vuOv$akullXA&8)rG)K2Dd0+9_r6(8X1R-pfjd2;;XF*FQvB9fW!6=uogJUZz;ex^fZ?H}Yxv}}-Gm=&Ay=K8oOIb_}&?zo;XRSH5U?Ii*fY@P7j~UMVm^5gVfU`GB z=<7OXRmkG{qZGeS7R+OTp&PNtAba#M#@eIWy><^htcb8v`3rl}|1n6aQQ61t8pg~P zYQTk>%Ge)yoU1K^zikcN_*Z^bq$b$(3HRv`P}olcy3~9-rHo+Le~;p3Ek||xHt`Qnb~!8%tf6Azs3x4)woSuX zkO9Cqpl?`(WNO5TEF=`gAFaZmsY3BvltW|DmRKdmof{^bTEQ_Ihox7THeK5IZMf>X z>ot@b#xlW#r_@AaDoRGPiL2=7s)n0rnYc_Qrjb%sRpGO_CJ$U<>hfnq0hj~x(BmHs zd(Z0%R@whkk0n$5&Y+|kJF?H(i=(BJiXS>_uQH(n#!UtrS1V@8$s|F;cIB z!l?^TBQLV_;GabrrMV|7XJ&G{^F6a_BAGWFlCA6g?wM3q1IuI`47cphLkVnDl0CbJ zVx^Pr`Gq=WBOfVz{0gW38**EH>FFU;b9D1mVegt|EN+B9>$dgTKi(dBDs<8AnRR*L zClwGxDZ3+i702K@)_CfNyN3zCCL?@QKmud2g&!$qf!;@vuzQ?}D z8wG-2ldhd6&2d7d1GKIFr@<+8YpDu;l8~G zvRibuX^Y=9uX8I<3o1q$EWGP9H0rcS}O`_^he3`5k^M}m3?D(>VR4GDdJL5{QX{HUx z{v2(Dck^NEGMfqdmD2D~iS9V_x~^E>dcq{P8KaGNId$A2VTtD7j8nY)wj6)WdW8aF zW7Mb%XKzLt1XKu58>F}&HJ-RG^Z!zg2K*9KH^KI4ql4LEowJmaDYC@t)ysSPU#@dl zy$49-c4dG$C##XNfo^F8H%H*z=S%GOo{N1OUtd@>&yjlZUt+u3hz)kKs9QHz?;pxw znWVoR^1iz&5t5$MOXiTH8p^=^rss}4EOSP%2o-r0srl^tK$FrMuC$nm`by^BVYN&8 z0)#ymNgh9u$pW+6R+U#*!}j$j;&rsrHJ?oXlUa8;6*`>{^Nx+xl9~P|&fnP6_%KHe zC&slY1!jG9%IaQCC4S5hth7;`)h^{h`sH<3d-hl!H%&-8x=({t5RrIh)6G#(oVV38 zQEP>QOYA=u-^xH$#SJm)K?r+)$lo|(6R zv56$CcDqvn*m&akW9YtI`0;d-a-|=tReSG}B&VnySo9T2xQ=VM`D?DV1)uz-P(`!t zE@N%|w9`NT8~D7|15m|}THl2Z2K9K_Zr#qJ>2_n8bi79Q!}{YNwmXwC+}OM>2g=Vv zg^G-LUm=rOdCP}RnkF%bqutH9`0mOpE$8=oPk3*@``@;Gb5G%x?1nMl|Juej+d=AFnq^AkUa1r@)XhaTq+>;=mWb zM}C?$J&xlOUIYZRHYabBAK|PykZe!Qa1?BL=N~5x<|T`=2##@m!O|TwEd~CK4n|K` zT%{WHOmJrIXC-+{ot<2+xCFFOM(_Q{6S1O7+_QW_FIMX29#Vs{d$b4E^jS+G%P@SV8iyPF;4F1%;T)4{+j@)0OG`Wc)ZlPOFZlXtS$KlIRig492_%w zkaUWQ^-sWI6u)dno!tzl>%RPdcz?w}+ez44d#Qq_&4V*Q=U&h&rKm^BQ64=TQAnf7 zv;8dJi^Yn3bRN(|2rlfKK8vImKlN7kvB6wCI%LvDhQljD4_Qrq(zv@yKC3T`a%Yh| zBYba+mOl#t>XXuO&a8~ znZsV6XImdVywVLV5^K~Zx!J;Pfaqrh?8)q6h6JJa79=(mtrHI4V0kKR`i8FT-O|M{ zv-0udo-m%Kdo5*x!Tye!zb%8(X3yVIgEqzslZK7C6SmO7RrAgwBq1Q~b-O*I2E=|$ z6=yXKEvOk}1M>7NKmjm5^S;P3BdQ9!0NFp-BK!i-_A+Gz+YjpxU$*_mzW3rbM_{s1 z{lU(8U%YAsURCax)}uVJ3KWF-#pJcJ2R=e?HNdBj9rr#0wOo+&w0rI7c#BFyPeZFvGUmg>ur}|08K;F7e*RNL(8x@2sGhE3iC^Uc64vx#*u6 z8TtT_fMvTX>hgHe0J8>Z4=v|@Dq1^|5D2?84|cJ<@T_%)$lnyl|70UG75r3aLcQEl z+XxK!oqe!W0c7g}DbVOX{4l-P*1ivV_iABvmW$t4o$0*x$~ch?b@_1-#IRa7^Jcy{ zMb3^S8~^0jn64MWfN!6el%d4RTux;!pKX|R1GRr{rug)MV;lYHl@)jaWm|= zThdnk*e{;AY03~GYT^}N%<+fd($1OoXUoEK7U)dDJ#FHLN$r^*R{urC`@f^2=)3xt z%jdIAZPRrg1?)0k15Qt?l;Q+07eEPk?U9T6WIm`$_oUMirKV*e-e&BlYpDA7o=$A3 zsQrE_4yz!V>7S}?x_I<~qOa+`28YPjr;uZ9-xBwWTkaBh%>Qr%KKZpZ^7fE;oh{(# ztcOQr*qZem`Rzr(lriV`)%|mhdbCZJb(gVW##m)b?9jyEHdXpdCjCh>b$xZseY+zc zNwetR<{A6(U(Fz#2tn_FBXV>CK%|2vIZ)uyibe)$*4NM2(Sd~kL2O)92Mr2lOXXu) z=rT+5vXr}MJb{o|XN%AVUAhhN?o&zR0Ui58w%s3jv){hEF(E}ANRm6Q*&IuI;JA0~ zsWf}#mWfB`^iR)gFS|WnQpc6&^D%7k3T_9XX$#@`J#}(`ak+qXONs5BZg<=3XfWaU zeJ@sh)uLyp)>e1Yburr{(gWARcp*sE)+PCN2jCGD+&1nop(=Pjk|gODBwI53##m@( zbUW7z5zoYgaT(3qS?%$R0Z+bTsOUt*BWGn<0#mkX*8ZdyVJHChZt_q6+#ue&4(%Gt zM@ElGuZ!VzaPk*9fhafFvjOEM*EH<#%2oz^=<{E_g{Z6!ODW(Qik3IFOD;Y9h}SjWZIMEZAO;8Bs%!#8}diiXOu(KYw=iZ-=m4c*9Oum;_M``UsC$$no-cgd^0R3 z;(zTFz{Oiue1z2OjS09r7&lv6k=?T1HdplK^Go6dQa&X8J%}bkVklH-DOAzga^b4o zKvxQ<9dcSJ^|{8q!Z4dBxNQ4KW4`HjiJ8LmDINg8uln{pwtRfLgd7F_Bx*xM%}IqZ3wjJ`e$ljkI1SB&^$;%vNa# z?a+zgJ1ArycbUyap`(irATJ1z8Cq7WnQ#O5z8Iv?DML`W`BaqXw9j}+Tn}@?P_RC+ zOJJbeEs{m78xP<|sZ?1dL-ol1JMl#GjZ_=WtU{nfOJNybm%S=v%z95Z!e(NyInz>& zEz3LDm7;Q9C@Eh}Vj$eWg8F0g`BPr#4I+^dp>QTlc8^&c zH;tsKXVlqy<;Gqh+`<#uMV`Q$oytL-Zgc9z&XA59K27n8*sbKQ7WnuiBp?#7pIIDl ztLtYz3H|=0BmIfqk0<=4>69H44}SXWM9tHmr&y;{5TB#FaR2fTi>PxKJ8oIrx@Dt! zAw=N|i-zk)!c1=5YT>GWi3{u#CZw`UufAl8Swff-dLk!U%-LI!;<{M{ENw~&U_Zi8 zqUJo|g`lFWz#F%$q?qSN3c46zmgGg%3V;?CxCgTl?>!T*hW4th2=$z;3YM5%aEjAo-Yue zYbk+l+ijAcpK1ydpZJa_%R|?+;yD-2&s_u76xqFp=oT4Kr%wM|sC{K9paavKBKRE& zW*J87uF}^apWTWZy|lImhl{w?%j6L^`H=59u(@u#CIw#Rt1Dd2QHbH2z{_jv`N-b? znWAroq{3O`*Dffd59&6Tay7_b&M-BR-GG7HF=R(xrXg0q(bY`Y^kLBvZx{*z7nWd|Fu6bg!-SOP!*7xzWVFq-sAzxZ;(Lmj9iZS}xPP zfCh2r_tQtv_v-7;t4+1vX~->dih>@AMyzR{=5kM~l=*w9)@TvMRueZV#Dq5pML(r2 zP<5F^{m^nk^dG8cantjB&#>Bn;_y>ke-^%T#KDk}o!ARl6wP%}_RXnMN>Ho=0*qv* zOs$W)#?W`b&)X3rj==mI#?tj+>_kVkt-QVl7RZ&^cf7ouP$_;Pw1(}UBlP@OV zjhn+X8%ku|BJmSvAD%0J>5Q}uzhv&Sl<%RwHY!qDMST9@xxm1n;^SN+R;LhhGL?G$&)LgD?6g__o&HBBfNsEvfHuGSb|{xo>C*WZo73ME!LM8OqhyZK64I zJ`6eh#Y)`<=I`9$c1vl%%cO;+er%S}Q$Bl`oK;_%e>&jWK znS_`{;f1B`5AySI^vLCp%#)nGhsQSiS(`la62LofW7Edpp+@u^|C#sy@NN@af`#** zr;9t~1=(r~L~W}OaTk3A_k`-)2kLNYwtvf1R_OI|be*M4krr`bW6wT;w~D;c<0Z0j?o`oa#Ua+eamR+TF`sZPM!F(M1>`zTuvJBBONpDJpyJ+FQHoa1gu9$I-~b zdAvO)zXtfyGuVK${#!Ewo3oRxXsnQj2d*!F#Xh30PW@-Zj~eJZ`~+IWo z5r4KU>$r)v+AFHX;*Vf<)<6)ppa+s-Tl3B!6Of0Y&Yb46excbV5 zj!`;ptksFHtG~PzCH?Mt)^bLnK_)t}Y_5*4!AIJed`gYMpaeRYE z%tQCQS$^FR-_W(B&S|g`|76sTn43hZm9m&dovS~Egt6sA7@ZoiI4 z8#i!lgNnUZp9C*~v=#ERC}1zt^L{bT8_e6<&PB=wMY8bz{x8T|g> zXE-H|2zm{Gd;Y;_;hG(^m9u^e2?YnA? zWx2VncE&}3Vy6QrTQN`eX>Uu+P;MMQkCqtV+!&wG{+We+np|JOf`@1v>697t9emXy znTqWmHD3XAMa{BqbemMb0@Ed${Qg^w2AQ$1B-MD8CHh(4gpcXNTX(`;&!vD9H5R10 z9Me1PNJaW??gc5Vv)t8rQzU6Ht$@G zz>}g`-^(1D^4I$Q;{pVJ9=6iDS6N;TXO(P3TZfs6G|jltkTMM(imq8rgXN!|3)|C3 zV7!20H*P)M?cZv2VmE5@bZGd96K6Bgx)=ZWtqil7Q~CRze%hKevrE_RSq4&bOOq=o zCALv)ez%;EhLUS0eRazl?`7A;gIOKE4uQEKyH;`bO<(|pDtVby1LzF@? zxqP>TU%TXP{axiRUK(}q+uaEQT2FnCNfy~M0v208>^GL&1T-=yr)Ro-aEI4((#ubK z?{{%^W;y!(Le!arzf`_cuXv~4ts&&bw#7xS5mnvjca`gfuWE7iBxz)|)q>EpqO0>P z+W5igr?;S#idS>G`@>uM+NE*1cE#sc_Ur1 z7B~A576qt+I}=@K@v;X7VrPLhwp_&UPh08536+ANn8Djs!)D!A2&Mk7W`M9efh77q zS$*Ku2`Q;po76fy7~}j@Zm^c!K5K(Io%)tij0=+iAmL|iD^{(k*8zb}wc8x^m?nTH zg5eN=M{d8V4o%{Y!><8rg7`u-F)2~1@$q;)&$t`k9~I3oI(t^b0(R$^@qKLm*Cj^S z7dpu|L@sTr3(VC;g;$n(e8P>gn_l>+P!e1LN4;^njYxj<_q6|nRo~<<{nu(H+q@1E z4lD8Neunk6)Qn{Yc9HPWw>Y9=?coVc3v;p=JwXv`LuBue_qY=h)SU%Ez$#O?zDTdcE^OKI%4&nj3R2N&p(*C2X$%# zg~8n&jt7aIJ9nQrn~tm7u7|R~hKolDruv7%PoS+uiRxI^GTh5>SAvrLxlbLRE)?V~ zhRx>l-G8ewp6B2rcV|C6?8OL14^d1{Kq=dzLNbl!Qi?|*R-RwG3 zYmqulSpxFTPX|J)ju^kBjE&j>W(P~jM#b(;Bvn-9HQpA>SdBmM)UXqr4s;Kj zPKcUUgc_N;7n#!8-1#8Ood>G7bAY`;t-h|%!ehl9dv>;5rHoiz#k1C1kJfIE zxo(x}QV{~mN;VI;0|R1g1+8_FQ@~SixBU^!Q*T1Je$qK?j3z;Rwf1f@7&5WW!wrvk z5qgu&0iK67_&mx!gro9h4n1(m3JWOB1UUeO2}X09zua&GjWU1FR9zB z>DExi!x7dw6uEznLG9b(gY+>C3%gX@9=8_{*dtQbD;PKdmpO#*Y`3oMiav^h8kF{k z0s_)RKw7W?B0`iRNJ#`#kSe{TDWG&vkRnK;B1CFHdI_P04iS)EqM?@%YC;kM-_3c? znK|YAkr{q6v+rw{wbxpkIg+>0o8_jQzUKUOH|<{gN7{XIAQ+@7@|$eKy=VH}q3D7M z!gk^8_HYTT9___}FZZP{?~%IIGIX=>pJs&risPfB=Q>~7E(pk1zXXxT%0o+5axc62 zF;9}UcTSy%?SHwmbRq`QpEPO$ymvW44g;OVvWEX3$cyPE@k_D9G*pK1dmv%oM!UQqee`=;VIj>|Tjb)fIQtJPtTI0(!~fNAsj6Q~nTu<&SXkkE^+Ue>q6%=R#8EZer z)I{^gTuicJ8iq|Yt}4GcWs_Qj8#EfN*qAb71u9~*ANd@=-3<*D8gKhP4 zz(>on_q$k9u9749H9kPnY&S_M4^%%$o*7C(Y^W={MJ3AnwL!Tu{>I4zjUTW-B#p$0 zZ~fXZ4~OlyQB_60cH6XsmmD?FqFMWpD=#Kr3`GR{ zn|G-?#$iB&x>LQY~h-CE`FmW)HlAM==EUUTp3<$E$_py z0F^5KI?JzIS0^wFQIlLd{yT5j*rUdTHneimdRQVxnb4e`8aN5t*k?y5EGii z-@ouUpFd|if4=@jbVlUK3qF(&Q)i}3KK-pXDeR1n(mG|oQH)~K^OsZoQ7Z_`d`A(P zFDu|p0RCkpEa@d#sCEewWyig6Hqla97vDQRL;zsPs^=f5oI7Wfw=vib78!y~!8gBv zOZ-XiZ)cgBe>s2Os5q(P%TUIT)G#d&erSQ2D-|96DQqB$5V5f&uF=z(dU9R=nNmO@ z%+c9l$W-)ON>#1``Nu)lfpICg<$eE*G<6)J4KoZqGY14y9Hs2LZTtteF>{kHvI3dh zRgW9RyQq5%0Gqpk7JoZh~T=P4B;$hP^8a@dK6(|30@o z+7oO5;$7~Mq+hx8E9Wr`OC54pn%H!V!lP*CJ_)Vi?;N?16H92d+VXu-b`!#+%q9$u zqh_Ze;W>{YEkq5BhLo<7Tmr*NO2()HeG(~o*t>Z1Pj9`>(r9#UUyP^hSM&x7?bt)o!Xz4{2jeBZ@@ckZXAOl(DiW-@aw z_dasTeX9bdeWX)d#aZf8g?#7RyV0Oc$SIX_{GmTYBUsCvVS%J2;L;W z#n*=7S~6yaA;NPIzDCyEHN|O}Q@nZzJ6avPvpJsx;+yXa+oP%?@<$K9eSTcCA_%7K z|NIq{?-skB`0<~HmH&)j%g3Tpm4*#TQ7WJ-JW=Z9Yi|#zNCU$-Ouv@CKr?Dk zKfe7!`;bmO19*A9_k=oae%3^kBcqSq6;gzjd|dm}0Bh*WA(mZfTDdwNju1!Q4V(V9 zljZl?kWWQMZm}#HZuvy6RI{wG|4G17sjRQoC_Mce+Cy}TeQ@n0%pn8(8vAX_I4%*4 zs{Oi;AXoF6xR!C_C+Ou_YW3#ul^h#PdPlQWvoH!K=hca)$gM|0h<=CI7wapY&8l@0 zr*v4wcXebTv%+xpH}=WK19ahZu1x9(Ifr0=Z%wUUDWeZlY#J{1@~uzn6c2hX0DTiCBx5-aGt@G`{EJ50OEdjD*-@9H(xP`>=;LjdBTN z>ru?yZB6f(Idi7Ih$t z{3dBHX9g~7KO@%=y>~+1;kS`p-?m0_e#bb=4d&2~2*{kCD*@P5&1l#kJU*c8hjNjBn)jH_ z0`t$pAIKggbiiideodl93&NMrdpFe;cuyb#^kDX7b@~qg>+%D2OFOL~( zv>S=Y8s-a^i76B@Wh_)UN0+0U28_>TAV(akB}A^Q^25igj;wlX_ccS)o0uN>VvOX4 zMgGsHYR+lv-4jSEGlO#jPJ8Hw_m4CfTo?fYij6MGz2~iLugAhRzF!YhV zTCa&mE=kh1QezYii8+jeMngr-J8wsNY5R==gtw)yb6p`$|s?43k*~sV*@~LsFsmhs7&pA&=zFE113)j|*X%XM{PIuh2 z{AEg2a#xB8UNT9^>ENv$;#vPxyM&wZ0j*~&G)`B?7|e7I$cB?S76C`GRRLw2S_=2K z3%bNMjMux8{@N;csYu!^!`!}dynPHbhp^)=j$;+%%#>`}SE8#A+tz;q9-{S2tdOOM zdBGzAc}$YHZVz>9*tQdaj#so}r7B3|zHf)k$|T|?D|t8%5>0+VXrUFG3)dhcUidJm zjO1btdH}yDVF&c?&s<_`q^rUQy;f%Bhh@5Cwv)Z~RfQQ!r-lRfdzDXWy@tGE0i{jW z$}V#%C*QP4M5A$&mIfI*Ho{5!;gDA}&GtSu@|b4F)D~ZM9?*}!oh{VVH3m(HZFlDd zir1r9S~m}7#Q(bgxZ+>F&CULvuCaDnx4KS7{M((x-KXX`9rg6>%J z({Uj;mQ9QM!2`fq6buOc*9K^2O2jp5u$XWuGzs_jWBvSkQ{mOOEKdI%%*yKuMGPGS zwLKP>%-ee)3cj6Dx-m9+(QC}GwyKm6tU ziQAb9Mp@^Y5*jVG`{m^r&eHSvN&1xY&bZl?(S?9pm_e^GS}|dh2mQqnfBw;^UaO+J z7v65cerH@h!cpG*;(M5MmDG3qpqUj?K4myR&BZ*~{EYN8WVW~2QlD5obIUXtx85TR z)BA$;$w;YC^}P?rZpt86Oc-J`<35!@nhS=Fx%y_GHgT*HM%|{luov{QPYB4W0s(mU z=iJQ#xpr2S%J3wBAgb;IZD;;Ho?seDVEI5E+aL^Ij)OKHGIHO)4QfR8#*AKJ29yF9wRu= zEx}`D3)qw?fNi2a{LoODJ8ShcshHrpmT}^suhg=~>YaS|4!w`Od5>NYzEg}31Xg}G z6odV+s|iA_&q0Jw?$F#=)M{(QM7;h772Lpc;wRgse3r(*F`>%*;G&6Qc2Sh7TL6VH zZ`>og5K1 zgoysEdjBd(G2R{5S3!%?{*i zm>)1F{bE+Xz_*Cu7Ata!w?1f{3bwprHAydv)H+1-*8Dbd@LU}Z2@q6(f-K6G8tev#aNm~41NDinBG|6aC2KB?*HIbXj%*x1#z@;SgksjmBvdQ9x5 zIpA>9_j%k=3YB_iIL)x2_UTS%*G6OesmZehWS^9lA!K9`HIt5h6Iq1~CLC1ybT}g> zUfftRP_}`Q`+u!QkzJ(qj2ys%n-feeFlbsLNpfaJbjp$@F9R>ie*9CHi6#C;d^Prw z>QdGH*W<5nGdk0%<~TpX*TI0@fSG>6y{mQ~vYfMNfG;uH3iq_Pr8YeTpKXAI`e2M6jA^OEJvJGfqk`sQ5?zkC~Vd`|CR&R%a2O?=Uq z=ktBI>YJ53P1$G8b{X3~m(gNS*SjNQM>-sai0t6}lQO-^yhwxaktHWZg5Bl-%P*Ylyo4bQk80EljK=$}w zAFDS%fvGQp`MdwDmV6%N2a)?T79SZrEgs?>j8^)WMDG9E{dYEeYx8(erV7|LbD=vsFe_tz+XXfk3IJJQFKr5 z`l9cMufIP(ugLa!IT*YD`Ncxfbf`?mSfTzEi3CWY{)k9SM!KOl-21P4;|zGYTbn(< zFT4yD>yJY-m`@hxl*fnkJ|2^WXeLQ0KioPB>9&fwfzSEv_BVP1<6=)OB~g2Pxi$0g z>EA@3p;$is8f8qO`O_MvqCeJmyc&jTW-6KRLhTC~Ixdm@vXANSHt)4vDRC67udMmq zu@SY=OQsXC4UiRtk=%@M_xJ2iniWFZ9QlDzg?>5_B$?P5;^7o!E|c3EcrSd%I0P>B zCv^j=Joo7t>#e#gKJ>RyalnF9b`h;Fa_Pz)_{wPhojkP{KQF6DmOl6?x!jbhaYjDQ zL|Q+oEHP5Y*C)zUG4pm53|B)m)JVS#0AhHb;L4^SMnlI)zKp=$H)v`ee-7cCLHW|B zjmux2;8Sd7hIWlx*Qd6<`H4T!`_WqfTphkr_auOBDE}KIq8%H4jyDm&_w9D{KA`x)A8M(7sPOeX^_?8_Mjx`q*Xb&sJjiUzOooo@ypc zsh<(fq1<0aojJOaEk_u3G_N`+H#dg0+wLRPRGc@X({=ZpAE_~x(T+J;iU+KVJ4hs)o-(}}G$A{!O8yTM5Lp#4v z%BXtinb0J$$dKDIrR6hPhUHq{Z#3tAt>ipBZfLvZ!D4|(s80ASmiV7!%`1B}yZueh5#J6;Y^O#Pt zEKllE9en{`L6Hu6WJ9=B5#fUbArfPLYS5~cr2ILp(o634 zMR(wqTB;7z1K=zdiDL0LC{)dJm%c2d)BUQqzpOX7F2gbE#z(}xT)z`fJXHa0CX zVmOWn-l|y!Sb5sDX*-T7)f&GlxOp1bzkCLP$UdvF9S+jyY~9hsh@yG%Ad|uXEFU}o z^9}2x)$Z)qB6B!_KTBQcTM zGV-|G!5Fnat<-@JoaQ9;mGJy8j21tvtim3u(~Xe{@OtB#Z$>w1nzl|aP#vl(o{^_<9QFa$XXa5ROZ7izS(Y*^0#|+V>5A?IdV{8oF~C`$E2P(Kdx}E%B1(q zALSZjmgNG>N)M<|cg_11NeL?oJNpgxTvxG2-2EbQL1yoNH;a#Xbe)xQ^E%(Qt6mkr z8y;>4&dp>D3Swx6`K1r^_w9^I!4JiARpIL-(c;+De{lgiyduXEmqIBu5g(2m=SDMA zUbPAYr_#6So9hPX1)$Jb}KtnpodZx?h%E?N^9`! zDrdD>uU}@@ewwW(wZlBMXVuu@tor0fhJPrE<1$&dq3N3&{L53G0t1Upg3PSAC|4(r zPp=2?#u5yaPbeg&Ufxd3iC63pWghng9c3EtQwJOXs^2;-%;sNnTB|OqMA6wrscj5Q9H$1W?WFW)XcVGOp%;{+}rCAC* zvjWqu^^8o64YE#%Q_TIt(QEYT!{RD;C$Pxr6h}LaYqD-t;)AJvH_6BS3=gW^;a{v+ zNCf)!x%!ljm$ui=U7=X~<*O^XTZ8^LVV${5GtAUW4GHKGtjn&`_YLIqla`rPPW` zX1Iwg|F0v6hc|K`tr30?`_4&TI-5$)8K$MJcW=fpT9OT@MPTFK{GI%A3N+}dPGC0V zMSe@-6CUstxt|NvoIC)t!k+(_+?05vtLgb&QquGTZtg-N-aNVYiwp9&iHwb33(EWJ z?Jv)mS!+$(^{1B77rTjk~$CCw6}wIT|ow6p!GTB z&z$@8W9HYpdo9n$;3V8cAMFipamcxCPW!=_d=21GxOXQ|Wx;r{#;@by8D5TF9k6nH zwXCoJs9gbfY~3qPSLF?#lQ{<~Aq-oZ#B)KaCyWvoG~39!P}SgC37lFS%qO3tjoTATH6zrz*`# z1)fv1nZ!W)I;XEJM|ax((tfY)W-!)_gaFr|WwNaJL^oEJ5_+ryh&|3kM`1$$Ngo3~ zS-Oo+pcPGgCGYRg0zP-%+a@L`v`NaE@0|Hi>9CRPuiQyNC+*KGmu#66UtY_qxQdLN znH7+S<`&v>(mu~HBt_EMkyGwRw}Q8P(dwK1^;-Pw#OW)HoQNxd!_Z$i%xz!^WLj*F z%pQmoH+HgDKf3VXSW>nH02^{6XH?82Z$GpWNbPivu81F$FJR$%-aK@J@kuW0KYNjX zTMkAsVO*{Fv@#f{R0Ru!BV8Lz7{<5>DVm-1&5UW--&_2({y1YNwO^xV!KO;|nH#xpdlda73B(V$JjJ0{q8LQ$12#-+OcLHmW2UNY!p74#vKxy*I=!glu3cfoS$^L!xCqYFfwkIk*U!fv@JWdIklSs#;}ry! zRbg2FU~K&C=|)?;WpT9j?~l^vXg3Sl)Q%rTm~ zY^I%alY(VK=2LplUJht@flTxthH6D+21)83<;3GBj_k}c%as6{OGD1$?Fhzss||;^ zr(+>`G1n5l)cEbUlFl!z5L5O0#AA!GFKl*@F0` z*F83=u4rG4L>z>Hfz{eOvseE;YUlpNyW~0n(7OFsNU;Sfn2k2uzh1s9cs)`kZ?}th zwZs*w-j1YTPR_q@jlq}GfbQh%Y(_t?jl$K&)=b>Z)oWU>?UXL7P5fTj7Tg@R+7Se^ zwqos&+&Is)MMR-G6sA+ACOG#ckDm;{CO5knRVym1yzk5{t$w(H;4g&_w~2PxKaL4V zU8#`)AH>bR81XZhS3|`ydcEWfKKq@=&AegOpDgk8sIcgB8(YgzTSc)pdgR@ctK6fP zF|rw3gx(5>=*73^s^qh!^Q?S54A%{Y&PQ!XiBI?16+3)b8ZmElh^()+hCb1Z?Z@dD zQ5G(aAIr}-f#A*f_*X#fln{Eo5pGr-kp>Q%ag3;l0N3|sn_=mBAhb{D5~SD5vx<4ksKA^Y z`0nsJbtoVd5E;jGJ+0ON6)B=FxnKAg8-V@ax5Kvf^I0sJ9_)pUD3<`ekdL2 zaa!7dry0(qp!Zd2=#~4r@;W<@9e_9O0q_)mIzgt~XCYjCm$foIn3_y8tSWt}F9e$) zNztgK$M)D~URNtudjK0TjK8U^>G3Dq?Ml?q<0zN3Ulk6p~Y;nFJj932ye;0iST6 zJ{ee->Q(o`>NHP>EkUbG3W5XaP`O7X4oktS;PQZbUJ0zkT*8mZXC8BsZn)uNp8uE@ z=<{xC#te}&3l6!j!cqDZP~osm2x55c;acP~!6E;Pu&K#MgnyhbCWAO1x7e+PmdKvZ7wuAym%FE-9I&dw|J>z$~?iDA6MaPVp z5_?Ju#gRu{`u#OX2R9J!tp@r15aA|EPsa<56j8!AsUNh^(_HJGt|A{8L;V@~!=@e( zOcNVWr?&iLDwDW;2TTOUgTLk3&LcBH1g8Mqf4oV7X24Wj4RL7iH>c@Y^Ht_7efum9(To@Or5ewPej094=Ax~eiXx>Ks@qY2}$ zS97gLIEMxOcl!DLIe81$)v2&xfR7YPNa!8!u!>Cj)(FDjXKUgc{A`~$6F5@+4g}H8 zF5?VzPB^hb3zdQyadSU!=;66~5>MnZUrtd~|F9g;C!Hsb)gkUI+#OkBDxXasKH6mJ z5{X&;&Me}J6b@;ODHW1@9jaf{8IQY7B_X(R;B2rCZgvX!0~KB|mq4~HIS{yQc{yA^ zu#z*e8pYJKS@r440lT*?c;}n9*s*HBrA-D@E2#`6vqUYqTxYM#L~loKAzwy6 z0g9(*1?1_?g4Uv@vRA_v{t(rvYW1i|_Q_bou=z!b)qUG2OG!BfKdFob5ZS~}I(c2s z$<%cJ=^*1EJ6a@k>!yh&jMB?kR~-By-YF?=eOo+Y{^RYUfij#_G%v}egb<#mE)>By zYL{-W+BewFK3&pBTuY8CPkxvGl80%YHnA#dP{I%q?bJI1T;osJB`<-9) z*+zQh(+bz8(B|@B&Tuq^eCrg{M|M5sqmXf|pb@!VsI3*g@9xX1e;?d+k!vegCALv`4S)ib-yQJIO`xvhUS9f?t_Z;UE@drn1{|HuLUi{;vcS7i{n37lw66nb^} zj8N*zW8OC>jq8XR+X9Lr$K+`F6I8}|6;<8juD?X+kmZ-|LBZ*BkNy6WEFo3jp<51T zik;w9U0&~HdeDaLt;=5?IJMtiH@Wk`a|wayf;U2WMvYSs``W`lVd>z>`q&>D$$gIEKDKX_iV}^B(|HOvNmKxNbZ44byb^<;Z zmlzA}L+U#8YXB-v|8XFYU3q!cJjjl#-)C`2t^mG3@TxW@UeZglwpo2aZnIv3`mEYq z{!9^c3K#>e)23nH zk8Tib*ZEhex4pkugD_LH{0E|7f$7;<_VC(UKFP)!}9M*%*a{+vM0r{6e>;Z`Nc&!6$ zm{f+|J__F0lFNq;)z)>NR;6gy=HRtzlh8AJ$2rS;^qS{())fA2X$&lerGcJ~8m)?H z>MU~@98?F?0}*rHArlim_a%0>kp+bT`viVJz1q}Wr%oMd1svD}=4E}UWjYYK_Aut9 z9=8%DFznL{qai`j09({CS zP`SR38W}t6+ire^qPyOs6(vFHc9HSMYF+7$ z^2L3HnU#)qx2%M7BDkN!rVb?Bka;LS0(oKNYtZkxD)m(@>q=d@(E@T&~m`4F_cPI0-Psb} zq9$p7eexgaqou;`s<7>f}d#7Wp=dLgirFCl;^~N``*g# z+G_sxuTjnw(bBWa5Q#5Vt-WIZJ&k~qUO(4GU`AnLyGKZ+aTT*csChtxevS|O9k6hH=A8m32X0PpSdR1 z$gkRz9ECP%=n~C80#L#I`P&D)+pSPnu~QD=k#t4F6gY$juFN zluxOecLCamHmeyYmxSzW(A9fz`q`C**(Yp=Wh+^X7J>=BQogYj!B`^JML+=p9Bg3beyEUwWcG zh35dJ=s$LA07`PdbVoP;?7aSO!3f)d2P5DA^<69)jYZ$tJ zFEq^LZ2n%7rv_IM!;V=&CfGng=SgIHuZep<@deruvPu}c)Nd0JY`YP0+ahWNEv{gr zQ4tR_0`1cIa>q$I(jGEF_ma;zUkbd=fGy_YOrcepKXiIejIVj= z+@|?Wp5mS-?&zSyaLIBX&dFv;O_vA+_h#X^+H{t4>ZX$RGS61U&hIzhAK;&Bo<%HW zL~f2~v#&CEB{!$c>5q3pFaBq^Pu>c9OQ0DqmO9O3K1I-conw9K2V6DO{RNxug9KiW z&G=L7xE4AG7$spmuzKgBs8hm1s8^|>+QF%!TYr`IV`~#4v804CGPS4cm_Vz=T&nVb zT^U@(yI7xmoqXu`XvF%Kzm{HCj4w05Hl_<~JUdY5U^FKc*v>y2?iMy3GqS!lhqzZ& zl4#=LVfENWAEAGO8#q@Hv3iEpgpIOUWk%AsO&@v54R;rP*299%KUe5u@vqcZM%r|H zduuDg)Foi)t+F*Z&IN|1C&?xYmzXGty(j`Z)>?g6rnXZs=cC3c{Ou@iRh|cSIfa;} zoiu_X9u6R_Dp$IL9kQ{m^tWJF`Q^fG+_CK!a9gx`#L_oRx*3ROX5LiE44g@D^7+V; z{z;vt*sJB4iEUi>s@EKlc;$Qw?Q&2Nm1c7NnS4K(JVO7VB}w#=ukac1!McDtwK%VYqzPdV$|# zyeF1ZVaPD-_CVQk0tFey1Z!SjSmN`{22%HlAq!EU3zz$SxMt?u)`m7`j#^%#Tn7Tf z&+V{a0S9;bcD6=Tn3+Ne~<7JE5bJm4NXp4p2{2H=EjSP(D>}hW_%sS=6il)6e*MXg^0H8`B0<-f`;8)vyfVY>Gx^W+ zjZIl!Wvuwl@;^RUI)5vCPGG>A)b>1D39SxWY}C9S)c7OW7Fe-*_A#?O+n^>5&hE~p z<_{hK{Mb|?A<4S?3y`?ovc>jIj9z50+m5mhC`kBZ!!DN>4OB}Enjq7_<~2=Bp8)`o zKIw@O07@~jAd*4L_>DUF05NT}qx*GTd5!rXrXB!~ey=H%l z>lNzt4h)0Gq7E}fxF_~J(HyQ_Vo1K6t6wXxUK5jpmcQ<0l6k<38j< zK0w5g`gw3!-CS(NR!S0mV3MEGYbcFT?ucJ9Q3pr$+dE%~Iy2+b2-1JEQHiNc;$Jdj z$p%l;H=ncZh%>?9Fu3czJKiZ+Xjya^pkQGb;?2eQqQV*Vi!Aj@M|nH*KsqeF7D}Yw z*R0X><5uO%xH!2u;$x&r%;vMZJQDNHgmsIPXcS^l700JEl~K&5m-bM4t{;S;#c`n59|ooi{B z(T3Iu)t89n5*Cq32~m`c=N=u}jvPTH-gjvBFJP*RED~Z;%l5uk^aT!r zwU3Y|!p9&Jt6c_Nf%}RV4*jaXeV|mKsqCPdxZ6U4xeNU9c&^Ras94t1JAvX~D|*2? z@+}!1hDnGiR3hH)*J{(+m01cxzxmtzB=u}W!UsrTXTrv9G9Y|#cT>)siTrvccgKrU zT}@0h-2O`wq>t!b!^PiG65ynd>pcWdIW^C}P;O*@Y!l28VZY(E@7?+-!-DLmG+*z( zU>7YunnV5M{H1xYbSn#9imryy4vmBB3Cr^pHTOgtSCv>b^Q_Uzr9m0&*ItG(7c$_4 za#vLBw!V3yQ!f9fw1{?yBmQrdf>fu@Z#r8J?pKYG-P(E);4rlNcpCj(jEbo`LZ%y9uTUtm-IYPGdF(#w$SU7Oh)v`<6hSf?2 zJbo{966FTH26lBxKiZ=1EO*3PZN{T#b&bC}czHM+*WM(MsRUl$Wi)qPqkP9Pd1uM6 zMH-O$t5H7!hx3%si>x;xfhrIfr5?NU1@v;Qe=lkp1Qxgin9}`cTQ_qCZc;#K{(M#$ z=<1H@&ifXg7lPRn2Z?}bP-ZB5{=8sOd(cXR z@C}Fen3Rjt{2xPmECUH7qi&fE1GesQWL0T#VyW~`5SeA+0N!!4b|Yl(%$muB2AcbM_PTU7HVVl8SU{(vUE7UsFm z7pXYfWAOXH$F|rFP9Ay~DyP>Y$Ef~B1)ZY#gq18t=gohY7>=BY22k9Ork^;e8MS9j z_m;L8f~@r8kB1|+=e)C$zd(kZ@gB-&`lR4cxQRxuTtPl0Ni*TH(bo2e_L#3(!C_|2 zGRYGaGwq~_AHGxO*D5&JSI9OF$@krJEOOm$ z0LT4ljsUSQS9}QQ_DtyS_-BldkK`#^3fcGFB~4P}3i*maO@6btUto&y+tq6Wt~*QgI`-P+9gYF5yH_9H_lT+H;wOj@Y{C7+@Ve;z5`ms)ln@#T@LlGzP-TGez>NI=jo^WM{J zKOj{T)6M|w7))k){bVcZ8%)Q1ZPaLH`*teX+Yc{blf$0KcRa*LN`&rdnnaEO!~d4D z$SG#P%367`{O*gs=i(Z(VngvfgIt2jH@lM*wJP7Vb{|d_LGMx0vT$oYb_!4QP3@Jtt~#=BW4l== zaG&2+&fChSON&LN+Yv5t1&=+tYX&Le_VNV>eSLCuSLjd3N7mWDULpXSl}nIdNtDU- zHv>6>)l{ViTJ6hqDYM?yQ-v^}2#CJy04@#R2L9&ATX4rWYt!v3 zA@Ia%A+1AqEf5!1p*$j!HRbJMJaj)7nk|n}fIQ$S6)QTS+?& z?$nYp#-Vxf3poc#fiod#H0A2`(Jo_8cbLFLJa+KQe+%3~5M#FP@Y7X>w@%%q<&+4I zaSkq`*NfU0W`oL+j7Di{DZbMGW;J?11KqH|SBk&d)#TUR4}Dft)82LADd*&K`o5Rt zG3-mx5?$lxP9U|MOIdy-2?mipU9uRLpSqCbME8$?;?5_&x*?ims4ePhWVhgNt4*r7 z=Fp)U*Y9eO+a9-dyZILY^Q(YOs;=pcO1{rozF?kGWtfo?QCHX{8AJ-+f`}cFcEzUp8*#EOMp}AS#5$j3|P)s?9ycpl9s0T;5*y!N=n_ z#`{9xwxWxDV=Ez=gr*(7IeKxi1}Vd6y3yF#sv4E*c`n&Bk^3@xf|N1g7&Kt z!!^Ba%Ot%}$(sLY3LB+(lG@G5<{IE$i#SC?;dZfEz)t1P1IbqcM6xhsNJ)4rl`)^K zW`FlnCaBn4O!L$XwELj>s3Wqo4Yf(?WLfS70>OW z^spz@-*!dj|IvBpN^kV5)*;%*@19Ul8d-i5$jG#NNHrJs6T&3xF4DfUI@fb2%-Oq@~DD;XL_?QUBkua7seAw}i_=sTeFomz$eHR!*rE31#)ntV{Ds`uNN4v~EgNu;t>WyydhiuJ zqaJl;MDluFLmlMJvqrC$R82z$EQ-ge6=Fz@B2eud;dbhUZ1Hx9&)>>yGOzmH!=&O6 z2^mh!kdEGq(GEv7qcCQt-Nz)ytE^9GgHQ8S${+9DI#N^_VBpkb|8<+nN{vE))2j)S zUKqI_To?is$IWgm^S6^v31)a!fEk0PqNg}MS%B+Rh>SC)>__s|htRI^LFv8+mFT(A z(w|us7zq>A_hp4jHBM?{=j+ zfg-p243qNm6l?zUCcWf_civo!*puWtunZLE1Us$O!VqAjuIK7WZbsw5wY)oD1O;N> za`53w_Ai-ril{Z`*niN||KmNkNMG;_itg4ZFYx70b*4W-dh^!aXC4QqI#!h*mofPJ zTio5Mp3*qMeWdS5zkL1It_ep5Kqo~ZvC)~nGkwqABMoDqzCo^)zm3 z^&7Hk(r{+UBpp`W7m6W0Vm&6B=Drr3GEuqqGMfBU&bd`NjE8-P^&vYo`wVE6gt_$- zD;gbkuPTKEL20@uq&UwGTz&y9UewAhxIB9^}-7aP*(g3*_s z3;e-wC7kbQB&4Ud+wcSu_K6z2n`8slX4os(XJL#_6?ZrA4KD(yv0A6EvP#+TCu@yH zYmb=O%`Qe-S&b$V%5Q^qwc>^GEAz=k+Rx;N%BCw zif1UxuS6*ItM)?RvE2B*#}4`>WIzXM@PtRE-44qArm{eSoxC<=!Ea6cQTSoh+4-V1 z@oMgockj%0K@vc9dH`R;I7vtPhs|Is6fDM@IVRQY;r-RjKY&IOn6>{SK?874|9CBf z?LJYzX&83@$2K2A#R&d0({&cA*eH0L(AvX3zsaWM==!I<@@;UhM4mZCr)*cY5B+cv zZa`2~mM4)dRRga>M;@J^r)W5<*N7PVHcMFM%A3wQiduY=tP8E)<8B7&<|jQ!kzY5& zEBlT2kWb|CW{nosT(TEiON};hom2j$0gk_%ge%rYdNNvV&Vt4dbG_1z|6>#yW6pb> z`NfbNSK{diB>funL@pxjpf``(c!P8W@Q+X1oA1T;1Jh(|-_^r~c2>5;7>$8m`+JQj zMixA;yoo`NvsyEQY&*YoKY#Nb?Ht4G)Z{^*=nb#(UPc^PSO@MaKcaZq-sukfl!mu$ zn!BGJ2^$)NTL)qYEn33+V~2-KU4c%j?0Vk#*0s7@w$OKEOZ}jGug*lO<(V)L-B$H5 zXZ&>fAjJ(&7o8dJK7gXBdkxE6cs?ScW(aA&kePxm(~_$%LZk-BYh56>jaW02-R~D1 z)_d}uv}>Y@dwb+*Z9`_zxJ*^Y?9qlJFfkQEDws7b_Q+2B~oVvXzDy&+= z0{oxF_2jLtlw%7pQbx4A9n!nZ96|W<;6v%OSCNN?ytOK%kwSVc)hVJf^H&Hg{CzB`%?zJ0%Y&{oynRaKj!Hqk0=)oN?csML(TNyJm7 ztr@MVE!7$|W5x`%lG?S2Rf5!r6=FpA#q+$+`+k3aILC2v{E_=}@9Vnm3At(lUuYYNwPO(`}?}AOOD=#*$lmGKnIN3KtQ@u!?f&E*1o)*Mq&4D-g(otpI z4%L1jq;t0#;B2P)+ETlh9EAei8?KVPz9_ekOC0W1F94@TnJe^ zl0St)Vu$@7(8?&+jC~^Ni=6Qw+w4ogd@XX5l9v&jw_TeWNDWsN#?$aBnU{>!WBb;S z`4`Ni^{G{;)TUvYW9`>?d&{(DKpv9<27ZM8K4{xVY-ovM6?d7VJ zze1xHMz*dA{MMo0I6T^;-ffocI*QG^*Bc_8viOdREvaiitm5w6Jz529Ln#o`P@x3) zCu~$~jeAHoxmV`y`7C!ezX-AenD8)C)g^enh$WE$N8QPSMC_%51UU~p?^cH%#|~5 zuBO=OAO+(|Q`am7viy02P@D+gXGQ+92OG$hOjI)35hBR%%(g2BrLcPLW+Mc#cJ1j}-pf;h>#F2b<)HU1L>K<3Ol*qqve zrs}4huIMASn*HI}W#Z*<7vM^kh3KRX{TbOa>MH?(pg9)L^J6?X zZwGL+>QbTYnrz@MH7AA8?1`GyjvB~YPN23Bzn0zMcHBK5U;AeO?Ozr=?HqiDJwZvY zuY-$ebr>!79)5||%$#`F&+=rBH}SV)4Yhy-Z}d(NPG{Bi9aEnNONs}HzFl4^E7RX) zwBY85Tv@fN3jR8cr`bQk_B#$+z0>Z>XGdP;iJ7V89jS0}-s#oPPKq>Md+5bY%A4>5 zI2)wA`KVl0C6WryhCcP_p>F#Z>J7jw__{)5k3Q7K5T1@cY5(KDfD^irZKvb10ywD8 z?o#9H$-lis5%0&>HC;4V*>5n*7z}LMU4My~-pP0PWU!Q;Q>Ze?=VfoGALG?1xZ))D zHAr@U+iFP_Bde?w!^*e*1{nH$(}qdFM0aECSsSc_Gbjsz2cyGT8P_6UA8@f}?%)Xv z<={O43Go?T>BF((wKXOt#)$FVL4P~`kK&AP#F3^ z*+t2>nKz6)e>upHnA>;0ape0l!CGbX!{ByhpjIiNPmJb&<>Kx$DlG~!biTY33hnyXuq}ZHxO`e&qlp5OrZ5x^8}oFrI{&B-5|^6LV)WX z+y&d5h+uj0TUST%8_wzxfE_JM%UHcRlvaxMRO{Z6;m*;JPEkKv-VRgh|G1 z<|6Zw_QtF)ZC#MJnYf*^`QZ}~s<*wBu+1sf!$FEYxJXLg>>Dyul)O=7{jH&IL#ezr ziZUbDWcS+I5NmPn?6-(%LH&n82^?{RhUe^CEiJ^fP@|rlH|I!&&FogHReMCi z_ef4%k=Kh8c`Xz1=~3i4p}BF6XZyh@(Vr~JEN#xH0-xe1;*y_It5K%y9j4S0$y{rZ zarSjO#Eu9=ul_#A<3(T9dh11=pZgOlIVqQ43u>--zd)SMwt(N+uJYMysqYC06^%Nh3a5R^@mVSQSJ%{4n>${;-KlE#6F=qY ztJ-S0zQ*t|I^H;3PJ+rBcV(qx(g zhz+q#Fsjbp+u{j!u~4<6{8$K0WUDFMWAgC2y8rIP<_b+>b}XjvOZ7<%x;KKdg_r&D6TWUY}@CDzt&9}+q`q$>$oRQ7* zGpfxjzrjLZ9U+YH4%+5^+CZvz1eqpZ0 zbrE?R!#ab$F@vtt&i15{xV+WVq`{@`LzjbPuJM?H9ji%Wr#Dp z{wDnrw%R&QrYdds*Hiw!GGQt({qouv^u&E;sZ+i|isG#q%iWeq*pw=OE) zIW~x)y#q=$!=_GCt~=?GG(uD6vi=Anoqyua_+(mWK%EQHs*M<_X3RY zCz!-WJ_!R$y|lXeT6)>E`+J9^4A_kfLj4>~L3G4sl~mS_TyYL|$icF3>DX4_R@S5A zI$ilrtGxSx@9|Z;JQ{q!3^2GoJ7MrVn{E1=(g&L(W;8S|4)AeHjPVc4!LZ82@Ls8V zx71?c!Q(}##CpS{uw)GD-v++Mh@_m0N}jXoNY6NA%TGjB$H2tDjmc0FGO~CLYo3Ja z%~>jk?z?pD^wFf86(a)$U53Kw)RAS}x0I@&Fv;hDahi=`4L8I*C1S6)$Hl5gv^h(C zCsfrDiD#$G9;AjA83eDj(*!6FyqdP1Ax@h2sQME=Aw?WX{zondr_f(VHWg7cL%V8j zm;k%Z^xKS>0FmLpJ7S|REfvt?qb705{ta&3lLkz;>+)8s_HRjVoD1wtw$Moy>z8~_ zN1iOxZ1Z_hl_nEv?EC(p?Wx}HQ5(}L^l}rr@z9U0=XpM%ZObjx;eek6Hl5>|XZgXp zy5FeOoT*lSBsY8>^6cR0-vp`!nH#n~A?#V1(m$Nexw>9SpfNR0Miv+%OmC z(*t$}30=PRXzdtRehKs!g~4Eh1gwjdf~DA@;b%eJrTm86Y0|mBb)x@k{rP*fH<=nL zz4$^GmXkJm*Z{&uNZFatO>iJ(PbQ8pX0x}$KC_fYZw%kIRSo{DxGL?eLy^L>mZ|TS z)y6}_spH%=*I(z1%Lcc5u_FNRT6?3sNY?cJP5;!)rm4vpO|)4K;>Lh>s#Fw#`3Xk=>;ed3}hH^pE zScI3rQ}6sB<@rBS(y+^tt2Ym-Mcrs~}v%A^b{9jzeduJf-{^0DqkSKM98^nPE?ydK$=o@{E(4w_63 z0>6Xu=#PUbzlZZNM&etfi9)|$aXGC^fqoR|UGro4CZPf*qg?}GRH1`ahjq{QA2+x$ zZQdWaGi{MJZ?wLuOAj|BT{?#z+@?W9V4R2$2F1<4uR4gE`)3fSDx_XNS`k{3$u)I9 z0OT5W`~I1?=Pqc!zuEJ}IW1dp?22Kfuvqp*i{?^3?rZ9M%`YSP<}Yd~hS5dxk26a| z-+B1y&t2`Gzt3GitNrEl^{e+d)!@T&(*-JvJ>A52s;#^uyuBR>yO|R^p*&tHKI>H@ zHV{Rj3ipgA6F-Te!atc;cR34ua!x>?Kl{tnQ|A^G{5LZLGBZ_1Xj_kI4t!_Tn`<%x z*$CREswG)hE;DFW{%Fag@vo-ciuD!&26x*a5n#Gpip%5}=jz|AfyHvEoK|+j|}7-3#>HM#yb3PXuxMuK?`IE?P z&PyBKnCH?eblY3R^N7DdPU&N2N{z+TZ;oF=B;D*#k!pR4{EkY!b_nMs5+O`Gn1wSv z;#WIYH0LEmJ zETCKlZ8%WV#U&Y@Qj#}|3W=vXnR3njTgG122Ue-Mi8pX{#e#apUV&i#DJ|J4#=>ud za5<_`F#A1lhdK-JkEvD@|MgBX%elwT7E-j||M5QP1V2#NPS`T?Pehx8MQy%!X3iU~ zXF{%;*#Yd=fV%UeC7m`V>C1hWl*nNl2B)853zt$>JR&y=NY5u6u+Q43U1mmN_@n+r z`M8@TT*1{rfJFguHGM9I3#u#VxQq(r(XV5h^{@TK-(p?KnyH0)S5$%{nhKN<-=xWpT>!Q7i+gTXDI8eGzi zSKu{}W)~Khy84CrZidSwjsxE#M%hbfs)-8S^ss5GO8bV-q;u|Av<(*;oo<7t2eGP` z?%$G>B%V2yd&)g#bTcI*;P;FhnhQA7bkP#}<9|W!6@NO zh!^kd8c%7KrR}6gq>5Vz^`E(Ve(LG>JZa*L@0Yt2OTd!r>BS3ALYUMZ38mdjwhMM( zYc0Nt=XClUJ#_IV|A5Zkt>1+=s3OPro78tNoN4%?S5__RAb|Z~C+KG6E-p|Vo{H`E0 zR?FYyQer2N9tmyQUb-3!>P&@BY_LeRuW0-rEPmq_8=Tqg+3;EKQeI`_Ep*Ol+>d~m zd+}Iy>2vri+a<*~uEpOBFXV)J0lz7l06L@Gq7qWuHYis^a|%eyyAydLg+P{KpZDaV zM(+vk{>=HLRWbONxERO%^XGiD>`=do$s!;#z{n~+pK-6)JO~J2dYMf}cY*C>MySuw%99{x|0OM+HlliNpJ)C6Vdu?Tumz>+g$I*cRx?-Lm*Kv?a@3 z!8M=0*Aj|XjRt)V3*{FwjsM}I_Knb9&j!8e#zVgPi)_8cm2t8uE)8COd`-J~9{$NZ z{M0vgXr|8T=5w@Vq3LEU!F^VMui-BS^f9-jwOOn0*Rl%r=3?T*BJr!9Yuz%RlP)N- z>uqfNRBzPgmEgJhW?BNfk+VXHgKy3rZY+7=`K%7OX~D@nOpHOK9_f%PM4KOAk>dptoS^B`=~I?UT?kj zPmG$j!&yQ9#R6Ozk{p_s!6d{TP3xScsCe8jX7+fduIdN?I0JrK8IK$OILJS{ibVP) z=sXq{7Dw{3udhI-P~+fw>lMaj?+YO>&lEeHkyDxZ81MP?Z1Vl9_b$AFg^UigI^T8- z051EV8sqbLc~|)_&Thmzi>c;kZkkvUDP~(sGgupV4r=^WeSvQ|;A$8_c#^O3Ifs0t zq6T}to;_{>qcirP1En{20rYsa5YQ~WG-y}!3HgU_YTaMyUgYp?o57lrhl5_q9QA_x z`0a(WQc`%-ILbVLC&;ng$gYsMP=np-ZxNe$e7=(0h+Uzs>?v~3V|ylVJqIYV~LiwYGO-cFZ8 z_WF7GTU&O_D2p+#(ufr1cQ4XZhqt${9+LBHTKkUvJX8!RsAYC8kSm$uo@D@#?f^(R zh4eo^#vjojd6yju?Wm|Q$$%3%pU$<0 zU$;IyL*Bk|w4S#9?%0&3x%h9xoh`8|HG_d??z8e*H4dA1?-pCP?;>EleehoVaBD?I zyWmN>D~a(4Wsy=l*3FYP)en`Dm(;#>m-N~puh^+!@5jZ>UwGoN)~wc-9hqy@e9hZG z0)OC=)5Sm2j!G9lTv=;e_ieqw{5f3hO!s6CdDfPLAY~IaLM;fZk(n&A(IH5T<^9z` z}njsl+orlk$Cwo`14*j6M)K)yG= zPlZTKVDL{rf6b6t_5E2==mM#`;TtJGV#faxaW}4DRE$|b?(Nu2nG^Exh>eZdUa+C0 zA$J}rlcL~I+E-G3@dqQInIwDunct!E^eW_8g(yU}zNBDP$#~iKRm^<|OaAjjwI-M8 z)w&m$)C*hUCgZAbzoRf=NyS{oZ;EVwt_p9_VkW$Cwn$Za^RMbTS(?qfXOx)L3s)3g z==E7VY;D33f*&32h5d$yohX>mFCL6sI^GHZVp4hp4}UzCoSoZexpEkKzUv{_Rwl)G zh%$t*#vrNW=wU}zeh*U`d3Qd%6u>_F2As6HD+QGn9TIy^r>Mq0OY7s58ty8?k?S+D zQ_fAaj_JQIXFhxDL#*lMk1f=**C0TnBlYUx(U!#DDl_rt=zjPf*G9CXfZ)O@mx@OE zZPL;i9rm0v#1AOIN1Q;}6x5>P-57kqp}Rk1tnn;4*OGnZp?Kke^ce-1?v+vChfINB zL+9gHSF-p#*Do)zH!DhW$pMSvGn`h6jTIff)zB&m!=C{8w^Kvb85}l1~#V&fqQX~Tgzl$eG{!FrEo~`>Zg}^hMTFz6QmJC zg2_Pigc-HKrqGBt_CVzZ(KzIJf2PEz=pB~)ELLTu5NY*%BrdJ=SEm`vIk82SwCD6w zGSC=nLW)!+Kc_e#Ec-a&w+ zNzAQ4k;N+}gQP9tbCACT?tRhhx?@$ zhe#)IE!b!J^#(C1V50**^(LBNT3Xh4u2}94Q|yEaNcepExRs>n%9(l! zQv-Q~7qH`)w3*hlD|+qGAgv7Ir$3Q)3hq6{xhw95S6AGTf$gtJ{T>+5MOjnfQCzqre zc)s%vsRS-P!Q=x~+&U|X`vM-F>2D5yA80c!Cnhr(7n;=I30R??`aSDtPKC0;d8AzcRA^`7LGjv7~ zPf7D)gpZ-bg-n!DoJHWmj8J-6`ss(DY`1j7nR#$oP}?iWHLdI6K;J}&zhw;MS}*iFJ7xTBOrB@{#6Yr z^{`S1%W_bll-CaHNTwTU)S=Nh%%ed{cHhmxKl7&f!Q95Z`O_jQpC@hB{QO2Lf7$d1 z_Ls!-k40CCUHuc|5^P-WWzxB#siM&s!+xq@^4sus49Rw_(!|~VM|`nik3I`Zxs^4p zM*p;hqY>VRTBwEsr9u+KXjtHr!;C5KxGV(@aUSTuW{%#NZZ_|xw+b-0-Ur)40%AN= z1Gr9Y%riNbp_G3Fe%&0Py{0V%cRR-bXm<*ew=YdE_6huX^5vZ)azs;`0fMUh`2x{s zKJV?jJ-#(6=1^709h2e;TlG!8(EvASwQ* zEzEz1wRi4g^1FMP!In|mGVOk%BM61KdBS358a(}BZbs>&@=!$wG0SHDSA0=3BiJ?4 zC;kqwm>;mCR^De#&wMoS)$w8!*N!tx-Fk?S&0XEJ3rSiV)vDvF+KItqd-kDE5r<~H z7J>FN2I+gfH($6ahKjhzT~xfC7&?H%C#%L!(@y)N=;=m+;BEtQjxYV_q8f zM=#>vPk&-Gz5cLPsSR{Tbl!MI#mN4PL|R~xc$yuss;tyIeetW>sYemj7M-9)ho}#o zM^1;IzoKmsH*sB&V&ue$+m|xG!b}hayVjJ#+}Yk{HjTtWdz0}B0_&!{V+ATmM<>26tq{U=DiWOn z9tn00)hKyU+4I3xN+v-dm)XRSKCcoD&|iVNBEbEq&vQSew+<(wc4_|zs}n`-roekk z8QKgcFcA>%?y*DG=Wa;*#D;>bEMbE`2&$3EWN>UcOzN%3>8O~QXO&6Z)z7>;@CS|k z0Q+9!f+)5X+3=tR#=%mPb~Qftc2y~xM~P@0mQ82aNBOcb`4-DM^OwrBJn@zUpT44> zgvFN&Jo&joi$w(x9k&&_#WP;A=O8*s?;IW9 zesYII&HlXzFA)6}*s!AGL%;LXuq z0vP;NV(aB>T8BF>JPICjwxWGzKHCuR#}u%E`dJXX6S%N4Cw+f`4DLfApL{KJNk-P z#|^S7Nr?_h-gT$B=Yvju=K5IlAN&;75Ox$O0`!`kXD@%CpI&74V4|UZPIWh39xoT2 zGU&DCELZiz8ymoXe9)gUF?L&9|JKG*jUEGUcBqC7iXi-24`7o=UE?gH_SZH|vsFi}cm{i-&R`+3p`&}qe& zrT&|bH}rFnn60Y>&QPn#zg^d1vb)ixB)=fA3}8$!?vdv2mhE-rLGl@syK7&WF8E9& zmY0-aTGZtxfb~;svnh^67725>UlvgkksC4W3)BZ)D2FS%4a+U##g)m1IR+vW)%qj< z#ur*Y0_6a^4fB`Do#UL+iMjs}qUYI9TrIOa7qd6NL@1O0Lk31zKL;I-rFhH^POP^L z9r&G06aHhsj)iaZ}N4Wo(`m*WRg$z`u9NzIWhD_8r+;{$q)h;~hLSa?ea)o!%$UGVw(fXPB-L z5)!K!jiT~m5&pCh2K2ZRDKcFMbl8*Q*7=;vL0)u>@y8R|^~Zyin0eggWCvf^x6@x9 zrYoE~+rw74FZ&+z!PQ6&R1A{V-Dfz*l?5Dj3;@us7dXC8c>#J%Dp<66pHlfLLCQCZ zZ0zIq=i=irBN#6@wB5RYs7Q`>+MF{J&QVCd-1cGty3AyYrLn3Vb+E)PSs~1G;c${-f5)pL!at*HiG>Gs#t?WxN4^USzWH=Z$j3i)GWw1R4) zYxAMkR5BUe^WOfPFDO!)bN*{ALK@g-zyZUdF75Aw+OgUuOS0=;IA(zbY@8|9$NSk) zX3Y#G)ntN10-Lx=Syc6veLsjs`_S-YS0L35>~FVoISq%w2?97BOz(A~{X)cxPsZDq zzoIe2l&D%!H;e9rRVxh^5?%Dx6|h-F)PdRl(ws64;!nP1Okz$~y1klFl^Hpc9>h@* zi+NUojxibZ!HT&RH$42RuHs&cu&BM&`o5-b+q7HWyqFVCe$AE2^p-VW=|5ex@c*}zhQ=bevH&c6bVH)jU zoREx+>;0WZ3BZ$ms}cffZv9gm18p--acfUVh`zBh3}R!rCt5KT;>0O5_d)*n^^2F+ zI^EVG8NgW4$6^7_@Og4$R(R0RI<--&*WM$T9^7hZBBvJ6P+k0lRwK_2I$aT5M{qqX z??6?I2sRk_Tb5+lrkPckO+LF8yP7zZlw{Z~q-b*wHIuT{*TF9Yzf*>5yBgO&=fFGx zm;6IQ9|`}o?BA|(W>OO282z#|Phg{1MI(Ow3bY7xoTx*fHj{Bd_A`_ivm>{TO<$i6 z1i}Fp`UY0O`sY+>8)UPr+w1Vqd$n+HQSF(KYexU_=A4q*mW=(_6733VTSy%pcL^$~ z1ee50d?4VO5H*{gywxzWVt3r}W4kYohmn{=D!>*Kthb%Bq!ur_nK6gZ2^X#ovpPuT z(?Lsq_3&E9u@#h??l}$S(Qauk74-n^rJl}Fda<5emV!aZYLzV zE)p1qRyM6IE;lCc@UZUIYSgrt5MmbgE|Qgul#o$N8H2jbnSqi9EgmP@?zF2jtS2S~ zt%i!_b5&+irCoo8IQ<_VjhgD9!?63at}nD!jHN#NezMC-hGS_@Be-+pR4^3unu8g> z#}S%zgK0S(bVk z2w$sp-2%hn&|Evb2{Cdfs{QIhyc;r`d??Mj z;JE%^&ppAX$DbunyTNw#twKsJ$bRA1S=JPTQG_08p0igl#JZltsYzrN*`5^X72#zE zGDBrSvbhbTgfKGh@i_S{yJTj>#mk#Z~J^$*!>869c zaUt45Gw5wZkhSr+kE7UPUR{2Ntk)lbi>BwvBo!kMZ)QEr0#+^bM&73@b_19CubvG7>*0x;chHs&qnGD7F? zIqr3hy0<4CY^Rx6gKyx4q|enVv4t$2KIL&~gH`(Y|8dqQozr=FZM9-mqN|nIU)tYY z5JraORY*}$b~S1LkoDD|v3BAcKRxob)y$CHYB_#kQ7i%vJxl^ouM_l|16^g`(MsEee| z--zRC#3p}pYSJbT&ULjZZcRQ^awa6YCGqKSsS_!=jIB+@g5De0q!7KPaJV^04arPokyp0GYi<(QN=5QK!!#i_2zG@@g~EgLI;%$Tl!7S2HVerJ z$ITLvk?}gN-SF84WEu#J@jC}uOo>12srhKzH~H;%qX=`D+Maa#A^ow7#~|K} z@Xy#PJU-$?=uvIKwk}+K9LCIt3*>oo4bQ9pZm%NaU8(xQ!pZ31pL$1z!BE&~YRbd? z&a+|Q+zH4e;MSr*b*HPL|AcN)^&i!Fr~@)WK8N_0_eEb}uW@S9#I$J(g~@$XEp+v+ zBX7m-4pU;uSP?z>PBoEq<7XKxd}yh#*K}-mPcyhK*hv9$m`fF{^ze^C$&-V_k(MH# z*%>|rM*6vM%D!3|7t2?Zf_3Lr0d0GHu$68tyIGT6N{P`2s_N`p$p_M3HcjEH_C3vw;y#5lfBP{QEw0zu#!;Y z{=5i)bjge<#<=~~QyP#!*L42ECu6b;z0Wlcmc7pPYUKr=ZDaCRvOC1@vkdX&dXwnU z#`EZFIZ*+LRn-c0W7ikj{oB1Yu0%Yg&6I$O46Pq@VL7 z07;a8Uwff&Nn1J*0$^(S;XN#Tg4?9cuGx)Nt`8Vq+r9y)r(TDV4>?pzp@j*_7H28J zmzx4s%KoWU{xRQVN5eg3c=6Kms#IT2UI8aoiItC{PhGHZL3NRu9X+RT&p z12kR!3oO18X;%9+xM093DZ(HGriz@T7g@Kh|0tHebKV2d=Kn?c4Sjm|+P42axGiFf zVl@MZ+@6FfIowvS@$q025Mz5OkzKZm+Bni88vQJ>?v5{Z{^c4S!`Dn+BC=NkaN`&=?(K!8BJ+WQ&k=I`F{wxVc0RiU zstL{PbP=|FsA7<&=z5Tn3`o%N+TM7!osg(@!}IJp-3Q@^H1R z>EM*%e}X6LS(+sE_9qc$8(u{Fx-0r(=u&XwA2d?wFMlRQ@c`d)nL42^&*7w)ak@W2NRBhR{R}6YAt5#AoJq4r0>(Mil!RC zZsc5`R`9^i3Sey=?%e3aCeZarE_Tqhp+GNU_1r{EvhzgCbiL3*`x@@C1wp(iM!G)c z<+$LPMNHR~qz!N=gK}qIUoLpS1BZmB$uYnaNNU2F;O^1g$XG`xXZYH_MKDLyQYhC) z%vJ0M0ul2IV?cpf#dw^%8`9$i0v+IMceiT{NCl8Z<;qIA^$uK*61S{_5Zsc1xd4?U za4N>6Lrk6ED~wPQU0{L8HaYc;osL+Zteq2?82!ZEyj(pedMT{Eq2>tcct*-H(8!UW z{!#?s{I?bhjbuVk@t!#m+?kgq3Rx>KDl?MCgcYm`MnLH@e-uud1~gG8qZ#Gq$84_P zb(w>}JSe%*UeyFzWJM*md1=+Z$b2SSxRoJ1*2NA~EF4hU#1*Yb-t0}l{l`(4xM?%` zC21zLA8GiW-nrPjKL`Q5tAA&_e=3@v8QodDzZp<`txRCk&FNt=c2rS;?D>ra^u>*w zDN3oD^^&|c?W5U*WO%V?g~ZLFvwto9sXFh-!mIKb6x#pw`?HeNk@aOC!Os1rw16Fp z^Ek+pnp7KVTXx!Uk%u(gU`?;OOvZ|ZROoH=p)u-$hKfhrW3d4r%7Szcn-AvF_@$Mb z?PU}5Bqkn%OUX=9uafM!CgJ{NM8L7drGxJqiuq-$u>FIy(V1w*%gIb)0=g}E`ysh2 z6t@Z0^iv)JQQ)8w_+N*{J=OpvlipoH^DEa$o5Y7RFSoRy{<^hv2$hn1x$-a^)j8Cy zp?rN96=*>A!EW!4ZIeQ7kUL99l{UHBu8pVef_dN~Skn5(&a%_L3UHYoOgGwInrIhQ z{`%PC6-9PQF|bG48ijxtS9Vyy;OO+unnnG$TDr!-&8g|4a#O7C!q+0XG@>6x6!MpM zo4W{tY)qb%ozP2EtG39PaVHoeLP=IeqjA^TuEm;nyWbH{uyZt;PUCqiK2c}QL0L!0 z?TYX37cBE;@l(<$*2pr+5k+JwLTro)guyY#sQ!(Zr;!UKY5SXO?3FC9QQPW@z^CAJ zb51|j|4FLN>k}$ydtr2;$Ly*tA8p;|ERRyr_Es{^~l1~X6%dQ`lO=2Knq|$}{y)Re$^V9+9L*drCG-G? z=Z-!QGn_)Ec}q-ndhJ2|W3;>g7#J3W9O7 z3<{aSmYcpslijF$LA7H+iUIB;lgT4uQ>m;R^JIh5BW9?%mj!VmmZRFp|BxAiT=K~7>Y03+Ow2q_D`n2rk z%M!EFX+6j_{d#*o##xc$qMwNe;p|$&ngM(vFVn6+>>*2ajl^0maMNaa`}DNID{zYB zus}!5n0OTdFrHo?3`2YG{Ku+G7ys@!DhJF`*AW^d_AR*ne?l$I^)jUU&mJD^FxUa5 zX0g4hZ{8(Umr5(@Mv?DW%#wZ2OU10U9D7mU>~;6HD*ih3qitoxm<&1o#R9~uTqJD{ zZ)KHloi;4&DYJwcqdB#&%R#V=P%_twAHX)3Fm)YDb&va8G-Ed3l) z?QW#a^ro++M{kABs@mDrCEOmUAgm%3DCkK9=v&cSve)gj0@_;tALBl(AM>jZ<++GF zJKQ29J<`zlIrR23C%4qaxrxP@ixbnpa;)~1(w`JdF7MrJ=Qb^1D}Sbe*Shu{ zp3pDqiHP+H-Jfjb!!0T^Bght^$*-|yFStWJro38?Y8&4oyb?y=Rz&Sz0tsRx$HgB0 z{uW}Xj%cWn&a(D{k9w&DSsh22#9jT%wn`27ku8pig=XG>8=4R@XIn^uSE3AA@~(q8 zAGn0`S4xX&@-1PZOi_YkXZGCYq_8_}qOQ3>2`^a9@0?N98D`HX&sl7X4G)JEI@SAF zpQp`y_SuT*GJh7T(!aPO>u*;2?*0|+(xjJ`?Q*>VRlApPb&fw-R#Pac+onNbYErpp zUeL@<{MTb)d)pV4OfI|;F)_iKaq8Y>?>)LHlX1mUk=O1X=hx7tFf|LzAb+M>&98C3 zfIIBJQ{K??yn6KCWUKMif13_QJqVafp+@gD5BA}yVAE11#lHrAu%C_DzE1ZeiWBsH zyj5`&yRx@@gx(AFP>XYX%yzf`4L*(5(~RFRCxjw|-@z{o|Z{EZ5{4&+c3$&5$$TRL;D$g!KjIrcw`krpq5m zN(1xC9$Quq(kPE*VBRHDKIMRDojFU8hp!M!F zU`H@pXY0<6LG{YYz6eM)V<~|>?*m#iN73xPXJ3WvI#pT0M*qC3>}S!%^8~zP#m7wh zS=@XSSp&o!>x5LbBy*091mGO#QHGC&A$H~ z1$jNffikv~2A>C^ndSh4Gli@oMuYVG7f;$B&s|d%lJ9xQ!m{DtSl8a@6xeKTNY zsnRwsTVJy~Es+jD!>g(oa|ciR`e61=AB0EiB<@-{JNz|>Y_H%s965q`Z!*+@65#6Nu*x2F--BV-L&&>-eJIA8Ap{Pl@C{L`cI{e8k@pCd)$1|sV)Z_ zG}D{2$Hw-$!Q$|Y8wnd6(tQP$mV=e1zEe@Xo-s9Fq{N%)#|e);-2_#L4J5aLGmU{U zzPz}-d>RN%Vcs;9mmPrHy&TKL*;);s&%VMKA2*RZhf_MY+TCa7hHJ-Exn)aR_w%08 z`Ejd#6Whr`Y%YlUEc-|XwuyG&?av&}TP88HwI+J?WO%n(za8t~Gu$F!3lE}hmYkwX z1Uj6jm1+YPPq>8^ew|F4(gh3gDWvAoipE4P&EV}(o3f9uQ) z`m8!3TEE48>Q`-;ia<#iO}TmW3G3?VWaH?eBQx#L2c?c{4@!%ZL8w31{v9K-F|U01 z_So6geGT9Lc&6nI!{m>xt+wUq$w_QZy~pfpiu><$y=Xym>_9cEmJ>_oZbW=V4B+370TkyVPc=JL@oWkm(s|_-00jifzIxn>> zD0?q-O#aSL0`3lF#^zPjFv!tAP9tqIFxC5LMuAqOlU^?;+#C|iCtWidXX<^1BxD~R zwhV8x9tX}h`!X2n-VL`tjq8=JBx@k(cB`UjIK-5)V%RL~6W(KDZl3yNXXaKKv7^9;5nEc^LuyiffK_0-9UYiRfKBSSH+S&|B+% z30&!I3glj+XMnUi2-Jf1ob>GeZe4rv^O&$|iTtA{rX3Hh)r$6JF_)u{2Zr~2_Z{K2 znh=f9vYT$25Ickn!Q*MvWDPn0#S4UKmiVB-vf)XxXmEk$Zo8mNDr)66$}mg0otdJn zI2N5A8%L9#Xp?cD^Ilc#^nVE`e>w*%v$8s!&fV&|L+Z_sC-m8))*@YkUsw@zqldT8 z5TtL9>Fn1NhSeTs$qV1FW?Vg;cq!p;2v2x?yN{#jm!D->r(9iQHpc3wTUr@_S0}FC zlQ&qOjSOhIR{Yu&h^8N0y6JT6@8D4v6Y7Vj?yc>NZob~>GJBp-necj~f-a3H<4C`AaQr>>6PS9+PnUaG zz2LEGV!eWviUyH7l{duEwX|~MYHSEP)^IuIu1VvQz8L`s11Huv@@TT58#Ze*bfP63@6}YRbj6&**vQHsVAJMa4^$&42=@Av^vqCAt+Y3O2=&@b zBObMzAPG2*o0BEnhU!=I17Da9I-o&?NfoHr^C6jM2iN`wo8|nMi zs(KN@bU$XN?FyG`+rooiSOPCESX5mM52j`&q4*l#QuqAzA$(qZmkrjee}|Z^>Y~b& z6!9@R8N06m9-%F;HQGK&>P5B?f}ZkWcPN-%UX(|`G5t$y)Wkfdv)r&}&hMpIF>q*l znY3={1{H6*|5vhy%Ov-4I(wD%&A97dmZ)}_ePNR8dekFbWk8)-5_dCj&E{>n_5w#I zzc2hcc3@Vxr1%wKVoyndX+x`EU3=Grht$J3TMIj~#%vE_4D1hoy)_&HaHzY2$3+B6 z^v4!4MXTxDU43jBY=tR$)LDB|iSF;&Y(Ga2#fRFDk~MCIUdiXol+Z1QMz=qSCd(9V zHysRI^P(86fT2G*>>r`Wju=(EixO>DEv0(iw3y)fGwQuG`{a_T7QZ9`dsbVfATm@I{kyd%e%>QL-}VXA?tdo zn{8aw3bFyohCFwez{V)WgW2;DCm+ecG->obR3d$m5m_Q(3@C>o{q zN>u0rhwOJ_X_6o}&-cc17f$JBd4`n7HBE+GZ}P&Q4fKH?Bs=~i>HKeL8Ltw%)h|Ih zjg!|TKz>lWLi=K&H2(TF{6oYjLc}P&cM?>0i`WKuGhfB+XC0{aB`Iqpr)SP zKezhSV!CryC&WG_P9tQ z(RHPYgdF(A2v_4&O@jYU55A)0$FZo2N%s-Ch(Fi&h}R9!wTRvkKOj}CBS6vFOP%uL z(Hm12B6$a!oUeH!eHmD>m)`GrhX=T;YLf}o;nbYxe$;`r!Q6FjmTk_1A%p_;`kJ;h zakCY~r&Xo4VE%>m4vYFBbe_F2yr(MVaU~n$PnH#4R$@wd)~}j^DEmH@#DrQEePCIf zdrrAb(tttd;EJIIt)I7ehp)9$Fd9~?5G5&9_!h3(M;=a+YfmQPp<9Kk#*QPM>No$; zwVnFJFaBm+v@KrKb0hq12VKykUJJ)DPPbFy{8s2xjw23QC*V{o(8H@%4T1H>F|o0Xjg*H{zY|R*=V}R( zFGJURnO2>Jt#~|s^8u;CN8>w;fYRXeT&;|`&uUbs+k7q(Hh*nNs5W>r(FFRcm^L5 zotHrJkpgx(>Lwb5N+wSvq{Sn9Zjd-*x7!cHVF55b=r^iQ^!6F5$-{c~2V5-Gk=V{M zkyWEH{iq}s*_W0Gj^qC6J3(!$70`2pc!S=+ilaSzr&1D@qg#GxYt1jrZY308_1h#^i5|8k;6#KC3tYfD5$W z4Un2n2szBy4so63J(Xvd?q*s24wUCwT(f}S@NJP)$mCZo+Y%c!r^vr3vQ3YV6?OGh zeydcF7U?#qTgkRk0cAPG!=*B<0P!#yuUO%Q;v;!~L4c(g393tEDC zk(JqP#v~mh`8y)UY)o9yR!i)|v#PTpzy7Y#6eiaW?ZyE7@YxFoCe3H|nOl&7kcleP zSiID*{FN*5V-c#UfN);(PT|$v0JjVOHh}ZM+A_17&R;#L6KAI=Nc^jV{XUB_lSI*g zoy;PB_Pl__RGQuGdhgh^RUc-n3FvnhgpH3dD5_6HOZ&e@@81VoZsDExqE`7zNYMAK zY5PYUXwVHaZhHngpk&Z(!Khg+uTSn;R^d29C!VgeLq0La8xg_ExTkF8uJTyJ(SlmX zu=H~AstCG0D6CUoy`X-n5#(ppkG=vEBRoF5axX}HB|}#Gm$v=Lwb{0n${{6$>bTSk zbF}#fw`+c5I?cnmRr-L;_CZ6P6tfKT)J3WPgj2iRp;8e?p!rhZ^;z!V> z3hr6;JDipJ^Pk;{*fT%IjI{9Zgb?G6+;IEN$*8w{eFX)MxY+(^M?<96CBM3}$NC}4 zpnTky8ZpKO<1jV&0&^?mB zCCnhm=>xjEHJy3^5-{^rRQmt7?*Byefqy(lbqWWr@9J+OCheNT;LCNoH%W)9KYF&a zKl{Zn;MYp}jL+AE6q2_S%$hex3#|B73f(nMpD0=utAl-t+P>_U4^@;K`MX1Y_-QBp zLx1`ZOJmc$Aa}Tu9n-qFMg(xjJZ(2x@TlQIW4&56+Sjhy?UK77y%02=yyYSd>GB^2 z?VO}F!-VzchAO!+y)Y}TX3>khSm~EWi@Q8UeY!uw``+`|fp-kd4NJocW zF?n}M>vGqqJImq$PO0%gET=n`VjV$PFu7uJvN@zmpt;Ne(=_COte`HX2m20&X3{q`~ zHTrKPCP;{!*5lcg_FndapeVT10ck{fbfPcQ$FC5U`9EUTwbMX-wz(M4hPsOl@RuC>47LkRMfrk@a9=_@Xm+8yN*Kf8I^jjoh2q{a$6D&20b zT2SBG{S=k&Q-$9pOvACW^Oi(FEunvZv1BdNSvo@$hROHWPonfr?mj*Di5GO~kKTe% zgs@76{`+8e9wqmz&Gb#XhrBzR%mJHWeu$q6R*j7*+6C<#K}~2!wXDFpjLyv>S$PJEy+A!KB$PlWo`| z`}hso^d|Tm?{*pdytnx9gJYUg8-8EU>(V~y?E7<|VdA5k zK2k=WB?ri`tsL(gW8YpOR1E+S^PZfx!f>PCB22|eFl>Ab@``m7+mVd*7)DQi&_1w@ zIv)tgrEZ{>f3-I`meCe>d|wT8HjKG`L1{UMI^eA*oNv6?(1}^#ibyt>1Mv`OiE5TA zw2BrI4Y14nOI0jXepc-VcAs2+&wQ2m?45W}Op}Mpd^WpzdV~wX*KM3#1z_rwrc1== z#yXAglL~xSQm%J#WBYy0H$onqUkS185d}<)`M6h>uiyZ;`zeJ~??A(Id$%-`p7vJEgkvDrC&Eo%;{{Wx-*xfnR@$BPOr?qRd7t{}CB6m16;3CN2S$26t z$-8%F7FV=_cb5fsCN+YNTkZVuZS-X@#hpf|Y45e1Gb%pQG4eRn^a=N)gw__H(+xoa zbYLNP$ba!)R$0(;Tl|5tJhieKo161N*+o|UG z74cv0BQ#DB-chcp9@alzDOaa1*nQ!qRgMGAg>*r8_a(OX+;Rwg{$Nl2Hp#FZx6HCn z(yi|6j`ntD_x=Sn@4Kf_x#*17!-Okz;mX@1>{4OjekKz#nxA8?3rTaHqTHIk-X#3^H z9B{BxrnD56ARm=5bBUeNldWp??e_$~V1(RwvcOqP8qd9Qqy|DjxA zjzjPL(kI&N>7R70PoOcTh?+gq@sR}@xzrJq7$>%U7uM^TiN5=&q6?yiRfZ^uf-f24 zs?Og#rZ^11synv!k%031nCWQ1%IMpsJ5cF>!Y{~lJx}Mt36hW=_U7}ZMp#Rd%yUMX zH?x1~Y~MY%%(5#9Ydmj(CR#)7@U=B=D?piv9ky4rnGD&~FlU0U;d$LA)MJ zUvOik{w&M-S_aVEXBH$?>)--wkfsQ|?goCBkR%<4jiZ5UY)Y+GMk(ZYuSWBKsc;#V zbA+Ms6tQI@TY1L82iGgrP45hQKHEmP)d=jS_=&!mPGkB>$NTTAeS9B8ox?IjpXuXx zFJBxw@1_q}*GNIa; zFU=P3KPYXheit*HlDI!e%S4)&pQ7++0yLLj?Y(muFekjso-y1&^mo!AYQ#CsamZPs)}hWgg%5iM8(5?n-pJh z7+dV<`SuYE*ZF1BkY?KQ2fm=J+j$L~W^3;SI9^{LV~a6vr}$%#sV9BD$sp$kEfauUQ_5Bg{B_3EF4p0~b8!h9 zcCDB_i=kZyllh`C;{_LppjZns-5(bFU@S-pN9|P;1pcrFN_DI{ceG9E2 zrb!o1b%11>zgnm04!j=zFA1&$j{!-bW~``sG4G6d`^k>%_O_!l*+4v2{T1uskfBC| zVel503HapQhUo3f@Xa_5YnlF?e9ZP=5IBr>s^VIX_T9OG&9myBf0Xv;>pZ5_iolI5 zE!FuFJFR`kcX~@iH~3U&c3_Z*Vfp_Z1e{_bpJWdo5W)fTb25Yh=3i55cwIdA?a$$u zyOCz9^|;Pk@4wDXyvu%Aa(y%9_ynwMoUWQbDxjAEs)21d7|xCDu&$an9)6=>BIoBS zG25O{7KSc(4dT_RPkMeZM)eS#auF|<4UV@#_a256{gpR|z3;~)ewp(%`wSBH$5n-r z)9Ke+v?5n2J^Yvy70fkvG1n1YhQ5u`yzEs7^Pbg(RRN;eBJco@a&OSpD|ZY}4PAk3 zq>KWA|M=^yCZtRpTKBdoORb>`(!}j|Fjnv0!!O2=P*+g&O*S7>{C zWtC6W-0;-5m$Z4HWOfn4mKVN&0I;kfCT6Y@n3=r|+vS=6rL4r9j@bU$3Upw#o^w1~ z&wQWT7#`=3PJA`DsO@mnLVt|wdG+-bu3c__KUO0ObC4PNBoorvwaIkYNvIV8dt98h zI-Dx1^#W?Y7~;NmOk$)SbSJ!m@EzfKAeJVy8Y!RpjuXDV6<6D4P3kiTvwQWx<)&O;lgApiuk1<86B7UB z)V{(cr_5gWpXDxGvRIQ`x516n(a5>5z}tc#EMI%A60M*ZYNquBQbC{Fr~O`C#RfW* ztj#Z|5g6+JxnGKH#Ir|y&1pMVJG?$-g%oO5^KMjeuIJj`E@;LZG$x4_v(bOIUg*{l zC8zK7xu_S*@}{a3!hXXt}!#T>(t ziNT+clZ2;^qGa!C4@Zl+9y)bnn)5f#H89wpwbad z^5N;5DcepI{lr)z{#DNrysCdMuy>VvMT2FrK_mnncYlzEYYNn;n>c-Mclkdq0NsWn z&EV~_toY?v<|6OIrD>=8y9R-RqEa}f}?+Nrlu(lJMj)1q{Zw& z2uSddUNZ}634W74;?OIXpx31LQk6-z-(+T*HUF*pRAYTndA`r2JGSc_PRz%`9&}^B z2>1Rk_7-*v@>)_3JhK?Z~_uLEI-`_<~w+=uOGoF6;cW(^0s$WkU=?8XNPpi5cg89<^zdrU_SLi?w zLA&?*@4*XmP5EUA3c;?Cw$gqry)ziNdsh$2OFQg_I@HwA_2>FCc?wxJaw!SUYea+I zpCx(u*WQI>ZnU;|2N3q?A!*Kn3i-cMyy+JeNC&^h6mFwDr(pB|vNfiwG<-|c?b!$Y zO9qp9A@U8EyQLH$fH>}>YidW#C~mKE{8t~yyD{FwJ<7rcav+(RehED(sndLR@p{us zA&!8k+eqEnp9{e!>uCdx0r0$niQJ!=E)DKg*&jMyUF}&_gIk=j7tq_-HyvA!CGyl% zn-{CA$mulVpM~)WVsP7>j6X!)j?Ozn*@fApO6EBVa(*R0z2Yd>6R$TH+}F@YQ?Y$Xh+6ECdRH021hK^x4k%J@H&mIPb|Z&$eW`WXiYf^c^er%}(>Mv=x! zJasoD2uIXoQ=q2Spn4}*VY`62p+jKozjJ-g8X(a)-}OSKZDm|Ay?rpqq|C!1l;b5p zFRrT)xEZn*xTy-?5EX7=5!N6vBAfK>VDl=gtp_b9#vAN_@gX(&(XNEdfSR83TPzqg zC)%eLEuzl2CH0bZ`;ofeAKrRheN>T1J{|HB0a;yG$lFfqX{YHMZWKx5nHW9Nx2WaTAk84o?abXb_I>5 zb#^!0m{~gIh0WF1M(a-CoTe1TF!3IVm`gXDxgE4C=m8Yyi=A5vmzN02uPVH~K65&J z+0px9?J>QSYmnoE`DC|q6)TgF6|ySubpNp{ew@LcI{NKbiB{BLvPIL*MPRAJAhBP-q;zu zuj8K3_z^fsPj|tCO^pv@YqmcHi9~e;c6qRkQe(~BxA$;k zOkobFph?2%W8ZL}xW@j_s#>08sGNyLlY<3BR2b6iMOgOAZMxG!z)y$nwW7TcdiV+n z{b_t{TfjkWA$1beH;PdhSuBoyTMmdH(u0=&pUeXrs;mv=U?^n2zArMH<(vE<{_7Dvp=Bh8-|3%s)_D7 zkAs&_=y@^%#$+Fz-f81UAtVT|zx5e7*cj7Z&{qMImLt0byA3jT=EYPq^Y7XM@>!0O z{yqbKz9=XYYaBuszW5efJJ-OqJ!%<{hxCBn=I<@;8!Hn|Am{{bGjm&>m+Jz)v zt)!KALGngWuCzk({S$EaC~?|7IW;lu1pf~ug5Z{d%CO>#06ptjwWgdJvtcQ5FH*Y5 zLXeeuX|1R--`E_-4Ba#%(LJ90bGp~Ru~jQKJ!u30NDhddkMOx6o-^zxzrRv!e<6dr zIt4TVKRXw-L=jJafmGEQA^H*94~Q0~W9_l&fhRS*7RQhLdsfY+ zS`a>qskOlYtcNd2O+z5`e_-!NmGEP?`_9nTN4k9Xzb~={;KzI?R3Ek9=p9U9>gGpTVx_N*3`MXMqR-6 z&{&+%0I^p!^)oJO6uCOhHg44xY6w#>VJUi}I&0ftouNE>Ma@ZsjP2*P1GIl>ipNq% zN6XyqsrXon@`Ij!C62NT%On^&r^Q=!ftBZ?_a!z%0_!$5-MBX@-rnnT3Qdd0m7$#W z#2nB@V-4l!nzsTZH5HvsEDJBzjPz^KN!q6-4JV91?G!sF++)%{|4KVFg?B4{Ip4+z(*%WR=Od7V3H{d6Eb7Y#ANTorG|6H}64PnrF2p&sX1FuY|QX z+xF!xbyD@h*P_%HSgX5+T+V?^?F~1juRmB!1Fq&$R<;ejr3@P6{Ia?rRT|ABeT^^g z&18sX6*~M`Ef9nzLLZoh-ifkh;bCuqv;s{h8@1duTK-$BOgZuH;ixwFY90OJ1k?`U z4WRkW_4LatPlmMr#qL3Xknu1(#0kkpW;Qil`rcWpc(OZE5zHA5>#eToPFS}NH z`5@@Xhx4Dr+v{O6n!p4LYQU)Ibt59Oqb?U#blACFv)(yK=un_yLJ)99!#Z|6w(>kV zCDtPmp(XqH0zmhQ5=}*>a|I{#TWg#h)0l#5s$F%M6Z^9SjLirDVO}6t4f_4nckxn2 zQK9873|pmP9w)iKOm)~mR{77pNuW#rEiB~cT}S|SI8~RZ)O_%amR-e`!z$>2tJADV zb$>_mUadoQRdhK3I9HV$p-K?FA$@L3PbP0cJrOyIy&Yi-2@9#;z9e~{A*#2g`D-{r zq=zaDPkuy4R^K{MPdcnC{bun6A=56KB8p41$bnk?9RoeSJvC~R6IQm7GkE?Bh9o)3 zJrVHq7AS_x_TGu$JOFispfcpwqTdukGd(pE81dGmmtWbmD03q<2@;2L6%u}r1pJr(N#2KgT{PO{Ce;v);U4|Zk^YpOigthe)x`{+EnXMb$h4eqAO05q4KB_d z4g|F4?W|_ru3&o(rb@6qXmzl<3+XepU)NT+e7|rpfgpN(R!l`C(;4|T0Wq9BG!e*F*IO{?lbr}6g)OKmV>G4NpjXvBGdgi8<^-9pDVD9c8l8^F>0(QG_ zJW9u?Kk7A8Kd>j3vrvIEN4hxc2^)CT0wv71Gg=s zP<~!S^S+@3{N)716t_4bk@--n?A8P{@Hc)3f3|U>YGG%txMX4l@euEf%-qAv%Xp&{wjE0r5Y_wCx-5*Ogb7DH`BTKfW zz>wT^bK1pG=-Ip0$usD40EgIR>|QAtU08umEG?aKaXKt%B1c=JJ0=wVH}`sp9t|{# zq1l(EFurGreQVZ=u7^WGg>T+5>>Ia-N6%IqaYGGm6z-s1@}6s*;W?>m(`ps|DMqoP zGL~-QZuc!O9jmS|fqkb}qa1r=s{K#F+2Uo6rupndlshX&9cV?y4V=TcNTJj=~ltzVHT3< z6Nv!pU5IM=p0#~ZF`wtLa6Pwpz+Z96EYe0cmXYM#A{ZX1u1k zmS944XSAFP1()2Qu0MOd1&`1B~nMdAFTIo;*(`TDh3k1YvB7f$ZZ zc01CQFjWt8)?{+g;uo==isA1|+(f$ayPl&l~eQ;JUEm0 z{r>gK#!eZRTa8|eQ48&UtAN_S^}RhiI$UCF0hm6arzBc1BNE=lr3lj_25GZ3$FgUa zJete8v7T@X+kA>TPXTuM9>sL^+R?R$gHP>yyp={|q(7mxovlWi|MsDC$+4)ji5p`i z|Czn2-qpCHi!B3wyu0u;b(NopyXAku9{_{R$3u$?b(8@+kwh+z?J9ew=*-!`|1b|P zhtl__SFM_(V?CPRTQ$?!M&ZYqIMA*$B2zT6eFcwT4G8kA^o7;Fw!r&Cjkz;^MQL3u zOV5h+JN;myH-5_^Mb;R0_H~+S=n`zIJ&{a~W39}_8~w%PGWkRE#{opgPOW97lML|+ zDt%Igr$j_VC9XJ5H_i$W)I3tCf-)BP7-TF_xRR@e8&+rVCk$@62xM}k9A26ie5 zPNE%KYoE-jXW=<^STZ2_!_>6}QoxfgUXw-Bf+~=y+D{{9ZMX&1Es}cjp77sR)s}s7 zG{H!XJhDIoTh8X$h1n@9wTvj|;HR$3%?pszPy5_&DH$k!AY!aHAU{Quvt>?*=vEDQo0;BwenSfWI$X$;EP?@XgcTRYFs2f0AD4`m^7CyrKOEEKPWfsKW#3ioxE= z!u5hIT;1Zc@1U{#mlD}>jq0+va$MiwIejw<+iAw5ho4djSpe7Q8CGK4;n?O%^rJ$# zGpD|h_nA2%nx)_xyo5#jRW$HR>6gQ*Ohz(_kY0Jg7?%roY>ESMRD8o;#!rx*j8mO${7p39D<+<%JX? zdMwnw_HyDJ1;xlR?Qt+vF4UNlcR44BjS)5fu==dbLeuWUs+O^ySmo&x-fFo4s|AUh zTXXO2a`qd}tu2HxSG2(aso19D%l*eErOg+bpMFSBv=z3hQXB7xpZ;Fa-%j*;Pzmn% z+c1Pr>q54Lh$Kx1ro~`IKDa?nJ=euca*m*0!mwD|pT*_*l$BoZ;z(HHiD&C%pe#tsy2XrM(ta{p(kG`5 zsUoxo;_Ih`Knk^>#w&@>J9#3W4uuPK6Stf zL9D1kf|uPNi2{NWz$nh%O#ju(SFeX!`1O)!A9Hwq4ITM{vdIcOIDJ{p3gO3wYp#qI z6;_H)Sa4tEm@DfrA~c5cS#=-sMV{`Q0aV@~A>@x^iKQPr^UKf|-KWP{h$_)XVD0}- zqUg(c0k$g_;0pu9bxV>*53kGDJf`y$4nllvZwkkLklVV*`Bg!H#X6uh0@Dmca~o6R z*YFBGI^ip6Rd#kYv_OLj()~V-Mh7(v@`ge8E;5fAxtm- zqMDrJ)wa{)yAIe!i1Q^(%uBk3mN$-+s9l3v7`>sl%Td0~*m z@s2%;WxRr2(EQuahQ;i<3y2H4I`vqSHO+*b%54p-b{Kajh&MYNfeOHF0%Ou* z9M@_BZ?lD=QuX8ehLyaw;y(;@$XOd+g)0SK&uvnzFM2D4=mr&rWs*#Ac@h0zF&2W7 zG=&(q;=4$XV%7}FvABI*+>0J(Bp_UJIr!j+QpME2iB;&kl@eG;PQZJU#Gyl~14CQ; z!OyP4C2-M!?z#LB*C&tcvERV`eB|C?jUU5`r|Xmb)4e}Tqg;*7wOf4z1|FVP-DUPL zV%8VC4TMl<=f(Uer-fZAFL}tnYaQ~xruAcu$`LnJOKXO@;;Xv-Tjf=dHwPcc-3~U# z^qk{w<%`q9CBC;n`ksqD!Y7YMFW<8v4WC3=j<>b6Y!DzRIqj1r)HHAMLCcbT~2@MEI-j3n1s@E}IyJEaE zVLGFz$$nV`PiXpMf#?P+!Ji8c3gfmuVVz!}+36=+o1RTP_PGAHSk$$KR{$0}w&P^N z;UcKRyyxIz5}DAmJ1pH5_vWGZz`5!}bY(rZ--B_(E+G(d)wQ{5f3U?O5;_Wz*BM&B%_?Pf0^b|d#`rAKTdMbfb%?ivv#%g+DY>-|$F zJ~m6Y@fghQXN z8Q#H$d#ZfgD!6;hZCU-i8QUQ*Rs~>gSnoNLwS;jI^{b*lY)Kls2pSeH1y$lh!aFvG;Ezw>K>AgJdjs9CfWDpaMCOSmW7QfZ=b*qCAaw}})<(mGo;Y&oFR6?>?yp?jb_}e;) zhk1)(k>=MI7Ann7hb*93GWneomkd;bA4ET4^0o8- zKFH?=zy@cucc!B8rPBQV+@;<5>4hvlschTv1MTn97+D8uP4ZqLgp-((@%ELIxp}XV zSH3jJj91xJoC+ic_jpNBe)~bU$I`K6Un>!stjJ^L0gAXvSEwLev8Vuf5)~(~>T9RL zPdJze_e>ZEp*^zU2}>RVgvQX5ZeFvelH4lXGom~BPg zGi`xcHsDs(!!KVnUJBJbA-}evV;0;S6d3l+jf4J&wILCWkzYQ{IpcrV@T}_gZ{(KQ z+SP(z^WdY!U`a&~d)A#CC@Li~Ri{T`9Jeb~qJpZ&o75(WD1fJl&&DO9oIM`|Sm3oU z43>+*+lp4Mi&K?Uo{z>8te~P}vM+QNkj{8KUspT8Og=Hd%ey;z!rODvku|fcxiLUH zLG9~~UE4)tYUL<0;(Db*A>dWrn=1K%02!rUY1I8GnwB)de@F703{B(uUTSY$sazjC zST*|#QuA>sUteaaF|c8z=TkB4@j0(;hW81manED(Pj&-+-5b|VQ^_Qm>mzLGXO5b^ zk8ywrKLB|}0UH-O5dO=C>&T(f$GCaAyj2^ZO*^uNoEbaBO{KOwCtjn$IB8SQ>kI4i z8}d^JE964wU)6?XJ&69vY4h}}P3LX*S)pZZ@l*_ z#GfzRKP7g#pF#Iw6D1vE`rk*u>$+P1M>t4rvuR^?9JjLirbuIY7o))=E@(dq8#?vk znLL7v)3Pq;K`4u8JQdU@j0ogX+uY&o+&2#idUTH#JN5NlT$P%xU&d;B<9)uRlx7VR(9sqg@h)rX8AI*?Q2%2mLPJ-JW*E^ zAuu&2W{uO$Qxe3eX$|LsQPw51T&5sVCT3Q&#a?rd{?3KSHk+6AmkbRI_G?=$hd&76 zsdSj7#(4GeMiV^n&^3CdgPD-0PCc6J z!}t*1@cOwkf%#HvtxiE#P!kpUuvir*HzF`H3y%irP6}_YATi^^mSMeF4eB}r(6RZ{ za2<-vbnyu&L%)FUdG)Hm3FuKi1pIn!%E83c_qrRZv(?k0zlWQmL$`i_Az6&mhe7MO zMq=dF#3b#PM#Jutpj?&AQ%vixHaAJ3K8y|q^W0=+4GP4^!PMQ}G`C=IY-!fg{`aka z^XxT?pus(Qg)Bv+h%)hhWqA~ zH5e3O#REfOZ=wt=Zu4XcbM`l>#QrKVw|ZjY0GOnG6_v8MI_B*qlHr@@NQhZm%~OlZ z`;QCI-!zw+ALn`%+Gt1zD;z4+loV}L4ffrm2jB5fKNJ^AzeV$ZruS-PAiIrV(upCJ z(gPCE1HB$oIdoB)U&hjjDcVk)f&Mms=I0cAKdENPuz4?Ju?(etFu9e9MMckrP48{2 z?f;2qz^(AOgo6(|?i!?nME*EeR+pLf6t|>kJ2%Q9=ytu4)b(GHYi(tZQ9d-3+Kryk zNYBRSd*V4}}OdG@pQ*vQj zL-CYEN3TqxvHqTYlAiLjEOD`~;-$$9;~1+8Dm03>iMnftr@`c)T_x7)X)SR(k-Uhk zPQqp1s3p0Yj$BKPjd7og;*v(B{f4oaKCQ$b9$dMv-`flkF}l$cF>69ko-kszv_Zx# zO#jGfd#pTFX+*u55S)iB7tOs7rz<*KnKd|AURy+Q_uB7j)Rlp84sgd#Gm3u8yrSiTib=U%< zy-u}?D(~}en=Z#@_Wgkx+`T1({-+}Kai0T9(|0lN@K``zx#zoQn6bwWBjzeNFvd#` z+iUiv7$a50(F?jRh>Qv1Ajn^HCSqG@jK+&YNCs7Rq?qG2zpGK z-Be-nT1Aovd*_Y^dA*4(iI?ASPoD-~_%|_`IOMTyK9qnuqlF~+_X5P@Qp9?+o7M2J z+U89`@PmvD5R*hCZTLZ=D7KEIeye&0Wn@csU+%Qs`O_#b*ahgH~T5OM3 zlI1ftU1IRG7u4)*%n1-A5%4!RPXkp^*nC5pkJI8?E z;r|}F(%ask(N&apJtn%0Q&W-h=*6w$1Z&q7gXkF5V zbCpe-%kZub-u+XHB~u}riX`5Z5SV3YytrNUmZzvQ7yh^kM469xLVc<@Uez8HtFRES zM$oCI?S3;gPb*ib^!7Rd<(~c9_b+iTvf44BGm_z*r>I@h9e%LA7ejtOCl)8fYq{l= z=O-?$#<@MxwB`?^G;RnoLkFNe-U2Pi2?cN%?e!^Y#{`$>XSblHe?va5HgtxG$(oBE zzodg|yn~=KFuEcQiiY3tlnn{cAcE3^9-vvlqp2IDn@k+n72JjT*Y*$0x1#wxjK*f= zKXUaaWi&j@V9cs)^}Q9{K4u*_x5KLDf4Fhqc2bYNHMSuaG`BQ%W#hkyzpnBM@cINl zTo+I_pn8r4PAJxuK1e$zEMg$rnbO)3JH=x4%TW|BFQ+NF&WO109|K};LNF) z%|WOjL;ME|??m6kl_YQy=|!3m7?EX{mb9ELK;eocMmyPgm&M8(#(8C8W;K3i7`UY= zurOLRqCSm=Rl5r9D^kC_viqbx8czQiAJCpWy8p<+U=H!7Bqrm_Y*O%MFxK}a?^iNd zaFF5={v_7UR)7c>_Uw^%7xP=8w01YxOHCmH&w8qFd-iFRc*hJER}LFt9dQ+jT7RRy zjTR@q+bQwhproJA@6@QJ{%PK=wHFyD?u0>|d*Qn3RjOOf3$z~9m)9ZktB#lOW>{wd z(1jwB17i|l!j8@emnUdkIqahG^=oWx_59 z4!WL|6eFCip&BeAH29auxBoKcdxX*>mMs?l<`76TZE3jdU}tr3YrjeK{7>g=!Cxhz zr%1uTwE~Co2M#F|%;1H{-qmsr%CHE^LS!M->7i;{fk>C7!b2ij_~y3Au%*K8aXj(? zuINXBBVp+c#WG^+=`dROy}eW1T4sz5cH3=_G{(JL)mCu&kHs5dFuC0GXJr+eZeG|! zS67ciuZ+ns3OS%ky2+*Pd^SH;arl0q+uO!dApDr3(Y@D_N!NUDM@QU!mj054n+p#XVMV|Iel6P%hh4g%*_zJly zsm-r$sr1^qL`NTrTkxuV8H>5M5RY5u$d?PHRmoT(LDv#T1O|1b1=5MZ4OYvY-l*+2 zsO015Pq-x&oDk^V#Kp{n8Gx)G?q8%@Zh>xk;VZHNzBol?o(syydHE8Bn6WIh1#%_P{8SWpEjr%{$UKu5v- zgTGEbK@p zp0HWeo^hqM=!qc0z&-9TPE?q^ChOh!?vQeK0WzyvL%gfDCE9mHO!G%j}b_o`gfZf{6=nB-f;sP$Yjx zvgPORCTb*6OLLk)JxFz+G1OA+_8Gmri_-S_d|=oI&qrzzR8^DP9RZSnFJo-_X4O~t z+5XxyD~%~GJM=_|Xofr8P}I4{X^}GMYL{^SAS=TuYEg zjoU--&dF5+YaFqDyU7oKzl5-~OJ5#2ip+N<;&d@LPzFLnVCs1p0bAXbSkXxAL8lJp zQAXp2kWYNIO2H|nSL%VwRa$!@@EM6MQ9|uQjqSO$d=JKV-g+NTiigZa5z%_@wfD(k zQdVQxO-;R4mcWYNM^@08^Nd+ht1QBPlE*;F__;rC24`Ydn`41ep>f}Em5}EEYS!bc zYoZ#2Em1q~@2!~Q20&Ja!u4>kK>zT+{!1K**`seJg^HxD9F8$uwiK*(1cFFQoX&em z$Qw_C0>lx?dK!&Y@)Hw+BJa&rHVy(fM7cUcEAe3}9K;z@9K7oGB4*L$X7>6o54;dn z|6)g=NQu?q6@+8;;`nde!hw<w3(<-d*>_%& z9Wc0B)vn2Y-Og~dQH@J<5;mO+dJwR%QISlXy^+ClbhU8;UaiggwtY zh`u|}JUHtIo9tD{6@#Y=t3k5bEDZ->13K8jt7p_3AKuj8C|j{~z=(Sme@!a4V*FYpQAyDjun~1MQM6Qp1SHd{61OTQz5{)Om6#AJ!}r((P1Veq<(wN<0eCX z;ZY^}=;->Uhi#L|K^~MZTyBkZ=mojBwNK81Ud1Dw@{2RV&jhb_;a1bfhZhz{7wr7x zwcP$RiN%PWA09V4isx&&<7L83Ole%PtCRUO%i5~AtNIwqfP#|<=EGm>kG)A$PR6VT z^wU8nx=B-n{!?!67hO2>-8;3TGiNIoP52tgM_p1uHfhINHr&Bt!<+Y7_4oE7YnE1< z7MKBfeXY0GoqrOSv2%s7EvjxP(y(OYYE_8)dX}B7a-P~1U7zpa)SLaMr6(V< zY*G8||Cf1 z#0@$eCNQq;4Fjk4e2wQ+^`g=l=uBladf~?a(MFv?+UQh6t7TAhpX}ld%YUs%ynmQp z`%A8KwbY~ACOnN~(xh(m3F)6v9Mv+MckxF>K}>tIzDw~>smkl>f!{uL*fg+5%#%nz0fnAasF5QW*6c1WPHH*#8+raJFO`ZB-xM>2`lmXo zda$3pMIOo`kAx@X=*ut+*hNL48cASSCw|**E=d)$XX?G8;CpS@ChHXrcbRYO;rQ)F zN6z`^xx}`&DbuLK)r6ZAROF#}mWsN0Kcv8eU#}Mv50;cN%0DAR@qKS#7Q3ov$z))c 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

    5F^t=Y}cW0yD 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

    >lvsl_vIQuKFeEd`GK+g-3Q^x5E! zj>h8P>IgW|(={-(4nT5k6QXc7ESMEl*ti6nW$_MRHA*KoE`Lz(y*tZoZYI6r!8KFeKYtzg!E>4)^v z(?1MTnI`;D{Y)|(f|pSNQ=ZW$WiIne&B)3~&B>eHov`DvdKyhI!=$ZEucwzK4S^Hq z(>f@suyP3c1e@oH9~?vkbasD-8wUhOx#Vp12jgP#viI1(2S8$J2)h9m(DI3AP8Cj@ z_J}}|+?jScXrtqHd?H0(`#Fu9Hd)0sndPgV`uqg%X?5pq0&{L)1}*>i5GAZMqIixO zh|posnV@G2!3#4`&+U;=C!;dEpL+3&!!p1psdwV#(kC)zHKK@et@4Vvx(2b)c{pXh zSncS=&OTtDP5L5Xn8_T~=d}^9uq^C{fewF6%XOxf1cWZPZ6^)rgRj7++6U`S-4@y2 z#lB51b0|p%lG5VjYqVbw zEMxOUhdN{G7Io7Lrz>%V9n7nAb5TscQG1{63M(ywHSjXOt^KW83aCTr>_(M$M z^$M64DV?vr3r5lXhj_-i)f6qhU^~3)mpouCv|Q$~0@L-Ob=_~1(} znpgA+%!$tt2XlUBh*r(+gg+KhInKy!G=HH?EP%Gn?HJ)gIL_B040ME)VV*u#ZZ>ZBs$y zRcuY_~$vHLh<~sNynPcYh0n`@e9|_Y4JBSW$a5HH~s#3B~m|=I)}H? z$84y%$15~4Q(gBz+o*|YEjR$%_J=CMybFaFEBOCg1Fz8W`*^fTiQQ2+>5*#*Z&2Ek>BJ=6G&8F5RJ$`%UH72K;2>c&*3fm!m-9onw)Zey-5% zb6~T1NGPU`_qK2qwy*-mXzq&5)-ASn<;n-2^xK{1;57QuIHpHc!UqRi&bK?{Wl=-Y zYxj(O!dp+p66z+0#Xd(jC-m7>R-VR;1=!8a|2O{y@X8%2-i8Q-ute&#)ZHnchv`Ns zNR322V8L!a2Jq<{%j}0h01o`X%1TapcGZon{}rqrNp*WlwU!nqnlg0LVkEk01VG%% zRPQEW@ZVlh(p^zLyS@HvaD7^~bA2!lN3XUd9;)sxukup1!U+!1m@iU}om!=Sv z=u~MiE`2BshPEumq1MOLbBL|JxTf_C&FZ%K#`G}H>KYi2K)DmR3$ZTunDA9bxH$td zPt)w`y&S&fHZ%F{KE$x3rPaaxJQI*i&L()#QEqE}934B=b#EU+C_bs!%$(erW!p;` z08@y;00J})MflJljXWdhq8Rk8FUN-~<($_bUHsONH^u!0%~g(V|5rjUrq?%PcsFCY zjtS;>T6a5E2NHHw&EZ&L^#n`HPk<+?%w}BZm%e_1F+{n-ElWL*^8o88RXcrP-j2?u zSn&LBF*@`H-p8Xe%kghDke41OEV#+! zMxtP94LYjtAa>&}-nGje_s^{z{3T8WsTT9;{KQ0<=18YzKF3I-Y_Izsf9e}Q2cHNY zIuu~8nMkff8NWq&gaB3asBgF&@A z7mTKZZVP^-tsPZf`9{x(wYo*WVBW1RDej8r@|5#m+(*UXfH?gxNp3Yy5w_FB|4VA! zb4U(sKqm{Et^8EyI3*|E>*@Mh-JI(n-`;{CfPNQ-wF{eDGOp4at?*bG_#C=@sUBBT z6jyjm{iRy%yF*T)|3Oe^(7;KnB24auw}?uwRx_|!w2W3dQ$R_iCC7oJ1#CTf| z$lB+I=3jw%^|Fg8ONawLJlaas266|}CFu+?K|Rycm= zGoI?5_QmAeD`=>B_NRyL{r~F)$RaGOc&|;AtSYZoo*0q;xVBdA6Ifrig3xWpj5$@m#|y)!*90X~Z^`ZkaWuFYGt+Z7aT_ zfBw4^_mB^cEP8QN?Y$+2nJAqD^$txl>DXsHsy)4_rgoJ;t-M~mR~4z z!WSHmRH_A^P&9eQx?thFZ;H^s-Lo$oyTO5aKJ9&|6Eaj#A7wzeGXG8IZBNkN0goj> z#@m7OFy-I7k>O9Nhc$J9p65k9i|Qe(D;=9&FLYqQNT8nCe|2!46pR`AXh9;Ns?DwF zWrdLb<5q-D%T;3_4jIWUM3_ub?{VxI-X$UgUI69K(sy75G@_-+T(()JLlB3oh?9$|Dw_AmLvvv=ug1b}JzmW)c z2mjx+oW_IufsVc}t(bj~A-H;?9~VAP0=i1ZnV;8hj`?3dYh^z+&VN6d;a<@nnSoYD zPi0mR%s4fYT>OOHwJs%dJjXhhDI2CjUW=lRLdOClT#!ApuTl3HpnrX7sTs>!lvm6S zEWx0&AY+1-n-g@tg?I`1Kp6Y8(Ptm)i%D|QWQX?cG}rvuP;FnBcBk| zoX8+^@B!W9nb$@2j}u)^F`X;FZX?M3E;_pJ6Ld1Ye)0ufiNuPZQ3I+?g9shl=!AjN z5%=Mz8uj_J8|{|N-HmjkLK8NP-;T!Z<>DX}#KN5Lez1CBv^f99I~R~(fMY$(KF^#8 zcAlhaH>v#+*poMq8pCF(_iEH=zTfTNp6pXA^709rA zll%)7`@*h}veC$OfxZE)1+CY8vid&vg0ASeh|}Tks?`mW*YrL7A}PfzNFzmcp|2N* zX%uT#%kRy}IXhfFg}Q5~1cp92Ry=wdkh5}Kj0!K#380%il}`Z*_7^aU147tWNB+ zYred6Oj{}{DlMesCiV^)Q6l|)?%uo@%slHahD;+xc32NtUlTCrmnba=8siC2&8Zp- zHpgrTjQw+(~Fg$|A($T4Yh7?E@f@zx^HF+sK&5xyn zM^>cdnLp9>0;zl>9PE)!A$cs?G8H~DLo3xYn3|yVUh)%7VTrzcDb%a@TLjiv8!KL+ z$aw~%HuE*k5fq%v5dB<(uGy&lyU2=)6I=*{jhpsfdDs1rZ~T2)r^2p_Uv^mC*Sien z)`DlY!c0%(B~)3g7=n*pn(;i}{ql4FeTr2s%-;R9qAsG3+-C>fW*0XDoGc;lM@^3P zd781lcfziIr~WnR$jgIxJ;OGUH)ILd`mOrMj7H==yT>$Puw*+G4OvW{4k0qa>Y1V| z475mry+&Pio!PVc4AwuZ)_%Zc0j>&D0*CukM&l16Qoio8Z?r$;*t4~ywYxgiVZpnf3|Q$?3vxYit;KO3Nj)5k`5X#V zT>V$J`BC%Y|7fZF*c#oLDj1R*s4M~6>tBBrPT_HY6Lp^Q=zgb8t5bGQf#!(F3m1*j za(213f4#>6XhP%SUV-&{GTWHze!+#Em(; zzRI;Jeedg4Z<))v4f`E+`~!P3sk!>BB-v-y52Q*Kqvlwu>u6;aEzfIP0?_wQe=R5sw-;LwbFXCLT(op=r$BzDjn>S(-H9;mPr#X^ z8!c#vWC6Z$`OhNf4ZxzyvHMqJn-rEc!H1F|a}Mg#@Yro19M4|i>vqIC|4ncpLXa-I z-AlzAP;)#}wdcQcyCOkv6n+nL~EUuX#aDMwDx~Y*7-jPd6D4y!4lL96>)g{;wYm8 z;d<_PHvN_dt`8$ZekIQMZbIk!0*Zw1bPfZ2B82#nd%t%5oIFp{8xJ)GLK49<5&XK1 z=qa+?D-*onx1HyI&iSq+`PI5}b5Qq1a54wh8SzIwVbw`g7_g6_$6c#N#BEWLMBlSM z{*N&}Uu1vq3o+pXi+v98ED$2_hF;{d92h1<+_ukDuZ)#klxTtfi~6P|6VOrA-M}#_ z&!3UCJK&(&iQ;EZ?#lLp)lg{YHY1_mgABzDmW4Ek2eY9iwxfF)3pue7a60ztdM`!da*NQThPpuyD@PCpjYf7kJ5 zHmnJQwpjx=dJFs5`epkUtq?Pt-9J&kew4fdWWKPhha+nNQWms$jD860nn{0P#BLgY zY1}2w|2)yZ{yJ8L+F04#+|{VpXADl(enk*@-GZr!kIS0)vi4`_9Q=+tmyfSSO}p`q zL;Y(D@9Ea7^-@BP4DTbiipWt~Zz;Per(FXJl2W*yp2~e)t}b=#`Vw7ii_P?lk2JQ$ z_gmK&1PkY~zn_YT&uJZf|AiuLIb~!(4s~}iT{2}K|K0a&6zSC;3cP`+oK{q||L|fv zeVk+NO2qt<@u{OR2pr3hGBNAKG|ME6W2!y~b0ed2z`peDr`{sLJMxyerPgvX4*|;j zRakQ)dzr0q=vvC`v+Y!>3@I-#f)93?!D?4Oe>QSTaOSEq6=hfIvb_rX%l8u=VL^hn zIBcrAdTW5$b{TX0iU2e18!Mf4@u>*Al&JT4dohLeh?7AY!|jVp;UM*NdB~?yee1J+ z7BiO*t@8zwwtw|p%!efmP)DnbNkbvX0wHS1XwA%LxPGWS;~-ey_cm#8L`#X!#geH3 zG#ilG9>IU(_p#7eMM<3DSqQR&(27+mpf&!h(geK*;+J8Wd31+###Hc&!)V-uhG*a& zFtgTB=`In|``Bc&xU)?Web) zRl)ZwUVTJ{v2WC)vg)~RA)AC@b&ArOhNeXC)T;nTEIx31-CX(XeGv;Bs$P{Rf?JUg z2j;s;TM30&g+REluZ6=MAppKGGhGF<)eKgMy zYXY53$?f4=v<_})x8GDWPg&^4JiClnqu*_WahLWfjwqh?bE~|ktnIq1(aTA9U4=;=j_2Ve`cYaNeG{ho`;@ixqLwl>BWJo`2;U_(O^u3c^QMgoO5~?s%B&K{&MOc(W55P6V(J_HeVwFNaxM2TTH;+^bvhf zB=T5;%zcuu#cj=hkCQXm?fbxLmac(vw&7y|6tdB-s#On3JB%mY&{X|L_!zofU^2Jw zp&rL+rU(|3{6WLv+}ddzn1J@Jm7xb0b+Ph!f-q`5oWC7O3UH)%E{#jB4fZBgSs+}Y z7`p8Ii`kS}^|TgIT2cG}E#foUFF8C>xQR>^KG*Z~rO`7a1^yB4t#h{X zul2~iCGtKvIleiJ-piLMzPb`lpjqj4_9xj08sQ-+P=|88AXf}(aXXuOt0Ma4 zMW_mKVW5O{^n09qC3+%7NAH_4=pfjg$jI_iYS3NdnP>%f5=$XC;lk-V`$UKVpMumM z{rW4e0H+3{G`bj;ZnfwaXC}PVv9$rGwoaLc`b)jKdVk-tzihzrgt1asG6oY`Og^>| zAxu+6rK1-U&tbd}41JG^m=7*lty06O^>KSj9qV*!d5vS0 z)}}Qh6qPfeUZ-mj!Ed1SHts^ncfMifb;eF?()`(LD_!u2ew5bB!gJ^gzKz+&1^DS> z4CW@Q!!Ab%LvN*(FGO#j19@QsBi^XQ>GxianZ_coH>hKgwO~~vwmN8aQX%-1_VTOx z%PgzQ%tJ2Az5UyE6`HO+s!E0=r>)SeED;z@rP#MYU+qI%#dnjfADyCyY%z}W%8$_# zJVFQ@yZX_fV9n@V$Jf z!?jQV^P~Up2Tg;*Lj&jk^%>JbaquR9$&PG7)#LX{p6DIW7fy)b)T>5vt6&SbGUeok zf96;v%Ryplt6y=vkzCxaWs_p5txFD7(9vu1NUB2Zny8YIt>w{=e!eZ`&h*}t;2*l( zmYvL3KTz|zepg*X?_*&V6N;GIf z2cwlAVD$QU0#M)=XV#Y2vsqea->X#BGK7FS7UlchJ#!F zK!rr1d12VtzXUw9np72-pwoV@bSL@ebW-K4oBp1Xo+`RDG2hIFU8}~>+|l>!!xMeY zJuUkUi>W@D5|!vfL@wd~pxL!9GXy}-pOqdw)Xa5I#h`cSlLXI6AxU;j^aFF6(Z^n({Dkf_i_=Re;_p%;U^_t@5+OVMXVpH=3i&&sXCVY*9FuAhg^V$K-P%JPz z>NsnAp-|y&GVlh<R*yvL zAn>(i4JzqMEjM%wW4TDA71Q`Y@)5o{sck@nQYLpvGm&jf%#; z6QIO)o@0F^o0XQSEwaGe;})@NA(JZR`2@{@6%gjG^nG2Sh4 z#jQ_32@8K;hOTlBUcTJ24;6^^J}*3;IHo+%5(n`3VqkeF_{&Hqc8)`o*esC^8cN@J%u0lkIa(uxepxt{*JabJyZbAGJEd>!(s5(vRvKOh&XYXLgTT^ zHee!$%)KbweCmnkfwOD>F`G1qpV*TRa7DPG|1JFfF~m8gA4QDp+;u`asR9}IWvm-r z$ehA|(RnnmAOVc%M~9D2EKv4345XM#`-N!BAxES8OB!iamS0mRLT$jf6oYnd7K4GF zF7x6<>6esjTqO^^Jx%d>15^8+UjDv%BS6e{$z~Wnr^y8Bm%toVh&}8BRgDP)+g(77 zVarrycbGIdFA51HYWj0$VdwQjV5T_Ksyo6O@p>&tQoHdLMr@L#UsHc-CBUg_9D0d; zEBKbQ!<5UE8t1LYkA;=$4C7hrLIijUqJUc1=zrwg@z=`X>F7|^_;JhOpO-aM(!qFz z9p}MjHe2oLzZ2miT?wd(~OH$e{tb(lHpl5&c1nNsn5 z5$tH(!Rtzd3~);Knpp*lEjv)H{GR|&xUze8HB`m51N7zy+;!du&G-i2Ue8t6xvk9a zzj?oBk)L_fVRQQUMTy|uyD3R>Y3n%>Jip;;&iMR!gxo_>+I;Rdn5p85IIF?D`s$5u z#g}ptkY9;rQiW8A0Ly>HRlLz9LfgD*nBmH#G{t&{{TU}+rvUM`7M-#Ztd~`h++zKX z+cY09>k77!ov?y~7s{$Bf15{X8sVlQZ2iIU=VWZxvu6!PMYSBRslLY>B`OE2?fF=L zb0f6v;LA$QeW@2VY>wv9JwmeLli)ZEfBMHJm z=~AdsDP3NqDh}Ptw=kLpyDc^kw?i;j_nOe)JMpoah^$26H^n9h0sCg3f9P+%(16=< zDIojK#t82p-iE~AZCll@lGM|-bub`eFBXh?J z$n=1>9j2D2xy0e}oSCJYwd)BbM46HZDN#U85MHfx|bs`SItSeaXfIe!G129!L8L^}xJD+sHK`QL|pUXL<@& zlrSmCWyjkgD=o{wLXdDIU)1jK%#4h1rzVY@AhH^IJ_p9(Pd4HewuKp9D%56+d-CEv zHKmDkJma1F6le(>FnHb-E)lrziT9z#&_i23TJ8pExvzhy*`7yri^$%RE@ z$4k58uOpQp;%7VtwDm$?^ead!JhK=Ub~5bTftv&#Z! zijqigDy5ojji;X#Qxs@lh?x<-jKgM;f5+ag^~xBo@`0W`p9rku`nO06srAebDth$V zON#!DjktfDGreE{chhs6O3}gGmcS780h1sY$f6GlnLIcdoHel;Z{|+b<}e-@Sq(>3{TY!Uso=GkOt5A5nJB1PSYL+`aq=5n z19i4L$urT0)1ZG_;(1FgNuWiOmPX_%hj}~rnpb<&`2GY%<&j(iuQypNTybgZ8k|oF zipdTBjMrgw+)}Qdl4bISbv(Xqj3z0tTNlsKC)xx@w|znDa=yyG5ye(;a>?_ zSzG;WmA@=&>p-mWnJ>sxt-I()-bxelLKxG;(#mxoWH99{U~j@++<5AU;pDu!K1zyw zt(~PHLg&a{G$kmEk83_NilULHhoUm}z9kG$buq;wy}a(Y$JkXXNPkbKE`+Zw>!irD z2G)GJ#?sxn%uP|pZOX9JBI$Ep1c&|#pYk35*n0hVW^Zc6#o0l4n>7||2y@^#PrV`x zOm_Orhr4&eP~iw}E8Zzl7sm7w}O@wPfHKJfN?**0O5@4fuGtIFM-FZ%%wJyf3UlCzbl(h%{9T-!XYXQj!=Nl?z=km>{um-|#cb;vh(>`9uSt0)N6FH^~3j3())cw1WOha*{e0MDn=~Te%V638`47rMV6FHg$XQ(m6X=JHM;PtIFy27;9hJ zGpl0&pM!fax7FW;O4t}3BfuUl8T#lpsar}BRSTp8aOBZF@aCLFFtm)ol}|oIliQdW zv*8r1xuQ*XM7AiP)VerA#8x~?qz|LVIux}i@!4r4RPX!QIr@=4z+RPy4Mj4D@?BRe zYDA+$xm8_YYa+bxfrbx-#R&2dqHLgAylCf+ZAErNA1iZ!q^B-anrQv{eqb|#<*sFbM z=OKh?7T>O~6j|1ktLGT^WHu%T*UBH_SOT;MQ+4me#i1fpnkr zi;`LePpbIuQ_R}^QUKBgcjynz-d~rY*&210i6viQbRBB1OcOFC0lg?RIF-W82_r34 z&NBqEvY!*kv69?0w{Zf>S3i%+Z1q?*u2>7AIQl3K!cf~M10JUo&8$nfGR)u1U)7C# zPu%YNKomTt{VGzwNB20ELf$Qp!}Rr)n-*nm^-Pd_nqjpy?6DWqQC|LLzqmsS+`luI z>(hn33B55>g`Gdu8wU|Ph zAY0JJ!LIW+e1(pky*kY><(2vxM&_w&O4z+e31oTg(ghM4ahPo4&umr0IM&9=8m$!f zQcFJ1W5&i}W0?ddff%6KpSke5oS#ZI5$*ZgJHtwqxp2jA^hkA=xUc~=>`>@!U(hXE zJ-xz|*zRp(T(RyZ&{^2A)BA=?)S2+^ZhpA}9y5^vI&@q=$qv9xT0kcL0KYPx>Rjg( z)7w5qb>(cLZpH8M5U4t@Z3#C^c)%(Y3O_3;V_*D(7L3jzV8el7^PS*5<@(Q`3~Gk) z7V|F`3PzJWw~Q(}7nbJ2m*!5O$ul*c-cFPggEMA78yJR?86y*=)!U>a;6F0apQVy4 zF733Iwd@b>Ly-BTA565;^peuPTpZ))S&+`BRh4m_8$scI_uqr4U+<6gK)gJF%RIM2 zwHBLvEnsB{ZW(@!vK2d)cw9w9GB&{fiT4PvL3(A+y03ICAug*E7qZU^-#<1EI6ijX2(4OP z)TA?e2bFxPiZ^%NPRpP>m%5Ps9Pekf2128M)Tv|{FPB30EVuA)3aB23yeWp)RDmq6 zn$lF_$&aAzFD2~Y@7neVNIr$_OTGDD6hEfImwThK#SH)8RyiPre3f#fg+=oVJ`Ap$ z*_2)i9d}Ss7X)E79~bhdA8yNa&AH;qRC#d>$R6K5`BSY(Jo6pS_UdZxnerwp!SPcC z*;lPNJO#KChcGos23y&ZeiDbbl-s;g$HFoC%*bP$K!O+OuTCLV-&pOEUj+RQ6Y~l& z^)rHJd^!j~yG` z&cmC&@CNSi2kzgbysc$tXLT{B`6K%tLR2sIZ~pC*hB(n84odLWBN~hXe-SRHWf1PxUeO%QPqF_V7>IayPuF zwPXilmgUjL&R2!VCLiI+;vH4=KG!^BzT#Jxr?o}Eg@1tFe0X68!892A(3-LMR1+J{ z)#k7zPCP{aNE%1g*ny3u05UZ)C#s6E`{TY=b)2j(PA-IvZeI2G6-qkjh{xnP+KEAq zT>qBPH0=}9VFH2VMh4r>z4O&HtUqxPlg8}wehonT=~nql%E+FN@ojwqL3Px`wm z{(S!tp*MDk2Yq^kew3sO{c9io(J%fV=FN{3XD4K!(2unQs;|fSE&36fMKz^z;fTln zbu_cj9P0>n+YCynKh(|SsVCxo!|c!bJ|paS9uy*+tS?oHmi{DMh(9^B1(P|Yw|i0u zEVia7_{8J?&~%kiado|V@WI{P-L<%tV#P~wcXxNE3|ibNQYZ}W?oiyNxVyXGdGA`^ z-}CDvJ3Bkc^CaiJWYppu5&uNC8*5Pc*woa6m>KZ1iKzAyZvfvb8l| z9cvyN`*lV$Nr&vsTg!sGdrOVMbik5L&-W!uPoG9Uel8LMt=pJ~jn$%)`~)yp>-RvF zjRdIl-%aF_Sb|F~7r?~f&5(`exHp7{t-vR-K*X5@;PK)nKRM4t6ib5nb`KuX*~Lfk zvU&S+$9GQ>lDO+7E7;2u{!LA(<2)P$UT9CWfSvh?H07)3k@9YEL_0DS-w#(f;t2El zjN3I5*)R3*rYC%q^+z9eF6YZbm#cv{&;9VNU3UY-kOkZPU7N3_oVjt)^zAcZUlz2LmJS{MND*4C3U2am^_?2BJH>wPJ{XWty_aHHxG z&>7^_=PoII(r#^4nvaNk?ME+hdK*B8_)n1Hk4S&}fVFe-V^ZWZ_owW@p zmKpRFmI0^tU-Dbl=A6|$Z!mt6gTTO;m>Q5ELTe+F;w4Iq5w3!dQ09EGhjF3~S%QNV z+o4WMB+Z0R63n|w>e7fznV>tVnQD?PSB^sITUT$NN23W?Tl|*A1f&Ad7JcvRzS(s9 zCkPjXiL(SZleKV{p4xI&f^1uU%Tm-uEm^B^cm8g7eIFn&^$$UqGWW#TJb-ZT373Vv zBEPnJ#yLxpO0rX9^)gg%Mc8$u1$i$GoB3oy*y;lwG!x$V1!ygmf2WjE5DMN$VF{@JhEdz{lpRSw0JN)e|4 zS|8S(3sz5r&iB&XPNa$8!*Ep0+#Noc(Hj{|T|NTRBcK*tRULU+|6O}nKKCqjtRf7* zt;Au>K-(`JYr|Y(A1gn_PUyNJzEIR-O-Tse>`LJ85JH3>zid5TH_5thvJd)d+APEw z!~n$?Ox_*e@vxwHh$$U~Io6Od^T&Q8aA#pFJMbqbAI@oZY?JVZ2c&)XgQ>=KVe#1O z?qzYym+?GrgsSY>M#NpeUY>m_to0x1x1|E=NC@rqHqXfB0%wGI4ZXL5MZ@W>nAo2F zK#c^!*d9kd2cf#P;b2Ns_~D+P#+3_v)i7x|6tmI%bL>frZpJ`vbV(-i>pvW`Y499< z_)<6L*XWuufay=9aLK@0ZjM0$Q(|6Xv=P@)EdwpcWJ)g0wC^hj&2go|j-i+#DIm;95HYAcq6j8 zGs9QoSU_(xP5r^iHwO`y-2bCZh2(-wVMNKMoEPF@h=EvoN8PRXfdMj7;!?4XgU4Uu z$a)+hMedO3vh`nAX$P84Hz`MPv3|Mf;|87S6M%)_NRJ6FysU-CmC4Qsg$<;5G>g#i zJj+zv7+`VOHnqT%i6;juj4AeK&;=uv;n!o^7F`|dxdj`oT;1N0SEST~)Tz>v zmc1UQVcbT?v=IVgr9b6oVoRFPVTH8Bmh?!Z+-h1Omvd%hO~-5w3nC0?jotm}(L>70 z-Kz;lhVs$=z7JG+qgyX&29o}fcFrJFY_xhK5Gs$5<<3yRJ$=o^Wx(8GQnXWrrj6Ix z%c4+;ui5f7@05nP=r)Oheg-wUne+A>_2b>g$)f5h=Sk1@n)zw~FHJZ;V4RVaD@{`- zhK8Z|s#vV+$D%>@iKnU-zQ9z7dGR-Ude<)J{DDI*MVR7f;X%3!xbOcR-SUkH`RL6k z!z8<@c>vtr09Q!=Olo|bUof{02OkrUWxZ_wdUo_Iq^0ITmWqT~%L^7~Y;y$!Td^?6ig>WwV8LN`2_ zOXrqJ1vJyZB)1gw4{LN|;oZ8;(BvBI63o)+$ zSd9V}n_%LT`;xHhcZRtXCmACWDxe|ga16pHtbIG+_0t3c#& zN``mf5!MQ+p2Whir?Z0w>Uq-F;Gj6r1sUW7ZVSH;eY}zPHTq^Hr{@{;-!`;O2L{7H z&WRoOSwGA^nS8VAW7g97CKG*1t1G6jRXV#M!dx0E{ed?wi^QsjY#85;M8rL6<1=JB z+jFnAz~l2lXWX+5DFtG!a&J}Db(pDiyF1XdFqB*8RtclPsy|PLm9VWTFl+Mf6h%y| z-DvO8&)=6FX$E0Ct&C}LHM`FFaHe*fOP`3v?%zFWi6LDL5sL<`h~uOu!F#rwHsb@? z)YU^t2>_x10Hfm4zCfmq$zOJ(ugla~@~7J;Y}?;I77fF#?=(f&*Y$f(!B1LUeT1yF zmO6AOv*MfRgT8+sg#EUZMI(y(?eMt{|{ zu5t2tH822@lDkRBt%Mqr?N@}ao?Y(>9Ia7F>xx5YwE%&F&t1DQ-Wtqr8^8M8_59wk z1Ea%_9v{$%g>mYnMzz?JT35nOc{M^gA?8(R=UxWN`tESwMnFA2u}ncmVq|A_spWOS z!;?yij?IZbz}gldPfO%iLTM7ujZA4oAWYXCfsLS3-IGrBrVj~;T{@h8YNoGoWt*(p+)oi&tu})>Lv{3l3D{Z;Ama*_qnqFBmJGOI+> zszkG~YgyWVopI~qno1|p{k+!CQI(AQVqsXd3_*ySVTfA90WyFeu-Wy%uj(fA$j{$| z7Z9G*pe|m!+c@2gAa4_!BK!6TautM6M(3e4m~@{??v1?u!TeF$6^tgGJ@ZR>8_jGF z*_-D$w!d}2$L0rE6;#dH%WV6Y1-%H;Ft6&wAq$}vDi z4b*t(h%;*0?sbOQJv|JCZLmRY(D~qg=UPA|8#l?I0$@W6bkYu+6oyb_6V_eX%u9It zzX16D{lKPueVpth-tncw5;}Ojg*JHK9~EBihyS+{@EUp5Y3OITQ6~pPt3Ax}0|i&q z{B>^MqhJ4_?0@<*TCc59r_b;$QrXnroHy~NriZfm+>}s_DE&%T`}oJN7qGP1q^@NR z%_)vv4}mGDxB$YHJ73UeSJg`UGyna3o-5Wt1Z&9O2%A>Oq9yU-LON^!bb>G>#A=-QBAZ`K3 z92dVuA8@`#kVT|?njPbrc6t0@7{1{1o!@53=;i969ec9t<0$|i1~6H0tKNwNo~`lR zfX)3FXe#JTRdn-gP#drmd$+Fmwt)4CoR~!tawSJK)nV9uy91U-^uEtsA*4nD`ZzXU zve|fSN&XXw1-bJCvMC74({aq`eh>vg6D40ybn$|UgRdSIm`d{qll)l{Zp|Epo@zG+ zF1duxXqgYtZO^C5TJ=lS)~KnYUB9?y|A~QUnu~`ACRV1pO|%fa&Bip>zLbf|3GwO~ zHF7&qMG$xA3kw`V##;~$m+5|qj{P+wjrgA(s*tcte142`ebTf2aA09(@F|J4to`gdw$l8j5>k)@;ZL(stxz{M ztX)EVM*dmvQ47O-LXNQS-LTHHwYgdSY_@+YOBltnB3-xq^vU|f;L79i85WTM6I#BQ zvTZdjSDZ309=G7l;lRF>Le`k*N5W_%f(>y=7!nUw9&k1&d26F9r>+1d)}k;tybU?M zi#KLDt4=G!aK9!K%F^+4=u|vGI)Lg`#BR^-F&N1^m#QCHBF1snc5JXMaxdf)|=w79g<}9JiU%^deEyiNoZw zbVSa{fNi8RA2Q$Ae^H!;9tJ3Vhvc(Vz7-Iyo#j(6|gXumyLH zEgsK2G&broH}ICM{Vc~(Du3J4t8Mp>`6$6&Y+`45e$%d9L z&Hc2i0kJ2R%saDCclhWF?`EGTt}!5_^fpPFZ-9)h;(b@loJc3RJwv3WgBA!M)nfA2H)2Z`VVf<)S40A$y*y-tV1@ zR|HhOQuOgv2qd(l)`E`{_?@Ia*~Z${W4n>M$um=!|3W53u6RoB&*fg90ha?^uWE;! zCB`OxOfB}5{C`sW>U_VFEJdm-XDjVJ-^oMRV_En@kpJd~IHlqwl0oYTv8vpiU)tc} z8N6!}bcv;7EifeJeqoLR_Cz}~f@^rX2z>Mk_q!*Gx#Q+4A`ucE9RQTGh<p|xt2~A2((0V|ds`r1sv;IciNgF59wbVp$(@A{6BgSRkVX*3^sXO* z4!kd^SpGcz!|#HgRXiYT_kHQ%ri!{8)*|~o=$aLxr||M1S;E7%FR&GS)KsY_W$uiL zJgab}qy*cR(D#`8mvrS?QeN>iOLFtYiFl$Csga>g)WD!@>sA`7u^oS^jZ;vAda8S# z7eQeSwi%Ru{U@>z!M$hz!c;eQZ%C3TBTztqggs;FIDsP3fF1~+)MHNZJge6?@akzn zzEB`}e;(b=3KMhvCHUZKpWNH^aMwpjX;yBJkU}oO;!(UpjYzO}q}rzeP5x+&)Et^k zJ|f#89E}CWiD*2oJcuueRP*&*NUt|5;8cJDy7?rho`I0nZ*k>HR69d=5dUM>)hV-3 zB)SYbc7BA&1yl2NaF0*_5%WCwSO@o0%IjT&+9j1=pfrh9VybvJx{Y@(`lLHRUUaDh zbL(YMp4xGlfS8#!;LWEWMHXZFI0gL6?8*2FXDG&N_f;;t*$E3Fo~)f*57Vt-hIsmz zAFRrNOQ{aziApM#U_|Y!O=OO!YK~=AiQ=&?O@S}w`1=R5zE(4wVd>LpMz-SXvv|E| z#|#lyvD`jGhNLVIXXl=m`a1jaZw{p9;Y}uul!%v$4Q4%UGZ^x)SX}g6lYI-`3;#Tf zL#LfGlSsFed?8ilb}oTSxx@(ki#8X-kdf!Nq0B0!kv!R@Q~8TdhTC_&6kF{VW>PG~ zUJ=N?9PxXO#yg=Cl|=g^-2Zm*pG5vxsh?pennHsDu*<8|E?|^E%_?=;uh~SnRmLl;Y6@5X|j@W~QmhZ6>? z-b2HZ7y$uVmCeoEi`{*Z$fTk1p%mQ>CyP=iWP|X8|5*^vUE|pA0%$9N>;j{rQ;}x$ zi?{HDME2s@Eh9S&M8+%hz&(GjeT2NTBVnBrH~29x_WMrjw2-&qzfxX(@np(&K|b#j zB%QCn15r2jl3&{-bbjiBipNi>kl|M*YFYKX`miBuHV{d?4k;FISh#6m6=yenqG~XU z8)WME{z3*KWKgUysjw4)2QeLn;Rm5^F>lZ@zUsLkT}U)B6g> zt08^tnSRiwq)>u86tu;(gkW_@g#1w^J9gZoi}mulL}J)K7TKK=2H27`We5jn7REiO z?b_%AF6D%8;>Zs@IhWX|QDFwIu*R};1ch|+^-e`9#^TTByp4Pj!SoOlNHn@-`K zJ{1ng3OMaj1RUe9$LQsTvMik&>%a%RF9ty2=lWFqzA2^X{vvj*+J4!9kHxfX(LO5v zVYeps-f#N*vXwl5l%ZgLXtru?a3kP&G;s!0H!VRTJP?5csbK&utBnY;B~AP$X%MtH z_@L|6O2NFUy7u|4nvrdtHuyTO5G5rHYGQ+8iPSOTa87&BYXSMxsYzjnOw<|1L=;$4 z!i$4~mww^hRZ>+KzUq#be3W+eMH|R`aSrc}7r5e<^}mu(RL4yB`WtP;LqV`i-)H}Z zxMLldSRI&5(|S+VpG|1SEXfqzWJ#i)hklc9Fz&ae{O_4F;`m)dkVHAmw>N`|V#EyZ z@2MswB4X0hf_YzDF_I5z{iVr58(E6@pqBEYVgw==`du4FB8GO5vz1!9f6^WG&C%r-5(!mK;qaPFAX1FbD;@XE;RLkLF)NJuJnWI0qIy z=+*g<^gSTNsw0g{hDLl4mf{y=s4vMEB|Hi;SggHkzW0}pvoz=HF=~;Vg$MuFp00O) zzYpDwi<+Pu#C3~&$D(8o7HrEr(U_Y_ec99YMaagPjmOmuu&2+mL*EKijd8=Qhdc@- z-WqE8J-PFGLMDa5;CE~IZqOCePXOrV`3m}~Bu?;lbiz5^`?Z1Qbw* z)3tP&Vm3`=08>U%#_094iX^K!k@6d85~B)?)5QyM4tjJ*L$fjr%6rc+{UqQAhYrs= z6oo2|NOMZ|mJJ0(3@=94AYdKkAGD19fJTFkQZsK$(7Nwy%or}=Zl2wB^o$MqlNtx=-TDU?0xIya5N;=eaEk0Cmn7ly@T8d2^#InAIj}lsw zNlA!MwPZg$7*y$?=FX0*V}rRRkzTJqZm9*l_nnj%uSLka9;)6+4ScqW6R2Uj1>^7e zFGDXBd>4cAYtMiX)ph0izYsg$YPj_H?S*q0cyGynpA3VS=z*7rco$3zW;quAilj3A zk3#39zfu3lui%z_I;H@no}hcOetvL&`4g0 z74sg?(;cU1E+GBh@^CGv97+2_@Oef%mVD5M&}@DJ6hI0Ipbb=;qGSh+I?#d33w^l@ z3~f;NXnl>5#G(WGdw@6wh6e~@|jbaaet6}$#w=wBrj_i^rLSEcHCQ33f^uF7!#G(wJrY@7J>DHh&mocs{b{FC2F*wF*@eB02?>WLM1 zt|w5eL8ohCm6V8m!d#p%&MXTB)9%D@1ZmjB5&ig`Cxub;;Ggx0SWxz(jT&=Df67f< zFccg+9K<3c#B=$k*ce1rYW0@|kU*gVKhG=?#E zfL$VO?D!kuLy5){L;tW&CJ+J=mg2J!shsOaFhj<AFqDv5i7=Bnj525$Rh;X8s5ftmIdiUWkbq4s}PgAek~*IQuyJNtHEpn-fA%z zlJXN92&VZp<+H>yKDQ5p2)+uPvghKmLjEginTVk#p7|!5B=3*PP{j8@VV**%bg_!I zcReqaY3twf>#{l4wyvjuAx5*7eu2Uqh2N{{ z?ODDPFa2Dj<)5B9xk2Ab{^!La;qiE0uQ?_E#c}pA!J3oJX#JI5KF z$T)PG&(ehPpKY_7=QY1}1yKHYzC$%A76+h=j_eZBF(yt69^zQ>oGhD-d;tx(YKwTP z8VWr4!jC*`wdqUqz+hM~Ui($4;n>m!G)aS$PzmW6VsO4tJyS?ySc!+b>tR!j4@1G` z{)U=g6RDkcUzA$AbFQ#59!s8TotI664GQ}4n-lwV=$9c%Ae=2?PR{|3;|z$)+G$Wb zSgAJ%jq5Rc!LlbV=U?Q3*rgAF1sAC;!`Ap>#ge_sglaBk&sBPhhc~*I{_3%F5)i;k{CH<0RvbsY9 zBAp~GpMW(NbP}+V1x8H;&)>r1HZ15jE&ih5qBynMTf`_!-GhSB?9Ueg5BP9s`4p=L zqvKl1&f3`%*F)LA8`4IHSuook?}Ie;REMZN;W}kgf+}S=+>eQ{a@fFsO{h^b3VZo--F?PhUK|pI z4G4Q1{ey|24lBLA2^dM6d@Jp`yRc(3I692X{{qo<;4X=0hfNd&SdmmrPTqrI^oG>z{#iktUzlY9E>SE387oj8eyUsy!1R#xfk1;q=!*_~8rYI(n7P%o)6=g7e$LVqT!q8_nI)X!!irm4%Qj=SoNOP!|j z`{jRGGM7}G>|m~MS4ghQ2$_z(xDhK~O#HZZ;i%=9vAPJ527R{g;6i~3KK)XC)C%lj zdwAD(9B~kzGIJYKs%nUvkDL4RaEdrRM1VMg?lY2~7{LO)50DN_o9zgix;-&2b}I^B z)Wk=4c$L3{=L<~a(Du37AREATo%<4`KQu96f49!stxPutym>&etS z;}x&3wlxyA3e657%q9f{zRY!$QWPf`4E*qC>k~AitD2cVR7}MD=0{5A;vaRf;KLdq zkJSk_0u5D(-q+-y5>0q|QtLX6!5MBV#=d2z1hvMHM@SS_C`H$AAIXF|>1>2A$)yIt zSvbHjklPo2oBcTAT?7?Jq{H5QB(mOifjnDlr`*4~n zRzMVH)+@@q)&9KY9$d@&O?OHtFE5`CY5ssSR0&Ma=G~YLyYrPR2fSfyz^c07-ukmC z&hYM=nntyAuoFZmD)fm-Ls`QCXI%JjY3>3TIF+y50v=IthiAW@UJBLMI6sfk^im0$(69x|}S zg@a#zXw?mM{s(e*&={$&69$+n=5`Z<&TMO1HuCxIdvJcHOE3TkLlr3ccG52apDgVC zA@+icgCEIp54BHodNpkwS{zLwZYFUe3QGhHcK%-DFGQgR&Be*Q&VLG%6ysu59?5cF3!)QA`oJ`vBDCtx)`vS(BLg5)Pa|8Xcf;o zs2^LQp1g{F5o5agU>;~ZGO?^vWUgB@bhp$T2RgTp2GA!EScG4=Mk(@ zuE-K3-ANS$19h;YnghqRn(7xyS-x?2+Tyu3S*RMY!1P88=Nx%XL-J+rJd%sJgwzt<&SRZE%q$flcO)7{63eqDAqD8YWBz6fCxDNT3r%9_MXgJTME*4L*Waiw z5BwNmW1$qT9}#(v6d!1AbhXq)quQ2!JWxSQ>n zav8G8;vUIdP`h17;99S9c@7u!vq#4nAC7(Q(hJ`~ti+$t^grhQ7RCpqoBhd~i2SIe~t20GKv$?OC!3E_aJT z?rJ2=_iaE>O;me#&;@aI#Vx`*0Wqz^>_G3W@V>)@iGvSXZr>!viP$Jn93Ub(+F2_V zj=xyWaBy1%keNBP%JuyOeYie!f1m`^FqK;7lyhYyaF!iwrcQ-LN>Lt!Lxrev5X791 z3;g9SV+t}0GONF$$eDil!a)Jb;SNajyL^J+*~Hp#Qkykb!h;|L^c;z>LhoQi_06^v zcs;a60)ld8T))?kw+Ah4y(7p4v9+Bn5Yf^)d=qYHU=n@RCGS~V;qJ&|fePW)L4n&q zzC2_1>)04Dk_u{KBCs#|BBUE=T??p#pLOnDtX&70u_&&pJW#HlTaiwKHKI@@u-vjZwML=f$^8v_(>pH z-Zq7#1Qr|UK!wXA*NTA<+EV_LUiqg|1Rr%Gmeh{DCtAPP4L=-P=JGc-BvX4*0Uv;+ zp(mQ*dT_j{F@Gd;p@*y6KA?$S#rK-f$*1MDgX`7 zEpT#NRtmyqDKr2-v@rmJ{6ynjmGg!MEc3dLhLm<3#Xi3M$BclP#4b&aVZb3xmm!4} zzk%g41-=59T@}(hcq7~REv8C&pY>@51-T;4PA~uheuo?`9%yN7hJ(j8#SpRVjIO2t z5bQD@hIMI}kRO(ec#@KSg?@q#18oT&De3Y$GxQsKR!91hheBP<<73wo!=IFf0Q~Tp zMl>-OSmoELpH>T5A~}}e+6eTIg-A~RHQj2N?FdU@^Y7Q$0K>=KCXPT?rx4dAqa6@l zVT{LLS#4{V3dqh)-B9MDo;8a>!7KmZd3mykT$s(ChnWrbv>J)~Yks!E_U7J|_nHEe z%)T1;VG(t8bphXfl+K%8&&?OT3y#L0Ytz1Fpqlq>Olm$gJ4PpuF&WWqSgF4W0%Ey+ z{HZ4@+4EF$PX}Z}5KJO{>FInuw?L?eVs0hCEF}d=^fimT zxA%0@oCbrcuwy~X&Vjo-P0Sxg!P7ehEk@~@dpu%wDc5;yBV+V7^U06wAg?oMD6cJQ z7GIz_q{e{(EK!*45?K=kp%^_w(0CJW@D@@%An0$I-05;1!p+Uif0hs$9SIMCRNaMr z`eh)??o{mR^ks#-CDQ9@Qc2?i&Uee2L_^i_mFe-UoDZH+M6U|sd#vwMDT8WwMEvdr z*n~Ze)f2)$gHZ&?%y#u7M@G&49{I(>23iJqek^lu%Pj}*^7#85sV}N(Z$Hq)L<$tZ z5xe~KrRQ#mv(6HD>Gy6wkFDw}#8>L$Xz?8*FsF!Z)GeC^GRqC;z{|M zy^I+l))4n4X-W1kV(>k2M7@M~96h0s&;6NWx2dBa^t=n#itlQGJ!anHnOMZA1fE?` zj^8WJgs8vAs4{QvNK@lmDKqx$JHbdmrzuk>q|w3eG0z`38Z%m!((t{*;>750`J%Aj zllo$frpL2B4qq4zgl!hFx*L28%?hE5-6)Gh&>I9|#v2Iq_25Eoo#gx-E zofe42vfwTx*pos7bZi+Wiu$#5Nh}~p_0f(hEuWfjaY2CuXDF+1-1#aY)a2VRvGdkl zJiW(=?f3o5zwv$5N&uu@n1zpvWV>ywd(*#@7hbsoPoMpE zA&N~Y?jZve_NR5ZZpyIRd_y;Uud^+!Y=xX8v08R<1Zvy17N+Jz$co~=h?Nffgs3-^ zvgiZNgq|?M?6w03gs^d+yif|ZN&e2mG)k1)^nOE!AW=8X3nFCA9H$#$4i#DNg>VLH zrU$7N?TRX%pfZDH3}o_*oKj?#QPo)H6R0-t#GXS1K2}YmbFN1oF19DduAnu#^Z1GN z4st)mW8*7H3u-3y68d6(uR$M`2vC>l9B483JIwRPNJ){Gr~MkY39$)PUDvB(W&JO) zp)6YL0t%?aP`>DA18c;dZSVelJeP-0v(1mIpY^<+IhQ^O^~~I1V*VJQ8kDD%rBp3n zQ~}R#zL4}ojHLtUXJr4aP)}1!e;WAMFycWtOVlYIv$tnHcMS0cp*1}NF$#nb3w^A@3A>yp zYIT{a2i3KF9&0vjK59_QVV|hleh_=Sh@={Z-ULg*59loSq`jXC61i7xd^VO+0y->K zZ#8`!_Ef^KuD`|&UBNi|v;QcT>@7a-@?(oU$o0l+TtgyJl{a>F#)L4!U>El&L@Bj&;dlv}W zfFKNL1T>N$V}i%^n2pFCCmml1->RrlXK3V=EA?Qsv}#_Q3f1`kw&u$l%^E(CXDqUAR?AF(d0A?iv;hd#UT{jKHkFWHG+ZyI}Mu`~BkApFg zQk;}X&KH1yNyYYvA5^87-h&W*{b5x~IDF@8#)%VgI~Yp=en=^{a_f)2k2(Wx^~0qo z%LL198v{(SevSw)Z+J|+NE~yO-gu)pBzWJ11YW7-TG|Yz-T{OV{=vp)6FZ8GdnY&@ zhGG>1#)mcn5Go&8yd|h+?!Sls6SG0kmwX9Kmv4_crsD@-7J#^HF#pHg%H?qQPl%o! z#R72+-$>B!YkO$Jx@R5zNzq6|5{92x3UsnwOq$^tqP#R44e>5CuTr|25jXZ)qi7>b z?*ewtT4fT}^%I?c=LvK$PMNqkBI^9p(%-5;)y2fTKVOUajif9=*f)=645}%D>+GFb zqy2x1v`X-W>w>^wZ~DH|S8Ns*HlyP98HhWCXw@!_xDpS?6cf@4!Hr7(*?%!f$)y19pa@- zJio4@CMj&>Zc!koB4H72>e}vF0etY`bWg>60QiB2a*vfU)bwN!qISP$r{GX99x2YX zx0d<<|AeV&0P9znzb+Y0-X}u=H2QsdEi3acqer z^SLB1G;6wISjE0ILYewQb50Q@0jI!bgK1M@6(Nd(mpZYiy0e!oG8hvYK4?<-&*f&C6;GN~V zI$g=@+wJ@-Jy{O5dNmYzJ+b>A6^o1!XwZe+LvVtOmTv}Gx&y|%ysrY$PLL$o;Q=7< zErRy{pSzJ0#7y;xtQ-(atuA{fUKCe)h1MUGNCbR1t}nDc3Eig4jGq;2aeT!-n8+FE z30)ce#(?8=bv1OAgKyA%e9VNPTfKCe9d5bt?gP3Yyf}XNIx7BqahSuR4gd&=y5*7U z3;9+ZTs$#U+>*rieJq^(=V+R$!OZ)ZT@zE&pTYT$twqu+Pfy0G%8hx%_wxPG94Vy+G({HAvh5l^OpX{RA8&H2wMb!DN$QS**?@FCsG9D6yU3-`XpzR8zo%UlWP_T-VfD#)Ns$JaZ4A+kCFZgf)VQQD~reooNC*g5W5 zn@)O0sH~};9L%^5^=)=RDr`~>zXfW!X`@6X*{ zawYjYnoAbi{>7MhSZuE+gU|}m8y35jNTXl6{uIBxq#=pupRSLeiwyGddCx2 zko?fj`+j*~=+)IZbWC6Sv(6)Tb!{{3*CWMK;xA0P~|D?S`CglCI+%%F%-$`PgD($b|a>@ ziKu+{)@iIz={HSZ)`d8{-bL*#i|H{LhO`a1G!|XqPwRiC9-!<$Sinh^_P=cPCy1lEOw$nL_4( zPvm}rnY`f;6PwIn)hgBN8T{!OfYcHa+kGKAP_*KWguq*by}yIKvsCA)eCQnO zLmEshYNSAu$XrsF`Om!ZxDPh+Y+adI!{ys0U;G6^ z>7ot8$Sy(}@mGAMu!rgcpF}S7{^I(Gldwf8*E&}%U4`G}ZM8U}e|5_jRLhH9{kzEC zpC*;rd+!$2S~_P@$X6W~h_&=}AS@gwYP}6t5temrS##RrgXhZ*pnYOAqoPvygYCA9 zFnREU%b_!W<(hb9vXZWyv8eE4XQR$ndsE`CslJ4LR9 z!QOcCYRZl;QGxPuxr`rEdYHkOK;{(1w6jW8dqGPZ{*Nt@k~y9r@S~m3w1eB8@DuU3 zI!saPwpKj}jDpTn8FyOYAX9H^!W(3WmkMkkS;uoeMw1VBtJUGL-MTPZyxV*tv&--k z*=z~0ja5aEXKYpiP=~X`QDCN99gfnyZ^KdTI$~Z&oUBg{&K#CLdd*Jt`vTfyta|( zcABS)$|PB37XnzdF9HO6KZK|mVz5KFXJDp6NO^LG)J_qZng3hq8ed#XI z1Md9OR~G|x;{q}>vq5h{JEl9}V6*jKDGjP5%$tAtMG%>TDPoFS%-ipKznwCQmJ0F) zW!5^)W_ABEJbWU0qoUNq?*Ey;F!#^NmO=udbU`uM9LJC-DwYx2eb7>P?rfR`LvhM)TF}zU`b|iF0DfiIPf-(ie>Mw?k>rBdei-SFgnfcc83i z%xH*UML#r#)Sjk*D9n&KN`ZYu#>*B;~_RmwcdtIWkf`+ZH|m` zGWvjmM3^SV){J{IoOq;7zX*tp5y&(9l|Noj5}Dm{LD4o_=YCWN%YR>cp~*zwA@v%z znJXRJvGH-rO^9BRNBOSivhoyZ6d=V?VaVTJ4_{a_&{i23+ofB9r|o!z$fUBTLuwLt zUqp}Z1R;Y!bfkb#sIkSx=Bq8P2=g{6|J9%UJ)d;HPgi(4ltWr%5G*0jsq|F>fY=C9 z-3aGf39qLP>+bJ|#Y;;Qh>Jo+`R}=vCKVA4e|SG7Hrh+_9&_ySLC$;bQ>JsN%xSI+ z)oH-{G(`o3P9DXza^S3GEkRSH#Wr)cBunf1^bAREC_WX!nMxIFmKW$TdJ4;^$b=h% z%x&E5Q4L?77cpU>>NOK0puoJA-liZ_9JE>^yJoHbjt?VxefhxIm2Wr<14G}A-jM(v z*#E#!On?Zd)32>snbcwy<@KU$u1@#EJqKifCFqkOi?E!`B$H7;L6;T0z~q80GsF7Ds;m;BWdHsD}V_k_Yn-O=_bn!=>=PkiH=M7FPR)W_X?gfi_g+UELfP~mRpap5aMe7+CF+*= zMrFW5G`<--KR`G;W+y8qvz8?O!2i!3{;Dm8*CJusOSz&;B#TcvnJc5+T~;wPO+QUT z^Wmq%9X*0++dGk`darLTvN=TVc}ZsJlF~(97i6?9Ey3)xM%w3 z>e+=$TND=6j6b1CHJJ1%2{uuJ3N>kZ)QkX2{JGp)ZuoGV16;s;$U4vxqRI3#E?SdQ zkhX{lZR3GXDN+qiwARYW7BI8=elz2R25H^5T(~${@3OehK?BWYe>+<(LfX_ms3iKR#;6`e{{s(3$>B~8lMSN~fGNh@$3fxheMt7+xKL#imcnl6Htpsz zWsE<|bgL(4WgmnI-jRouwJy?Op+uEsl<zEbxq^cdA`oqtZIb^oKq`5xAW?(U| zT&W7`5T9+-!_T}Jj_$xIWPa(Y>k?`s8hM}v&z1K&D$2xxx~CwAJIvb5qa*&W%^y!T zx0I#9f{T5EYkz5|Lgq`}{MlC(h=knKu!{R>gx&tRci*L>@g z;|r5(@BaRN6s5qzP@_0h=Vd7pcQ&zm5le{H@qdY*6{lqWkd5khgj~iEWaj3#V^RPt z^P)L<3TRmQcTQ752+F@qDxViA>cW~GHE9aU}{g~<)Ut33>}PM_^h0T_cH7?0o!HehSuyMtjzY+C2L$x0x7EfqgA4~+(% zbvvWdnn`_#Sfd|4*Whl6CX<1Pf9AF!(R9;Aq-Z||~4WciS0*%OwUWzK|nE;KKSC`}_< zJpVKaapKw`43j&dpZNvUbA60xc$gAlkg+I=&Q`Lvu#{)z-T2mn+Tw5$eD>`ey|70p z&uq@JFjz-?15rA6T3vY9KQS0UxJ_@X47cX zR8{@crMaXumky=7yDyCrD%~yJ-659-Y3T;(?oMft?nb(#>pjnZt@jgOU~ztN=FIHb zv-cLS&XNmy-4k!zy!!4mU*8y&F>W=T;|K!OhSNyKMhsTGZVRSCCL$D;Rw>-K5#x_O zL@FK7Sga`kYp0{PA%g=n}I??E=Rgu>5rrB z#O}gts!KiXjoHwo_zgSj91G6=i>*;8;IMK8HD<9=9GdqQ4>A_^?obnKXGz_EkHwO2 zc)ZcD+-zk4Ictk!*Lhi<-Pprx@yFye0;}_C(Y=o)0#_tq3GP{B<;9v<{=oVW@8!k- z=Q7mTEdwVAGmDx1XLXf1W&l*LSyq{=t!Mpo9zWE4?*Hk~-(B!ZgjL(wTex$f7akwQ=O1{C7yFmCHIUbA4_2fzxUVkSIlo-F>ORbm zzOc#|^rO@pw!wVcy~flX3fOT#U6RPJA9V7h`Pa-(bO4~>9D^|84AF&ck^h}e=%MHR zIt&7SO(!;lU$54Y-a;HJP$d*;t66LCt2+h3^LFLBh)p8cyo+ukEG&*#5`BB0%4Pw2 zv%QzXO=5GpAF#Zw^AjUSNp@1+GI3C$+WEFfS|1XkTMC1bqh0CnKC?!2Mti5u|C#W9 zKBa3ZHqylWmQ{UWzS@0~eD{P@cry6Fd-&j5MZu_0cTk}PeS@NUPRFK1&-;=`*LTaR zD{`7It>D-~Dil=hOpdILp5x?+IH%3>kN?MNjybRvP5uh**t=IN;&!+Lre!KE|+t}%7pwX#i zjVOSq*2^j4F@*E+v^kf?xk|cst1fK@Ls1bXg8M{S7y zvq7*oE{z3RThuUk@OEFv|FF8RLuaZQW>pbkRk2(rIAtktHzJVXy%(*okzagPkn%yB zZDM^YF*CGqfTbzAS<1ZK7Xcd^8w1lMU@w$+pLK!VzXIh?CkVD_VJ=V9NHI{Vko0!9 z;v*l$a5xqnYLmlKWnYRF5@l1-jk zsiBio?M{sZmZ6amRj@YpK!QBeNG%WTAW5}Nbj2+bfn*N9`ggOH64omA#UOeqBdqN@ zikB+>>nlsUO!54~)lvJ+)v^OGz38mt`US!0BKBR^Y5S<~PU_G=P6!0@FUM=3Z!XeR zw@Xv1&DCB9EB%_?B^?h=IqHC8$A;Y0F$^R6eT$hTXbjn8OhvfcCf&D76CsXim!rcP zIeFh+8a0IO2+_Pg$Bz&JR$t5+NxAdzBYnzfIyvEYDpvj0kb!|hbZc3>kAS1-KoHt! z#NsAaK*A)I0dtP(aRxyev~kk5?f&1nFRI3R^Xl<0EL#PIaNP67@P$tQ_wiTy{;#gO zg1#K_wMb-K+Ec+U^jnQ4X9;q?(()6jSiqK7x6Tf(?jh}0%}-k)WEzOSw_R0Fb^J0! z87YJi;OmAzYJ_du_xn-8jAQv1Q;RWdvPqwN8a5PKqLXBWSk?ZBdV8`Ixs*mE4gyzD zg#hh}adTYfYiCVO-4Js_lAGLr@GKz`tb{g6!^Xi2FfDNKz%`k&YP>M;J4i@vbLm+4 zO0}H$1?Svr12%Ce6W~pM5_2a`G3cs)iNHWHFwHhD+$901E7taN4Z5dz_^Ju2hT z&1egHI2Pcx@~bM7f;VLurd}`bR(%}qktG3`$PhIJdh?c(h+4c4gq12{CNgNmSPfoe z4SW;ZCzj`DAK@8qs5BX1T;f|b<#^Sg~ePJT{49+%CEO{)$Hy}HJsr;ikQRQ z--cmN1o&e{)Vx>rGQDm;RA#jN5Fh`J{NGlFXg>Mh{zgvO%;Tn}&WoQdnZFz}cqI#A z>}C|5KR%iYIBdoE-FVPlOB#dhGHQuo>Gm@m3YF11Vqq}(-~xW*HtL3Y=iQJF^-KcJ znKbI_M>C9~ujgVTlxRoRBgyx<+5AuuH5D)oVcqymW5xA-P1;8=UioMRJVND){Ul)lJ}4f1}Leqh+EnRtJT zSZF|7^(S)}S(qJ9nQI6YaPI#tp0I+7=&|}-v#>V(QqlwaWYyXB% zE^Wq^8+M(QY z4IYNPFc~mzc8ERYr)FfXx@l=!w?9XxI9wl%BUtffFek~6(O{sySE)Kk({}>V|8C^Q z#-64`3&Ofd5>!vIDyf)X63tfv!7%QpmgB5en#T!X!n3pvJaOI#>E}Zrhl-|dX1z|i zU(iO4jQYA3WWXv9A-3hJ`va(jT=P|1PfkEagl?YY0p$R(QA_J1>%vQ% z^(SRNbd!XY4O-bSVm99$n$^}p%E$^$;2-=YH%T2b)|87$!NFD?1aCL_qF3hVbFo{7 zUJjb3Q#D}_na=E|it|PBI;63r0#|C6X68q&G<4`1&7+|MH;MgiYU5a?_l_CxH~sq0 zt`1{7!Pv3n^FJ(;~u9&hVDgD}xDn2lt;wY}ph0^n}jrfDnggkJ>H-AmqvY<@c% zFM_m1v^WgsOBNGbW&W4=nDZ(I>8WY`-u}0;D)fX+2C1<6_m9__KMh*XV-XP|cFX`O zUw17F5b{j0JVY5IM;+2_Q?YeN?HzAWr>E4C#W$nZeWRh!+QP)aSqS{NAeV`>S(HTn zO#g^6;@lo_Zz>T2bmj{hH!F`YDWkx!EsjktEO&kI^%*z+D)%C@&P^*S`~XbJSK%)j zj2)Gzs&$D{Fukt{xwiJaJq+kY1Z5JV^&lQ%_T7^P1tK?+AFT0e%)fI#U1*ktUaF zn&312Fbo`05_{}Gbx7m>hnE}^nMe;8O4X|S)!Pi6S3>c`VH5{;z>;2 z1YPv5l+f{ZuEjP*x`V3U5?%Ym$CS_SzIYu?XrO`#0bwKo7o7fck$ZR>^BaTGX$E3- zh}x|Uq+BH7Ny(`r*NT~%x4*FM2NbXDiAiTU z`Fo3ie#JQ$NRw1>06FoCWm|+E%W}>-W+ZJa45m*$z>Y6R#e?8}mlGVZxTgNw(h{B0@yh!+U2$2dzS@2%34-I(H7)T{%dLM8#J{5d?!5+Qdx?qO=f0D) z`RbvBUJDk7qbCqf9JK{GdZ&Q`jHiQ-@uo^zr5f&b@?$A_+t%O6<&s`UDgj{ys_o1n zHyh0u5zasY#y}-O$ZR&=kWx65-fR%&G&xwZ=iK${qYM^jJ|2*^rUw#0YUn@k#bgWi z+=75-R!iIC#L@&QoT$&prO~f=Y!7P|QVB{%XfJnPR8YxR;)&)(||NdQ0<#MPeZ77s$#xnUMH`9?esT&4TW(3 z+cJv5*f)1E@;0BeD_*oj79fWo;H9M_PA_sNgaabB>Q6Am{qHy2b06IG%T9M&CQC@a zt|j)psM1)q7@5^yLl-rQA(Z;K-iZ3~_}V{c>niF8k(8wssl3cWy$|?*K>rf44tFoCfMH3^(Y)}5BYFW&ydS)q0#RQgj7{;i z1*ICgRU@z0Ad#VOzlZi6B}}zV+YSd~p|?ZZp3&aE6Qda}_D#fTf13rMn9=vGAvDnP zbW6^+h*kQVNx>W@OdjH(9D|z9rm6gNjq-<(fJ`-=ZlG&!8;G&Ogu-y(>`|V>UNc~k zVTC1=xY2!DBWhUYFnxzSG4_Plp= zbjv9BA_c-zWK}418yakiGiE6Z#Ve^&M|L8KA6mcV&$X5~^ec=fUtzYo6ZJU28IHkX5e%=x`~zbpQR-C|_m1 zS>q*{ojTq7>Mw`F&7v*VNGKJ+Np^Xo^!P55*eBM)qLCVF;H$ zTJ#=j3<0yQRhTBGr11S$HvM#|vT5;xJBpq6I51X`ie#~9fW=Kk{1}fM1frurGey1n z3tO6dmzQL!&KB+bspT%e-5piKPVfAeO=T7lxtbLoT4pfw84geh_SD+mpBZ9Yh}>iq zJN_#*nUd%azhhzEI9birS3br%H7D5v2NKxTA&La_Ft2HMHUy+}z1S3(^sxh9)JTYoBvUg)W5rs-M{w zGXoL0ynYHCJaRgi6lX-+!<%>qJij_ z2LI8eM763xMW-}h>zve73Bo-r+!QWD^Jr@0`mJz>qhU_FK$>{Xa$YdyxKVF6^00nj z)%@UkqqQbrl&_WK>9j!o)W@&tG_O-F7@tc=9qaL$a*WsyInOdhR{cl2XC-#k8HII=eq+SFk`ALhZ0Z(QIpc^u>RYmsjX{BbQ0)s+fxJKuEFsVA0B6xE;V5V(4(SHf4>pYnby=pGf_Q1!n;=*x;PChH9Cs{+4ng0g7QUi(}0@c$V)p4zmQrTK8`DUD*hmN#C*h%s5*b4&8L^HfdByJ@O$&FwtlMw zO6}IA-n%zDa-%7|gKpbKtWQzW3I=2zuIcETK^oBWxMyp1gXv}^x2aQfslPsdkM9wx-hW%rS?Ba49 zl>TElVB8fXtZ#iPGrA~+OCy^Eo!s+Z`rw1H}S-zCGz2{$=my z@&_PMkJHu0(Y)832FOZ-D!oU%!Ojyo9N*(*htvH>SzNSQ%~bpCB?~)o`~2yX2EADg zCUADvGG~c+7!{-9=oI$t8ab_#cx?fes!veOWIWy|@2!Ynpl=u*ds}1=J_OQ7k1jRK z#PUUh#F9_&++G>N&4}a)sOuvDMCJA8e}6m<3sY3=XT9}kh*djVaP5{YoK4_GHRy~S zn43br&G~IkA{N<%?$89LShIqyB_JLDoiK8!xX#};WE53WNkbnS(jh>9bhjUJk`k6H z(b3Yl*L@~?w=L^`_Tu0)(O9XF@E0)nPtO4si!1H!rj^7 zzwAdzj2Kv~;z82Xbga?6Wbg1s61&WO2U#x4!EM^xj?BInCa7FncGH>-Gv@6M{X4q& z_lvHOKL(r6i`j7RPI#h4ltkN7(2AARNCVBf_ObUH`B6Mtb+Z&Bt0x_?x?1$UuPxU= z4fQRBFTztS#lXp#Ba#M?r7~36I$SD|M54hCDwf5~Tbh->r;bq2wq7Aa57uQ3qa*i+ zYtXJ(_?nCTX9}r7^keB%cEeG5fe+~?lLVR_&@g*-{9!SmDJy5t}-;nu4N48_k!8oHkmK1vAex zDTH?jpv`qF*Qi4vB#MB^rT7p(Z$3{StygAkI~7do=7=cF_EuP1J3A-Hb>3xH4I;w-9FX)7L{};K;d{-`t@KdM zo-KAJRo(C{znyo3v=gpk)T<;Tnysv5DoUTLS&>nvN76uj*e*NVXur)UEh0IozT;&l z`oj3BPp-GSU|mJJ{P)*Fgs4@&s%|$@D68l>N><|{~i zIE;;}0zQ>8c$3V8G9;FMT$TaDkS4+AyrxMc5ck~cGqst>aO%WT-255#;Tm!u`{GsG zAKJBRdk2{iqeTn&%0sz{KG4=)?OAu5Y4XgtND2KEV$IqGjU! zH3{fH8ApDwr&nYis_MuilT*$_2hQh8I6Mifa;r1NxjkmfZW6=bV#i`~J;WFz79fcB z@&}%+al+;mvHTMulr(2g`^Jss$p3|Y+SQ*A6MJU`t&eiPH~b7Sp6e4MtfeB=X}VDc z2R!cM5`sPv2GOM#r{myFqe)~qyV-!hIip$MgzcKaiFp(chos~$mjn+*uw}zT2W8|_ ze{dqg*y(M!Qi(wWN4ydHoQwrwT=I*9PPr@^6?Xu>@_Y1iG5?=No|2#vOcPIczhDJa zIjZxR6$qIQhdbT(x_g!le>PnqljligI28rkw*)@x?9T;GW2Y4*pF0mwaDA1uttsrL zPVS@dB*o<%y)(+%Hk3hx)HA1ptK<{ohISm=9o>Jij8ez>%Oqg1%|?Ewu3T#p)$^F` znz?~od3QvRrk_yU*4NwFGO%F9wcQHbJ6WeBd)!*fG@-h?-r3W}6(&iX*!dFp9>g-T z%F?qexg*nEUb&PmNMs}Y7-D8pE}nm)r68yAFma5?VE2`Sf5ACr$O?5Y7w&k)`FA;r zbdx*Q*{?Xgl)dg%dB_Oh5~WJV;lHk^K`TA747jy0bQGtWqa!Af_ksPE{LOV{8Rrb; zmB}i@Pt_+5wm+HUROYo2@;7uP@>}6H)?QsZY0{)vjdMcPFcVkXsc_u4$zdkC+%PQ+ zgwa;?-Ba+~qIlp?X(PSO3)H8HM}JH0%~T}>29aEHOD>B$yje9gZ=|r(_KNHOB#TP;EDYk zk_fYK`ukMsCgEz?NNS4mwSTj%0E9wDZ0O6r$ZpY$wcq(0o+@8vhOQ9kixrR}&I@d^ zkI&J-)%J-O0i4kyC>9WNM$cy5mHbt-mjpmIK5T#I5K<`0*U)A_w}9(v&+mgz+ezmg zQS9Qo;g`!+@G?UN_(Ulx(){rWrrK#ykpo2M(=y%nL{W1nbXPD|SgBEi=vUR$`pRlc zX{MZ!4slPJNl5pT~^zgaa=j^JZ#}Aw1M-~*?_+jqiAMROdmnZJ$FmrD` z3}WM4Snb@wAB3Auf5J9~UOsc>z+UjZaGF;TeCbz$Pz9v-7jGe~%3u?Ry;ZXezb(9pP9FllFePIMWVXW&kaVx3L^r7#rj0mO_|tc&fL1Yu zZbK>6Wlcn4TcPq}8ji)sWa?xmAjOZ8lATK^cxNbfgU}SV-0WA{&y3#7ogv4g*>Crv zL%PuI|H>TO!ScxuQ)yT$8-Amf!S?>IL>Yd!4X5~!#K7WpKdd2&jp(lXd#3P2_s6Br z&Ho+?0gU;KBOh_vLDAKF9gl&*NC4;4r=HsLwc=;`l`^3F)~(gr5|S{P-Cug3FO@(4 z*VPqj2?I(M)%nTkktkxi1Do-$2)$l1+MJz|s1*5@&d8XB5F6UgwIugL&G_vV9^g4I z0=Tj}hzcNt=b)er3fge=E=}o?PhE2OTk(!Td zXeql{-ke~DrtpARf_qQ8Q_Dh(z+H#emPEq|8shi?0pLE8)Kz zS0DEMCx|7vDJyz`=Xc>7OQ)s}wrc<9&bB%4TB&|aD2XwdgNkiCruK4Iu7g%-NtJEg zTl=i95e9{Fvio~t(q)Ti(+-gdyOl&Ou+63}<)O_G#|#i=oo|iY zSZh{P-nKGAd<)-X;PW_O_B%MD-A2h45 zB@La7;Uwk2eHKirbm;Yz+QsuFJ4v6bj5e}5=u<}GB)gk@D4TAZ|M^58JM)aKSxFt= z$4)IP;QL?KOy;%ri&WMcGi=(@(HiL--?=X|yHtdi@%ZRH6G9an+`%imNtWIH>7N!Y}fFrT}FIb3(0Soj+k+7vMOiL8sY zsq@yI(rq(5_t5npZxuCDEvk92X_P^RZj50~qPY%NKKM5>Q^$-Lcq`=X9Dy=*;R}av`Xor~7HHW(}C>&Hv8aYY^b}Y_Eo1J2(lP2(^>!sU4mfX#66tT>E=A-ND}! zz~=K@HD%>sU&buZ*vd8x2V8bEJUB} zgkN_%AtTN!b#}cPDG1SEiVJ8dYZgS5$OUZ>93# z(9TP~$$zb=5bmHsMS?*Ef@F;}5f;YCm2eyk9W11XFcDX3J-R;0(#1N9yb_1FI)zJn0=6u z{9XRW{@fSo#pLdm(Hnh@;)9Hg-pQBkcUx1yuteek@5=paN@ti?L%f`4qVQZKktX#> zqM2C}oCHIti1)3r4QJT*(E}@D^!_;XB%tq)4J<9Ny-(DRbmYI_#*TX;Ttt09ucRzk z@^z)7QsF~`HeeUAaW`!Tm|MI*LbmycUGbTiX><5<7!F!3|4qljMT6KIPB8OhDjwXE zJE6*OteZu<%J5EK*W(?4TUpNO+@BG4jZ#L64oTqWZP9(@T?vz8aJ;|3{x8PH{kTi6 z2iwBfdCCCIw^^|I5}8Rrz>hVvbok7`KHju#LLKg+ zzl{OsJ9&8Fr^55iJ^Rk;ms)yPHIP!YkS2Iqd>k+!c)osnNvUz3w4vT>&|&So4n6O- zjrof#DE{G32u?J@5Qin=iv0$ED5+CSsP^6#Wov0E1F3)y*f;=*1S#G;4iWnXdi=fF zFE?h?-a%13uU>!}p&&N7(OWMmaOPHWHeI5sj6@(P9(N!* zy1Es$9m;sf0C@*y>@2NkUDh2IMF|rOI14HJ6CD@`B#4jGGbzOE_fPGf;JrQo(xv8Z z;~&)b2R_{`~8u-uyaERf?x-WVy zC6F%-g3DKbZEv^m+UeU$9-lPkQxlt^B854P@-HpJj+^$!S9}rX)D*c2ls5NjXB9f@N~e$%oSdX0zBY&W^HTTb`RJAN!U6eb0gd8u5u0}KqX)-jZ0In z;$KcOBsemVfV;LJ(POvf1)Qzm_M@eB7P)PjqU*xCD@3hj_V|}d ztY%E8B*Vh7Rg`cgMIJN%r-KPVN}of3%a6}ln$%rz7r2hiE+sWUP_!o8ul8~FT-&Jb zkefwQu*55P$38_}3p=vC&WFbZ^xFm2!GCZ<%yUHbC$BF?%Bl>#yoiDH0GJE_!O2nO zCQ7c@niv_u-gp75JsM*EeC{eamy|tC{(tupc+}-H1zSz+M?Fz0tPLh~FMGxoj&zSURpX_$#d_S$Xkm#zC9{XW!fP+c+>_V4j~bIGHSs7b%Gm-hanf28}xJEF?D&JD4XM$S?>92&${A zL9hTOl)mKs_6f2!%sfTS2Cr1gYu8GA()O7RaFrqT+on7r{k;E&*gAyzKHFmy_x|DS zp|9Fza4EWWY3(!pkZ#Q<2BPXuL>NUrJ>pv8V3sdAs>3T{fG+YD&~BEPO7=v zVTQ+`n8z&|Dp?9*peZQy(xahX4q9+?ygp*l?cxu6WYnm@zIi`M|3%6?F}xRS_^M7a z2Yd;Cp_3{`Pk4Z*>9==1y%=37+KTd!%jBt4>OYJmhjv@ezF^svc>lww=;HK9!m`z% z<+3%~+k)0bq09{$uLX?jA0=HuP>?CS5k`#rc`G=OEZg$2Uv6$G9$|eh2>pICeUx2Y z{6fUlR_vvR(Hc#}LXRd1<9+v_GLoaht$7UhVFiQT+}0H#nw$oM)@?FRr8Na#8q~-G zeT<$)isU2Ua5o|cei)^iWS3NZ?G+~eu0`KujK29_Rm94wYb}1=NsvyO8!8Kd$Y1$J zlSJwloJs*oJI234$UKpcZuxUataMA89CPOtT8bcvjkEA9c-&dTY z?mmkm-;gk1jO@XL!rjHv9ccjX9be^Y_v(OWefsHtc^I`75!(CuzHb`O-J1^yOqLBq zCo34h(U|%tT9%|We59f$i)6AJq7;)w6&BDNv{`SlM_@1h5Tk^bW8~1X&so(EWlUlI zFDWEsZkB)^9en@{ds$71*-MeMmC6VJ5)#-{LZs=q8}mf4+IeLUe2(b3V=pFiQ$l*}pL<7Jt%hSH}I_b&%Be5Kqr zV#qYuT-T{%j=l`1wPErp(LWSHgcQvD@xlB}zaai|vIkUWcSwsDenqKti3-(qv-b}^ z^hKJ^auh`8aCgL9V4KLT)s!z~g(TAU1f0Z3+J5&Fru$esss#%uqub8dpg{zFHNDux z8`Cby-62t_oy0)A?InxmDDX=gdEPHj1)8+t(}@2%*l~IWB`&PJS;13QUtn9wKLXe_qno)L=Nov8vr3dQHeCeq2weq^hQdRu9%- zjoD98!CR#d@sgDbG*KoWSP%AY)QE$n3`kqzWX%xCmRqAIk;tjhzRqosSiy*&WB^gA z*dsO9Ov!WzwBONFA&6cmzft*J$ogSHuME#-L44hzb$kh>q-MV~XBVI3Kn$ph69K_k zaG^ES+R+snQu|jef1`WA(>IbZ12x7&J4aNy$vq}#^c1lYc4RO4hmP}S{6*o=WvUDPuLLa*i&UZ z@3wzpH%_>gefh+DpHXo1Tq`N?ZbgklBR4|Mb>u+MeZyu*CRaCP$*uT#OK>leHzNpM z>yCqWKFHSoS?F4XP+RQT-8>y$77i}?3-ux!`4G+cdkj8!(+>59dZpF zZSlhP9`BEao8^tQ1NKjiWU(ibHS~EE5fNI2;Y-33+3mG^915_0WfD>#fBFkplZC=HmqZEZVJ`|X=l(OOR|Y`)ULgIx57uU0j(mG=bX zAWNm8nJYe!mD~cK<_)_>KYcWS`SK8B7CZR~u+ja1bKzi+iGYgBOMFwvVleZIPgSSX z?roK%q-tJ}oQs1C6P%!={u6l_QB~A`RR6fXV1|w$;AE-@7YF1+*q}fhX^-(GgvDOB zDdy-1iHH#Q{!?E6G^vmy>6{ghOcxh1RY1oRTC?lR3fai4LwbenT~~>>C(Y&U5(i#I z1u`}%gQHDefTQeIQXvwTP89UAHgxD+Y){R3SFUDq@A{fIp!HFy-!*6$2^+7SGa%ab z9}T+{(29Haaunw9FFZdyaiOH?g5vGGOTK`4B<6sm-NC7FVQx4>4VB`NkYaFU<2nX1 z!Zo_S+3v(I2T|V*(#m7dC%>W ztK)-B{zGm@My8vXq55=|6TxO7HP4ZKHpXw-B*HiF=i;7u86Hc3K0tAn(4WiZ^b|WP z1EtqC9_{?vS{1W5vVdUf_++?4Ym0W-nHvEWWY4m zdFt&?7%1+xTvO%;jyN5_?)Z9B44l>b!TZ-e*l)&+7PIZl?>U!dbS+UWV#6dR4TZaR zF(h4Uq%gsBcI|OA>=9RXIHIW0bp8C}EM%{W=K(udR2;|V1^{7YYcBT6q_(Fw2L_?I zRP3y*WN=K8naC?ZwB=ru1eJ%ZCP&VgEx|eU5$#m0I7G`Fh(0X-`=DUrIEav^)6#%y zcq|@CqOq@{rz^MjoVC!Bt)cg;_xGNffWK>lv(A*YwALTFfpa^J_YPHdKKoy>v|s3%I}>sLIY#$n`hPBfkh8~Q<{y=e(Q_T81G&DUIjcPVDib6j zFFkyP_*$hZu3LZtjlr@(k3c);n*+_kBXNd6z6~=3mV%b(7jUr_a%#(&q++Cd8JiEG`|Sa_F>TQgtpT^2 znXf)4Vt%MegG$tU*oCLXqW?aJBWfWSLB(E%xjb${N5d2O77<8?BqmfZeAey`@7zv) z@BDUGf+&2G6X|cn!JsN?CH3=t1$`ja)+V_Z^$&pbeX2_kCsH9mMuUFW>x$LGWMV)# ziEiXR>;3_!2BYdGUeL3%h=c4#D1@Z7N)^)mZx*kJwz#^!-IbQ^sNxG83wppWH};Cu zxuDv+o_B99#u5a@27;ktFTu*acP!$ZQ$a|5?`1J*)nX2i?*E?q;oE0qDHgO#076n@ zW9TuYqCrlc=#q@}dePQ=I?XMM-_QEy&$DDBJhoYIb!~-V?(qQ%|CKLd1x>;3FVs9{ zZW5%(CUkWI*CCfRVE#u{&b%JrW=k8QFXw*8b-vLNngtP&a@9MwiD;32a%;T4`+58JOHuyf8;a zorj%c<0cahoiQF*<^6DyfasH$)mT>3yuBSSGB8}_DDp0HmABx$kic@w3N0{xIGnxW zGZxK=t@nNZ`76pqmhcKNe|6JeL4yDMYVU_##srMJ6&?VpT>rbeq1_Wpq*l=|fS~UJ zFSR_bq@mRi^K-bN?I@bbrnjg%Ve-^3zMgM<)OpiePXMO`tNjkwwM@(2$kC68sYyMz z;X9TzWm+aXFl^Ik`ajH@Wc%{B#O5~)cwB*miqS7_Qj_3dg>hu#{<(!C9t4Rv{X%-| zQbcV88DlE?+`r|V47@iT%U1Xl4;5m)&vOs@8lfe0m3pl)V)v)^fJNU;E8{UV%SMcr zvf6*+RSp2X<*2H?WyzhP3Y$XBcFz=!Cb;uSPEH$osQ9ZS!xC4#e)L0iXovvEGre}7i19nYW?C1`db zkm>&-?05e50IGN9p1HK1Za!2^4)v*lq00`7;|bBuSsKng)wX7`;QO)ZUYsZ?njQPn z>hnob!O{K+D?k2YfzkKL>W}NO^?2sDClJ?fh&Ku>ZI9@|(1l@h+X@$mkcRq_4gxwg zVAIzco4x{=tM>GppQcS4B;`?=bE{~v7}}JhtYFHxRg0>(v2yt?b^)wg4CXb>!6Qkt zKaTO^KU+yCGNwhuCQ>D2I*h3Dvgy?Q9fXX1J}pHP^&e&zYeZKnCrrQatl!1YA>$u( zSj^r>I*Xtr{FbG`GRdf=7|O3}6|;3BABZB*8$DUVQT*#6#R`<9D*8fNTGg(P(VlhgiMOFn4duEB`Z$TmR&5@V`BK>M}p)-KWoP z*$JBNSzcV4$Ai-CaU{{^3Jnnwf1^ZydAv;6K!hgO3_QT!@6<~M3tZ89J?|&s-#boZ z_9$p}N6iHxVz8C08;sYVMFk==5ngKMQb8W!gE`fMW&2F49ldvviD2@Bl~@gM?fl3H zB5*49TLq6DbX*1fAK^q_g(zg(=C&lvB`LRQjI{#hOKBoom_D(mCp6{sm54#lVY=JjznJ$K5#tSQ;p`Ia1zPaS_0jmbghY$m;10NsGFplzCIPrbvs* zAr`xOk;s$pw0@~%UY46a zE^tkie-7h-o%h?gGdND3Tl1wycNr2u_>I&3%&c3VD(SQDe^q5N_z59 z6b2(OG$$l92LT4un;vl4DyUp8s5S6+h!J_}Z~=vJ(7a4i;xD?OJqIl<53_i2_VSmK zXn43=QU^+y`k!~5OeVXhn04o$*}ea=!SmUos_qRjhCnn#s2i~>xtUhX^!aQy+nuv)QcxA3YN|9 z4)OWY|M7lV)PU2AGNzuCKJ7V$E=0UjGhmr=L<1D8HXS^VQ=xvA8}3$0D%Tu7XZFn# zrH+fMM!!z&^31Fb2J10k)%{kn<34Y%5B13fA2|@dD==jrpT6IGhh9LLSUFz z&O9h==JZy7G5;S;Ul|o;*S0;>fOIo--84u@Nq32~ba$t8cbBv@h@fErx z5X$gPzu&#I&_(&h5-*B??}B(EzlZLKn6ck78NZ&^K%Vf>xrsu)sk>twce?P8Q|`aV zuav+8`wd)$CwYPx-t*#cce4ZuUgJk2sZ!ewLbp+D?CR?t;jkG_rN|?vHea^Ix`PI* z6dFt@7btP;e{UP}tz15~xS*n*3MCJJUI`P@+YfgD4hRm7u{qY5jgy7bOC~k z8mX^P;Mt{*bOxLdNRJ-2Y14C-V2>Mlgj&^)qw*C9MwYdy88Yc$?Q+^(`_V#Whih6% z?7n^xK&Y((6ECRMIcv+2_IsWv_vNp}#Yv?fUE*cLG;K(y$(aXU- zfY2&Wpp=T-U*u*P?-mr8zgI$a_$3R|IQH{g%nq-LaCJi=1xdZ39FOK|jxYuCOW$T)cEc1By}%aq;4ki&;# zDRKDtF_LagSHg-p1IcC`_F%jxfB^NRm^zU~hXIFJwF$|Q3PVDVneQ$_8V`oZ&|UPP|Hz~{X5 z-{CM+3PU=7@X+Vg_s<kDehCHfrRU?>7zryYk@|L?SD)arAUUy8Rk{h)HU2$Y3GO-%(iv+a8|LjJqY zbnWFK(982n9(^&Zf@JMHguWhN5k*8is+MnUO=sZg`uHMrcOX%M4N-UiT}Q+>{aI0o zm#`)C$cUOwV4478!6jzB$Nt2l6sI{I+~C#e95kd!X*H|$Zw806ajS(3WeB?m(un{Kp8bD!IU`&LqphHw|-!))!BYghmyi)bIpG|T2UVeh*e znuWx@$QNQKz2)IcM+95}(SSUgZ-T3W(82>PS!uq~IkL8W$+wWT8;AYlk9^ZTmhQL5 z*5=;D19rr>oGqE)uOQI?#}J+`^bXVdI9OivAo$MTqnTgsewLo?<)e8r*_-Zi8TnnH zlyg=1>-CSeT_cv)Piq?J8v)%rpnZzc4`Civb9!3lFh5PsuRnE50e|0a;&r-)Ts9MY zD1C>7nkL8V_m{q6ttpPpI1dF&nQn1D0If`EK<1axJG63ym|fS|(sVl8s$*Bi^K9hZ zZdiYv0HxU+5Op1?$r(L=n5Es!upf5dO$;;p+^+OOYWI=HD_j~LW z<+N|z>!x{&Vw(w#NN|QZUHB4$p`RHKqkLzc94}9j5@cC6=?=x8e(I8V(j<8_zu=p~ zfRrI!Zd|6Nvnf(}Q;vDFh64OiMFO7W zWfblYL3k$UukUC2;-OS=WI{nP3j!{g0YK3Ezy-Cm)5&gQi8>SMZ%VAGQ|ge7dCEFF zF^C9~W~!8sK{zgWrv~Lc%>jGR_SfKkSjR!F9=T*m!*6<3(h^X>^z#sC@Wi#c!OzeY zx9H&&RPgyw1;2!^*lQG80G5^|bBROd6f8DZ?HTwbT)N3j`s>nWD3ojs?hxv2@gV~H zfKLWxKT}_|ZO~p!v3uxe&V(fw-T_P+EUZ5BPk}~veMYDZ+#I^C>e%;Q^^e^hC_PAb z6)XK?l@5kxenm-Nis)`nR-qigw_1|Nf1ko~PynwY0w$7^)7=XL)@qe!3iYZ7Tgl2W zzA~;XqnUKPZAQiP<0yzgaE9G zeqw4*fsoK)Yr=&IgDzmKRF?PIWmIjZ9woE4>&anqi}zoae$r6M1&`U{CsRs%?myYL)?3tZsdNsXrGJOPQEC979_!oy}1%)Mrh4b#KkKEue=s zn1K!dFl^?JL|cgae?{+w)jE%aKSs;HpZVXA>X@^9u6X547;N!GeJL|14A=ADX>x1C zO}hWrh`#hK8T$$SY~Z?7+G%4E_Xmw~sq+^OEG(`xoX)P+@XRALOLK{Rj^G<-!b0j3 zgzsr1W^9=VSjt|!??r!Mf-4BRFd)av#EYp!5+jV!34nHAFccVr_16jd@#i7JMK_K# zB5L+u2xcJ(vq&7p@QYdA zM`@{9Rp3AsDhnv7qFKp=-*)MrTjJ1fEq8IFbCNen5=;|l&?oPuVC4HNPL>jGA&?l*}SYK_s& zlt#twn=Fap899@S3l%Cez)d7sH^8@NdZ%bi#i$1_S z2F0x$#@!6J55g-VOR-%D+fM^d_j4w^ z_rsjJ6DMx2fPI3rRZ+D-V~n96VI|)M;&BRl`Y(h@61~%RqL>shVjejQ{TIr^^;A^L ztH-AEa9F;I_1|IOp@tGxC6*XRjQW}1BlyArWWT!>9(_kQrkVSgE)bt7zxzcyKzml_ zlj|)xe}YKw4-mZLn>pN_gOhQ_v;KSH7Q2DSce#Gzx2@_I1{yxm)NLI9~rK~D`ltgvn2Uyt=9Oe*!TbX`isS}TgJ z@gO2p&dWXl_1%R`GM;7!>;|&|xwM1DmO_TqAq%JTUP}26XUM~5Z28x^Y0Fun^0)iu zvng!YpM5t}%rKOwj7K}!YMxg$lC5(F4=U!-Hjd$YJYec16HSl0$?K+@6a-#{OKAB! zN~Q9;SN&S?k0mnsOM;C{#yjc;8JHs6xptm@tZ9Mj$h3)B-&xg%-E`J#gL93-$+*Z*Dm*e^&n#X$}5kNb2{Su&bsk>vP;O zUJ}DU8W|ffLl*xi;xI+FBFi%cm=H==b2cttv&ACSYxBDhT@3Uc%OBk~Wscdluqd?s z$|q&Mr=DEl4=LF@j+=TB+S9@=4(EV)8kx0<%zvX_#$GSu@nT%0G9VFi`f4d{MqhN% zM{a(;p?(SXL&D1YWWXVhZPp7@AWpkJaN_M0E?MKdJ4K26-zc)UHX*cuPqdk#>O=20;O6GUN(JU>>vfJjuXbLiWp zqNA~VM5F&Jrp-usWmjUPFMaYi12e_CB#6F{ufq3LB78{pg={w{f^a6jXQsUz%pJ z6708%SQlvN;$1fUr|UVZ|1#KSa@qfO0-8gG6+i>C%CGlVZ`{z$54~c~X#H;vOEBhaMVE8X+Wiy| z+TnlUM40>1?wMN_#m-2L&zXy1gm zmO&hdw)1oBu&~&C9GKIR+?itjC0Mp~Tsjc`D)P|$uML;knI9J}(`_^y@-*cvbPvaG z=1pKl+hABHPz!=hxtT>!%xftQB~k14&BQ2}5aRFzP#vm+nhZa+s*G+(H3xp@_*Is3 z%-MmpvGRmb&8B+d_T@1w88$QvZ6Og!ELM(X>lRioc{a6s&N>3)?UjTPwPvwC=uf=j z`WtTahcS&x)wdcG)BSy(>2K*-L<58Oj$#?Uz!jimWmnZ;%67Myr|(^JdQl`)&JDhi zp(g*}F{D8xSce`6qQ~1jeeu@R((4*LMFZ@$f$k>|eI7xO>}aJokOqxOlRB9qu#U&mms~OMnQT7YFasLcRLgQ^V}?eeCUy@` z8B7fYMvj$R)D}AFgNr&~9SB6=H-d-S(WSEjP`WY1l~ROAO?ov3>h-u0;;vWznAF3l zVUq%B3q%&PMNpy4MIj11c5))Og}|^%NMv`4M3a4~fk$@pj$O;DPh8z{A_r@)v^k^f z`8}|!{h%oOdzVBep@N*n_h_8ZcXj!ZxRQ)zYqt&g@W6ITp26ceFA61hRGfYNqT)wN z{{p#xD8I((*A~WE%9qqBF(h_OXfmKs+AEPUvC5C?dmwr4zg?ruXK(tW-6PiDW!fLe z(pzifLm41qGrAzo{D4K(UK|mz|88K49&JuZe-|=x)#NHee)PD~+<7R6j{Kh4$`BP( zQgM%M5qv~5x-Bj-OZdX|rz5&4HDJ!XM^>!U?k;}WbVJx}ITM zn;!3bWe6D~FRx2MNM$>gk}hQZ>U3SVr)VOLH?sNDLp^x>WtSwCoYfT=y{JMiy!PL4 zT@nH9&T|R;J-@3G=)WGc&}7Mz=6AjR;ciAMy@13e(i8%s;3cnsft%PEya`yAoM#@L zNx*kB88hHWk{c3!SeRHT@Zh5iL&)AT8SnUhGe-(E8)QcYdG`vtZeXgmU-B#B=^SLH?iiX`7Av#auW+-jgGgZu#RtH3iGkhmH(QU*W6_R6*y zsPiT2xWL-i^ajMt_ms#D1Wyk0VzJiUI9$`;JZ^3%j|Gz@aU~*?weDmComei5T~pGRd_?o8W&iYr%=LEy9R#g5-xZVeg2MTtRqH z6Cts9j~1>p$DqX#Jvu*xh`9gU^4-HGmBdOiVEv%#v4@T23Wj6x(rlr`$)At>8R9I6 zV&TslvzhppR+nr&vya^W0wyRdS2IH*TZv@c#P|(jemYL0l7oyU^weX*Jm%D9!0JLm zeD>-t+&vo^9GQBwKy-i2vsZQP!7%0gOL*r>Ujvp!ccL$_@X2Z8UKBMxh0o8g!0+zs zcn9=&i>j{CEjDt{&V$5!08Lg`>lbunGO*vTiz+> zw7s;8C5Q2ReOboApV?=>2yzkB=$kaPEuECa?t+tHaa5ClXfg^~jN`z%hPQF-{_73w zNc1+H-u?`)qwP%nvRM%#Lc*@DU%?PE!Z7yE$7Q0^m9}8#=9P@RXfp3)_cFc7LJ37b zxP#de<@8hV~nQr|U z{PUC6g$kslD*Ub-q(?9)Pr$Y)uVe`(kD1ZflXgKdDXLl;X&E3;@>(_OL zqN+blL34d64deGuxgGI7>=+{rM$O#13!w?H`n$5b=2p}?%NQ^)l<*|()O=DhFaxWQ z=v2km#(AOts211y@#*GntaV&vCBt(RPxfu2>+aSF3lNWHU0DSic`6c{&`Q=?a^O)p z<)!t#FEYQ|`4scx-!gT}yJW=G=P$R!dpRm}m~71*Xyt|0G0S*+I}xbs`2Pe=1x^|l8k7Ha4OdT;f-xP< z7O6w7CXABKVNR~W`=5wQav zG%ARRanaSRGF<<0nNewMpuLue*Fw0bGkF6aZT%JXc(Kh{;~3rtcDWetiVQn_?xHE| zpK+g!-V%KsKU_4@*hopn###(~a#i`G3Rk*LR}@xVHp{mL3p?FFQ51wZWczF04J{-j zArrA1IbZedFjjOVZ>f%dqCk?LY3#Z`)ogQ&XHA0kYSmX~aF3mXBWPsZC%CVus5j?K zXNu+VWA=Cz<@pcq#y;02G^@s5gZtRei&G#v7#JhF7d?k(vLSsqCYO;W&kG%a)*Fy@ zCR0}3uYpsP%;K}wh*eJORw=K(bWosG z%*IxO!$7iSu-z@eRuCIeVh3#%tVj+y;~(73AwJ^**Ju$>Z!GyTfR3G*Nk*3khhvr1 z%}~{;f}uBdVnS+Q+Pl2MF(|7trtgAcG(4<9{ghNJ&rf)P z6AUTPchgR8*eeXCs%%U)p>MX#rAm~jc<0@&zhPSM+XVj9M#;M+?bY8>N;DPnl~<r2PnG=8%tRA2-$d`@SC zj{V9MLgyOgY5N0&V>=6weBq?;jK5yCe0>Ci6UiwoIVxae10Uu#Wj9&@59 zEF3OB+FO}z@Mc`o?!#|* zk%c(r{a8p*WU#ZD5fz4mDL=Wr%dts{qY7bJ3)U{aTf>G;VDVe$Y7=1n6aqU zYIWO1eedr=xQQS9Dyy7t&qsmzQC(Vt;vIvL_fl*?Rq-2h5xHoDhgtE{!5GSVrBxwX z3Opr(Zl$NNNN+5My%vJ56?dztbIe|W&zOgCG36rWSni9R&KwD(%{d%)WnXFy)e!NY>)7A_tY1Mg zl+8$BUv5(b1YpW6;0GKEQ+)f;O+HqQ0NexNJFer!yX*vR2|8NjEqQz)qm8eBGnUE} zSP``~8xZDfjjx;2Z)F#{BgdBf!iHaeeyFcSp`5}+L89nDCEphcGHG{ z1`IrNdYWJ3grB$jOvlV7huXFuqpR0ipRj&N%13~WrcGuuL`1Tr@69hf>l0I~VxOmC z-})6`>I(MCEi&uT30J@92_iQK$UE+Y!|Dq8*;quL*fNr2y~OZjs44yZabH6j9lT4G8n;cC$Y3>%krH0Xdx=>OWPZvVB!Ux=jCKgSOV%MQ42Pk?|im|Jr_ zk9jFLF+#Wp(*$-UqUcx<&%!cBjYm!$!g#A-%#be>rC~|lvnU1wcq`wX9>KJwPd25= zGC1!4#SN3v<_X)@&eH1qS8=c*VRrgW}&jyskJ3qvc-33zo0!GTiHf`{|n2J)V?+6r&oO(G|d69 zT_`O{<7b-^laNS;t&Y8(NyS{;lOs7VJ2QLpWn@KA*s)!?!kaH#g9-(K)23nTe}``= zndmI=U?pz7&Gl^w8ta#nGVU%#5PARWr~;85QmbUYA7QTIuV=xJ&87k3DSd(rqIi!A%f z^)yS20P%N`Z8J~UEJ+btP9%t`h(DDiA2WL0Xkau^DL(aWjlx#=dLm%huh?WX1C73t z1qK!)`Db|x6_9F9Xt4f~9a6YmWDIVTI$#RQpTt+9zdoq&ZGwxtApjHHZ)@vd!dF9w zhjmlCC1Yj6zX^#)p+rFL5kEgdyLXMV!Qtu=i561UKz2=ewtX19$6R}@b!xJAX6iZB zZwVgB)%^?78}1$yA)ev%ZD8*__JR9z@S1p?yuHNh?9AF~>s&f=X3!CS<6b)O3+Of&kykf4%v!IJMnI(}!zD4tZ@!EQo9kJMlBQZwQyyow;KxPa8 zXZEJJ7|_)SA^~_nrBb2@WYMwB<5xv=Y7Cy~g_;yH$+-6YPwPeQe01!R1ycAxgb{U2 z%tetizdll{;0iPk&gT=nquePa-0D^AT(nPFw;_E zfY--XuE{B5I&$LzCj^qSdAJsf8EmeNebIfhMlbz90K#!=kpqg;$Z72Yl_BH7-`x#5 zjimh~OSe^>2{fC?d0n*RuIVb+a&4SBmF1^uzzl=x8t!7MY=v|pw2kum-v1ZUIn-#- zRlN}B-ojWX{^1I3l=Z2qJoYqizH_E2LxxZyag$7&{jW1vb%v6esablfNUl!CiN0FClsx010dSG+E5fK{U1Xk^R4pv!+C9k!;_ zhzPG-b!6hR(%Uun(OLOfA~+T|LTL5Bi?loEm*8pzGEFBWn2i&u8OaWcERKwb&iG&R z>RnO%`>l(YfgwDZNTSsbQMs>~xs(QsKUDm1ofATr-H(9>EP^&_iZkz1u(-!jxHLO= zyHnfvO74NwO+?A({`5ufAexU^;tkbBNy#aY*v?ei4VkY>Fo`aZGD(&+-R~3 zv%of~1%gz~cM^$t$D``*)Yr0dyk+y=`L*hoomdK@kr3UWZ) zw>}G5LCPeEzQ^JKa21Z!QG*-C<`!##2k*BI6q1iFxIpXE`dEgmKonrowZBlxQ3LQZ zi?g`r^R@r0OUw!JncJ6$@56W;s}-<7?{nK!isVx*Q$U})obZS_bJj=h5TDaNN@6H} z`f^gJ-Mf|cg`#1AC`JKO*IZNZ4wrqg*3{7kHd=u~jh&%2p9D8xKA|THDqihkW>}&b8DP(3KY@>M$S}6uf+BT`Oi_COCqljwy zjEXg-U};iCWF^lF%h4~l9tOi0m88hI7_z82$PgMbPqgePpHh;`fS2F;CrsI$q}zIW zolRuYGEcq2t-@KtHzp7tu0)A(W7YqGtR_^~*sOv%^!~DuAdkwvQRHRdCg9frC}%|B z+@7MS7vOLzI_=MHN{oC->@IRigZYcYk_OPtq-*C$ZlvHE9oDDTZ@UoECBY+qe9ewzfVs#F;T4ffvRBDh;kOvKtoHyiPmsl-?i!$5>e`7 z6|m#-QJ!2NqPm)WF%?Z1>D=R#oosBp%c2!QdEHvgT2tkUJ}!B~Q~-$*sJ}3=0V6(o zu|jQePct-am-h+u=wKkP%l&n0RU(*~Y_)u=zX%ytSiVfYKw$`9mqci*XKTiOVbT3s zWJ?tP#u?53zVEDxw*_4Jm3yitGNQzvlL&34>6yhADq5}|j0>9~k8cDqw6jA4CK$RY z)>tYF_p?={zXw{YnPG6?_Jv-u*%rN-yRijFEKiLDuqnY(hK*rw(u-G8#@>z#p@!$= zuF=ypramvIKqY%b#v98pC(;e|AuCpB56U;bSP~xbAp40yCMIOiIR`~^WT92|=U}s( zJwoy!pZ*4dH$>&$LP3aOpOkYN!7Si*Jahud@@M4EK{n>+I8J?a{!uR#h>4iC&W9Le znDSxKFz-dhLY1|3CqCD;J|Mk16v+-$jEZA^}4mJGoGBTDxw~GzsEOiE!)* zVb|=%3zVpAC1whY;V?mgOjy&Fxzg%En%nWlP-one1oTR#i>YHXyyMwj-0_t$?Mh=P z4+=Nbs>*6CEfu=&qP5H8C{Q<>PY`a^f3NUoL`?53WA~Vl;cLKJ3f|{~han|Wvr3PpTtWmh9dj1iIUMv81+ZZYuqUe8vb*k6)kHrGGkG;p77atYW>>O<) zl;9uj%SwY$@QOyFbebXW^HBqR=(ugCN4~hfpo$u}tbU_Kf@7|HU#!VQRe;vOa=sji z4K$_}&XTM3H`6JnD2B{ydHt>}XDFig@UGAmWD)&<+MchWl@%Uc+~)xyAtZ6NQdBVAAzlSY>W8R0Y(AFejK~+0 zyqu1{)>u{P=%(irK5N$sQ#vBto+9ka=KHQ3F;G!Ku+O+y(Xa&!7S@SAYF(ZM+1jto z{vFqJy#&|sMC7dgG;>L#=tMBUiD|Z{lgT+pn0vGLkBZ_!p%QcfJ6&1aP%tCrdiq4 zEI}fV3@SG^Pu3QpDXR2!IH`4sLuQ6r6KB$-cfTL)_nTX_`%akd^4!w@WPCH@$5vkS ziLkc(fmH6QBWltQ@wpmW0NnnLZjVeq{pG+H(4a!)I&2RkzrJ;)4hg7RUawtE#9k6Z z2lml{lm2|L<&hQHStADWFo(B55yFuIaPWoRiscqT-J;83kb8k zqck`iy}Q~DY3bErWq3aV=={o$2b&G03fr^<^MW>bMM|IV;!JwRntu8Cjnn`Ub5-*t zoPzIls`7KzXFuix1)hl0kHyO-pQ&J#nm%P{x;)qFGDPbxXjY7i{+7v5UY-D+b~n+mEltPSs+1QY3X)ddqrDJv@JVg^)_z%dZjAu z5rxKiRl}?gf-h~Fop(1cdO26vz@_GQhnyE9OZueY2Lw(jT4^1!Ju^E9sJm4&T&g@U zqop?8zYeLKZ$aHL-*Hwa2$u+>2OFZX-crCOhH2fTP-<}x7Cz4>G!>ow0xO~{gjVB` z2w$}TD`vt*5E+QvFt}&i>Sm0jVP9_InF7!wU*01_F;dyUNYvcSkpSfhXbF=$2@>=} zLPW28F~jNl6QbFXP(iVO;)P$g?F8C^h5=yDy@cG;!=+|J)=lvsi%sMRdq4Ab%bGxL zFNjs2Qo2{ULH_!}3Nf8Bsqr*?OYST`8jIJ-Fc4L;>3z?04(D_6TAbd-19i&=`j!J2 zcx<{~4YgpGA!@&|P6f)0+NWBKOhPxY8y*zAw z?y!qRX(r`Er>uhrK|(M4sy^P^+KhXZU$l!6S-m`;9o|OXz7IcGkX3H%`Fj=}um_TN zUvN~@hCuPa$YK&>cL8{?#eVm2f02g_f@8HwKiv7RUN+UI5Fv|~2dgX>)psqc9GxI2 zwB5ZAlll;uOAe~=b3$;hSaI+gZ7Xe5();X33=g8OtZPSPf%Z?;76Z`;%hT2)CO*PJ znHR<41+KN*lq9K51S-YCd^Ye{%0EN`|^IzN2iL5klB=f@?Q^BPPib3?(_*ifz zNl)xT%`XjxANB~^Z9QYyxt&ALPP>592?O{}7hQOe)oj5Nng9k1(kmnM*t5?FDwQQq zFzWN-$AmU7=u?g0!ZiP5pI(-WN{gQfoq+Kt3rZfK~B zQUn^+ziq}eiXCXTwRpV?LUeCiERu0y#SsuIvmxD~Qdpl*NS^Ptg*~@i3KxcharYm?SbCw>eYX6L6a;WE`N;SAxkoeP#fn-R;nn6=-e?4nla;E z>0m5C-~_U=dxn?g5N)I-CU8KsEQZT4rqQEn+}s>Gyr5H5%_>PD3+ipz*^LmK=>Ova z5Ch+qw%~q#_()U7VBmgV^SGl~Sk;?7iTd9i)C>F)RX~zq*2~2a%LlEx?bjRr`wfRR z=@OEr&^6>b4>`HuX(dvdBQ3Cw(ql}QGyp6B8^obS563Gm8TJW7R{mI4h`;wAZ{Qg* zml_#Lj!E>MkJq{CTnuQ~Gk@B+9hHyU zg3mEt>C2gYMMpN8EO+D9e~OwxJnz$#ORv}b=G(x?ICs;C=+nr1s$yklxf(#X%fy6CTbLjzmS9hsDj|`0W6E>p8CacSZTr!KcHXo_dIffw=3oTq70!g1NLWQ#p@f7 zp`~_j<(R-3Vxf=>Jh#JVotsg|vjB=!!^OswxVbE)T!2-zc0z<3`9LbKQ&WUZ8|&R&2py|FY<~eac2zyDJCQ55Gq| z0;X+V$wz!1SH%uSKIOu27u!w*Os|eGQzFUt8dWpD+4V{BGmTU4z|r@1`+Oj}$YH zbPpxbRoB(TSl9E==|wz7ZYrT;*%hQWIz4J)xs%ORRUNyx@Cn*{HiKABS>#~MnoYh} zc1UFFUeIAbd_!l&EQSl2RgOSRv+`HI&916OQ*hO9qsR-39Z zVePqtFJ8Q>&n@vqgI~TBhysWcnHq_k<1M1FL_@;oveEjYFVByaukUQ4Uz)>9F~J#G z@s5H6b*3%J0G-(H?u+iz7ST7k1Rbrri>tRgRp!wOIyI`3bj)1bV1apvKRwXRUt@^!!slZ zkdJ5BV6m2oHMu~);jX`PfCcMa39wE^hle@v)6&?uIhMc5E7$}NM5C!40mg{1+(8T+ z4r=j+#Rl;$A@@v+d$G>1l$>s#`pZH?#-bh&K_>!#_D|9b^~Mh^TXxMbH>x($RJpKfk{MWzEXRj`Q+ zC1G&v{?jifG_*^AWif1mL|F!eBz8CQIEaydi~?$|!OuiJ-=4?H}VJx_gJ=2Xl^VghpWL7Rv8hjtIIO&CBA-Vy-_w~Xu@b!V2yLr|1H3i*& zU-hRd_yGaop~Yy4tmum3p-I4T*5OHpLBlZ7(!B};9V+w#_dEypoFkIO+LWb*8rdzB z%jdAt8ASf$_miHj{6WKBV*#tuZ-a)!0PwEEChxF9voa}&;7P0wVB%~x>)qub*)sNh zwNbdQ_tEQ{yM0HIDNAzX)iE}#h{PO|`P2Y0Co5)Mwh`u@)T z7uU*%hE*#{q~Tf~^zY7@PgTcZs@1=%ZXh%Mf!iUzWXV}oSC_0w3e2(O!+hF;<7?qn z)AIw3gs4A8&_jQ}N-_WyMnt%Ap#*epFjH&m1BOVTDG&#Us69UHO!&z{w2HlfHl&Y` zreM$1Ib%^2UvVi8Zs7`e26Ix}YaiE$4RtL6=gbJro$BoH|27j=^aqrGGw281@Ts1i z(c(POozLgKff}+`+MHgKfQy8@5>+NF?G>PM#N~Vps`fRBOcV5W2OG4$5e88#u_P7H zcTZ~vY*O;vS}%o$BHRl#mQVuNNr<)JvJ=tOgS1Q2`Gu!$ha;NyoqycjpK2#4d7#7c zAdu}M!Sc}GNufV52|{9nh~oEycB~`#F-lkX0{+d>%AqixX3{wmi|UXZ*e?Y`FIriC zrSKyP+@E^$2G}8*e+}N!LAff|rPJ;m`)MJOp#PR6zbJp8A%IHd_ zY`Zb3+6=n7D;S&Th%xw~B%sFF%K}(iDX}7-;rbvhGys8gt|Jg%4(2EYQx1;F28N84 zd-D8CW2q#7|9oMz6s}ET4_j)81j~p8;-7rQ@v8bXwK>EJ2u9kpJFg?f7$K4l9@MwV;ob{dl!cRnlQbA3cf(m*KC~;L(0n)mkFI?{1sVXxobFo?} zTDBZP$IlPY^<1=#*P9R5N0Zx6;0Z5ezq-<3L_*@_s^2sdpO~h=ewn* z96m?UjC)ogya!B<7wPzU*NF6%UyE^p*rZMU&~zT2-RAXiP%6vCqvBd`d(YGN*KEv! z2Zz^{j?yxX^M$utVIxmpK&;=KgN9esv8-5E?~oaE(8={){#kG{WYW$r3~d@aUC0xX zq`GbQX2;YIPwIsqqFEV&Bn~%W=POi%tFEpN6Vc02=VJhGB42hHdzk>=sq-l;@{QwSo$j;zb725h57R#O>)-`zD zh?}U+Uz+nJykh%a^dl@5KnE~gzR!_gO!R|Y-lwzNao;Dxz`R@7*L>6EqA-c8PgM~gAd`d&F)R~KMDfj@#{0)+e$F92BD&`W^_QP<=*)6$48=-2={cCz z&}ZJS!dq<#=f*_x%{(q#bkL1VPx8I2D~M2^;+f^d9u+;?)nARq@FmA;A||j!TrGY1 zTWmlMnuK94G+Ev54#~D6fFPLQO2k~K77-;#6~B$E0)}5@()o785Y2;yA&~aI=ER3W zxCoE5wejDkoH6exC63CP#X=IggRl-7(71)%Tj`Rc4ii*dcN=GfD0JcpAtw&4b<_4X zM4j~H5mU_H#9&l@ya}*@LZa^c*ePSCO3F0=_mD_m#Gz#NJ4dC%*NNjR< zf(cGwe^Tw2P*P6VTD+gZfsvb|Se=I^6XS@w7x>$Qu;xtkw!70~tLGKIUZ}NlM}YXa z^$=KC1gxAtJisdGGg!IF)?U$NYh47tkD$i_wufrlQ)?vIJv!@s@uCCCRb z%7pw;@RqI^_E}a>JB^H5RQ-1uYY+8N+6`%Sa;z`8>;dXybVf0!qxw2xUW@y99lC+1 zeIJRpDb9%x=DI-nXVll?ni3QB)FLv}XvEMy7Ob2r*ZvGG|0=+KsJ5D|T7h20VJng;URA3Y0;P%Uf3zI*m&i?E~LSf`&oA`|E%9NyvX$_w*Rcqr2=p7AS zFI;r*_diKMWv(7M4)C^OGC*QtHdBeO$yM2!X#tq93fvfV?D>s$?BK7tq}I*ACs?+6 zlN(t@!d1+u+fr<|VSz#%SA}BlU#N@z%bUsN#Z`ZQTdj)i$5w8 z`8H@ht!s9qJZYz^ovBSZx%v9!CiXh7=_#7hy}h!lc+P%a5y2DFsbL?b8Hh2>o+nyC zF>xwov1oX!maiU0;c*%NTy|QM)!QQNSCXVwx%!%l4u|cCrklKPRW{wye?`2}Icy%Z zQ2TL-h*@B6oTdG3=W!jTeevJG^;k}Cpy!9&m zU9F-J{%>oAHiAl+qQ)T;>?(`K&bkrpjs4-q!QjME>{u$#` zSpyt7XGj)_mvdkae;56|55>fuNBf&T{Y73I1)>AsNdgz)n=)c83W_O;gF}F>u-bVR zJoWW~eL6w+3)RN*DS@P#s+Mn|uO#pn$=EuqsbiI5){k@A5P-WK=`EWs+2iBOUosgJ z6x!l478;-x?{|dg^f^!T6&?&TMa%!k50tazSiz6t6V4Qm%~?9&S!0PF6XVgmRz@K{5Df}bwi0P#ZuiNpH5 za6)o=q!2(?U~#Rb9D6*&01~~G3PqzyQeZ=!YAdePd-=dSJ>FpyCLaZu*c79e-06>Z zCC+0NaBJ>)eo!x}mux#Xz<2GjlHmc=@oL%07h0)6fQ-YzJ*nebTWI)Nu;@2bfGzOnu<4;{ z@v5ogxkFsW;#}S828ZE)6l(*R7N@i<&V_U@Q#uDm48ID{siBFVr&W=wX7(@r2J%k) zBhfk(ra)&jp02msL$*k%V$B$%PtdY>RF<hQ1ePrW`zN2%+Kf(9Mrit05Hh}?aL6}Z4a)Md?l@|PS*>niOkKl7~mbe20Dm( z=rHOOblP=Xc(DWL25~&68<}3p)!&Xpf~N zn0sEgYM)B500qXHzw+qb-j_Hr{6X%m23f%g!@`2zKO)NtWX;|Dj`0{I8Jj+kV-nIV zgs3bYJ2`Gn$s0L50*sgcy<2M>6FzieS@BDx50;g_5A;>%3Yo=nyA~YC`76?a)ie{D zU_eWn&L_a){&L@9xx`~T` zv~xKmU#5)vz>}a<{)64DqqfO9@n|C7|8~I2cY3mgUD&!L*qKN>|0SpG!SBmq%PI1U z=x*`YR|HFB5^6~ZhUph(#VBy{D{q_y$+Fy!; z*FZuC7hHKZ$2P3fegJS&WW3mo_^KX^U)5i9bN{jv4l(rZ+02bT*7cJ6Q9|Vaa0Lr7pgTir+8^K{9BNs-o z0sNAG53+`G_`)eW94#Uu=mtBgv>#}7r|C%$d^~?RpK~%)sb8*7203;7jIj)@_MV|) zXKTwG8?{B?5`Vz8Ew7&$D!hq}S!%l7z!7{C#YVKOIc(Tc6XSN8C0*FWpri{0*+(?b zM%Ccni^0!F7_;N~%MgcK^JNUAx&p^;ph+QsEKPRuV&WBBNaoJ|L6fpfD>%UkIo8Pk zfeJFSL_j%`-8P55#-hMeiw7`c_%K%-760Su0iw$?WLlZRm@q2*e1Y8ig zu^92jmbNHpe?_Pf^&6vxFSWTl>iUvLXI!M6q8Q|En{nG>C=9`f*`w&d0TSr2}S2(jia5D!6)oLY6 z63WzZa8GP{B0Aqq(s{4%M>yJ!tg$qbY`{{rs~Sc=+&7wi#2GSs-Si$kwiwg8f}Dch zDlWTkGIh;DzWH;woc;2{9{0uHtHvCi=9XyQ(<}?f`wY2axoQARS31hDs}62#*k3!oVuf!H&VmtF4i!YSpK6{SzwEc>Itlg^tI76+MSqr^%-jE4n zpLBPjV3}I`A%Z4;xQ!yJ3D{ureIHSfYix17MyudtcW)(qdh0?BbU;~8i~zy8Xa7<0 zQcZezaO+KqD(g2vm*PGo;Utz})vDvFrP*AELRy2E49t;;B1dhDrH$##$Ob%QUB6#v z+hEFS}yr$`kK+gAVyn=sk7-UR2k6CXy;HYzML6|eP zZ!Gs$8C^f27c*>;$q0}GZVs#7&mTtIaNF(Jmwx%j$D7$7-0Y7b1x=}nHL#Z$OWXNB zvE5{djggCn-jgyhZGmaHUkOC5c%61F2WKT%+KoQeV^Di?qL?U9FZ{shRd-?tGg z)^8-Iotqb0_6ulxR;ft%%)w(c*yAAzozy}Jc6@n5;ClYPUy22LI!WRi`onyO@KV$` zoykW=S0og*2}|ShrW=pt6W?iW2Ru))06j31)r#}8aO_Q0lGt*$HnSs`GJ;rmyKcKsL*z+0XgO?sKXS%%C5cRn5ul7H>ppE12VMTZtz;lowz=ryrFymis3yM_e&<2q23rU8joAj{djbkZ-=J2d}>Y%lzL zTXV_pC!R&1VAAxv9$N*S(tAj`0?@U^U->vfyF{*lEXh;qm^9njh z_uxtt!kva2VtT|Oa@)4(L@LHmIB9?o-dp4||0bf(Uj^=6vX~R%-t1N{ljlbivSbZZD8M^fQr;-sf#Ek_z6-JE_}Z!_M#nTjEYK+5;qPA6l+T%{uB||vuRNQf1Fa5HGOvxc+bj8x3gfT(w0h1EcbT% zGc2mJi0z%=c^@kDSlJsZ&96FWCF0f?Xar<-;7L3c@GrH#{C&ucao)NcfIu^)VpLft z=V8Hc({xUu!Azfqu@YU|Ki*HNK}pdyvEa`2AlO|fl`}MMty#n6bYT9g7 zG=RK!?OEjO<^0^w1vA>BS7O3Q)6v+f4ymW%pzj%!c;PsH;!60C3C{6Li1&GpqysG4 zk4B8Tz(ALUPirf5t|GHFMCw(>==&5-qgYW(b60pbk`)B)F{3C^OA8Z{`ki{EvC}zH zL6-x6FdUdhFF1@UYOl%xCFg#m#Q68V5du)LHhMa1%)mXrBZ$eAI(BNLxAK?`sIlcg(-Z|)Pfp565(<1Hc5(jHB~9!~CNLD<-f*AS-+%Mo zTIp>pPMJx5{c~O(5+_?QDX*MYCce+p=7!Z87AzRu1Zj&AVK1`u_SFPDjG(2~*9t(o zW1PRv1_q}ZTa?ZX2qPuEW5^Ws$9n01xe44HD!PL+S%gkh9Ycz0BI@gx?-k7s>Nd_z zmY>dOe%_sO+52Qp!AmI;YdvmRY;1mbygO|l=Q~=VMWlQ88> zbh+8H(HHdCA3Ip+FQln98^`!(Prtvy3qftLi_%QWwPRf8_lq2zGPF;e65^jg0OcZ$ zAdUyYCQ!$?WNNG?QpR$eNkVK&#Jf=IkSVwBvg3VtGj?rZBpp%)Y!V81;pxv_)aH-3 zmG$9hwWudkd5Z4XGQlBQ``8x;3N+E1fdT~Kk=^zwBlM`5cv9xL<{;|HIW09}n&>Yg zTuVei*%%WB2Xngo$lN)&lQ`UKm20E@WgCl>^!- zkxJVUH~8$vX|+#Rt~{!-^+Exu^<*`+?e?U@A8&Jh`eIFmus zx^(KtC?Dk%=|Tmq@(=S>X~FM_EuG@b7Ns1B&0S&1vGef#|k56mQ2-y#VTtmQ3gQyfH&^4=K2!KwsLE~M@DsArY#VWTkf4Un%}Q&%BK%v@qHE2Uv( z9(c+|mSS7$XLp2%3VTULZsT=P={ri*j!GaXpcyx|h0vtiuQliH3H=`zfSj!JN1p0u zdVOR)bJmPeb`<$i;Ig(zijn1PWysIwcMc|OpsU&qlBrG_{XBL{Vv?H7{UtL0swRHo z_;*|^O12M#4v(%ZndBaA{AHb$x=DNRCIE+u$*d8 z3|j1GQsbf7BWUynoR<_r6LFF%pNLX=y(3`gv)6#kI+4%AUTu{FHSuU=tRrZ*qlsR) z8`jO!@08B*Ar5n;sply#=M1=6+0rqvFVtdWXnd$>yBo?83pH(?IsT3T-KZv~^l?S@ zthg0guX{S@P>>0g1GuK8yDS_{wqGOFi<04SEjKlFdEp2>WY#mz^m&gFe|!DHC$-EV zz_muwE6h2}aIE`ru~O09P(tmzOxB;A3;m)NHh1l)U1o=o*NIsZ=`$^Xs0#!jwHn5* zC%RGN<3sGB}0Bj>o?9KTmCue;knN8Os zYf4_L!ggqUn73-+A*jKgwuNvq#=^qy(BRqZ$%>@xj2VVZKETCIA|mrG8~6RlV~y7N z@Uvoy7SW5f$oDeMCX=nxD}Q|&wOBOPa|f6wrSP@i89)%-CU?e%|_LV4dz|IsSNrp9u4Bj{er=Q z|84da+H9v?$1{+U-AVdbsGGK8o%GGW^gDGA3YVp}d0RN&{$fk|oVNJ-^JgL;ou}>O zey=GPUhV3EszzL6CL#0m8IMV3Nh%l9`71B2;yajOf0V|l+3m72{sj_17OsPLXS>t4 zi!I*W90>!n*^T5XX3Ytowko{S$9m_0r0Wf`wKv6c5dK7BJXW#kADFbVjn9mnsit_( zJ0S%gIil!4GNhZe{~Hr`f(3&cugAGo)olnc(Pcad+zg00O;dm=!CnVEZE4)C&$!xJ zsQYF=4_T>W*GwpGh2`XQe(n%Vv~6x1<7O!K95dcE5Prok8g2=T`b?zNV!%NQ3NlFt zL`Y;kEC>vz5C5rI@pQdrlvxTr$a~8~dw@b(ZddNTtAkl&iW+W0jUg@3*jJ-js0wSf z4ji3+ml355$w*jJDAky}I319u#gzRd+4E|z|9Q4kK#;9YAakp8to2R8-4Ce_~MM&?aGw z&>yfJAwV3^V+Tx)@o|bcqiKIsz#Q+qNRP^$hzjTm76R8neRA?}AV527DkOrJ=o?rX z*bTk(=U{hu(6)x6rpZ;AQ98Hr%7P2Am3Yv1m#FS);^&^%my}xhAx^B~=EAaAx zMw22Cm>P^BLsM`$#n1C91SQ)K;yI?=cEoJ#)|Qj$`@$MG_fQXB9QW_sU+79hw@e-W@Y%CF;Sm0p6p|UdtC--%oMi5Q2P(-Pb^GLY0?^%5? z7&)jEkO9ocSSW^mfmb~5RXQdiCGA7N775bl^m-a+AO1CFgV$iQe)pR+l;cE|u4cmy zRqt0|99k#o^bVebUj0Cb)GZ+~DxBb7a@SsXjOn1M*WT@@jV978VtUrx2H158Qc{r| zO4fFuMW?Mh$imPk+%Ix1)pY2osm|v!45j#Tcba=r^rL?&5!_8X1Yq#=qdfF7P|aJ@ z=HnVi4zh|P-H$xZFpf=$53ClfIxrq~0Wd6jjG zQBDh8zPMy7BBl54^J)(OP!R=Gn2>-(5pAQ#JNIg;*N!tTskPwC#h@=B4C(HHvo014 zJasg1fiT`%U9&CEvgq6-6qDkNvV#I>Qo^4<$HyGkEK^D61wx#o6=N5@KmcdDxSi!F zxChY!6@9r>eji@*OBbOu5}Ji!;U-Qk7b@;gu&l;n!XHL0cwnF`VggrNJ~ zDLkKb%xkx;NX}Z2nSs>hR0k=^y?$92D6?J&@tEg+xG?@i;2kv5PEoc*qNf&MwQAE6 z`}}EJ+T9pKvFDv%yuF9Lg+Gq%<|SfYM3&nd{ie;n3jGgx^NH0$ohtf)dH(L^jvtw* z%Iyq%YY-el`TMZzBlr&a0ATDPj=Y&=U=y&%+K(caDms5|Ce63rvXhI3=z4CtMJMph zhsJ$d7$VkO(gZVyH8Dn3V(On^9(igWS<4vMup`?Znj{LrYl0&0`Xu}NFf_q=eiExb zSt~w2<`ac%V7VR%dwj6*{jo*4!Gpp)I&5x5RID4CI%}BYV4ZT1@&e<0;%5b~QgMRU zaC8CovIAAKJIl6u8tCA}b^o&0`d}GI6M0JY{#DFHUV*(B6AdC-5l?i_4%s~ojXhh4 zSr}l4E8zsOr*W?nvr6%&Qjte()FMQaVg{Sk8NeEJM@YHNYi_H8LL?UQTw)53jaI5% zFesX%+64(|=Ip(Lllmf$s=4VHzJPO4?KEm}X}P z5JNTbELNudq{pkxEE#!J$ppKMiun2MI`{R*gjXhnCQQWfC?GcNqY1B6Ka3%kB)F`n zUBpBc5u2S>wTM0p*C?U~#Juo0AyuaIh^)E?28Ud_r_1dn6~th8p|cf9p(sG6L82!J ztG1&L{V%*F<7Jcktn9M01Tj2N@kF#?ddY;Y%$deM z=dpX671X)BOnxHd4Y5>8xLMYuq_aSGBG(H$T=8*vONT;J^O6ZdSL^;rX0jb@%<$ks zY{T&FXaY3GXYU}Q7%-7m9)P-pWR&#Wp4GDXv= zarYR5ejSVbUd%m*01mQw_iscR3g)7Ozeo(`o7Gw-+s1-g4gO1W>C`di*seuNGxOgk zCWJs5OJjWnX4>m8-sAEL`d05c+W`wQ;dSC0t5Frkr=?HeB*d zglUE>h^}?9)Z8!ObctcNW+?ZlZ+Aza+=*N%aON)}sx@gxCxpmK!fScYpQezTt?Lhk zxZ`MG&@5$;NvZJV8g^wlo-4Qj+;0Eo_kNWF2 zmZ;JkmqQ2uS*)s#H1f2ra9)BYU;mY&M8PJH#H?v5*5R)9s)#fzDPPXEEJt)6#H`+v zcb+4PSWauAnIaukDEU&K5!oVb-6;dj?MZhJOCrwtCXuJV?2c*5x!c1>@ZIhWqU3FZ z0L=m4KZvrs7wO-Q&yV!&Q43_oUh=-$?^k24ueHtbQRB?%IYDT3If9v$rBWc%1pGbi zKRa+zDKYeHOb#DTTM-AW>Abo;zf^8hFDjGP-*=A4VP#N;vPU8hWLX{nnR33nb4bdU zZ`t3%3BE>M6!e8V2sX$}Q^X)4ew@(l`OL?!fB|&pbxtEot!z*Oa>ac7A*Mz6t=AEd zAd9e4O?`F_r=PK4HF4A2ULgXOOfes1KrJ6oUodr znYiQr{IU#1mtDU-`t)(O!x;7|*|vGb{5PTH&8X>aS5|2ZmPf0QO!`!!)Vc>XgJ(Rj z^?`aFDShV5z90<)G)a|JO8Z6u7nGwHP zeGTowj&HogimB)6$TT!bicG@Id0yN-OSck3Pd7H|^K5&X%D9^p_oI@e-q5_Kn=th@ zC8m0L+~QU$W-fqxWnAqZx86xMNo|rTyQ?rQQLP^SbzCx1D_6F5PNLQ@!m>{ukQf=G_dwXPaXf$1S~H;t%J13O-^J-LCB9K6el~Ci#idISn>#o7i_&um4msL-n(y z{muR4X=bU>Vfd>78xFt<*90<(pVIP{=drOru)dl2%SYOYl#un6%|-;!b5pE z+Y+;}>WE3H`ZnaTy2grxC-;0wt(0wN?CgK4y;NsiX9qdS^$}?v9zd zxS%RJjDIQ-p8Oh2CHKD-}bX zfY|`l>1lr}Ev=%^(6eB*6A+{H6+FK=pBWzeW`e4uq?eZ2Kpob3$Tizy0B|(b)DRn2 z?U6no+`1e;Xoyc?YW)%h~vIeC27 zWzGNA?1=7TxtzSb%f-`IK@ZzAo~>K`+^`*;rrix`K=R^ky*@1XGZpiQ(efV{e?C^) z%Q~9jrxOCGm@s0N>q|lF`G^2zutiB~;`TQ;rm^+bz$b?pt?y;2Sw$DlsJstu#5oPd z#IU}P1w&SXm<`O)RU#b|_c?G`+tJhz8@WC_kI<8DyEGDx8nY$1BTw~CG{A5+x8Y|v zx3PFIFk$?~um4H=saKnb57ZhCGJ^qZXFTF4L-45l=K3C%PL1h39kqO@k} zdT#l~epaeh)~HG2?{1UzyIds~kk6bX_)T_czntNaw>a@%*VL=u&2~KDcHB>1I#kl{ zrRcAAU7gq{9eYs z=0qNN#+1`J;Y@Q~GoPY$-q!IKYb-}3!{@gRF9yOEuUXpa>)5>WyqU%rpxBU4<4nVB zHuNKp`FAJXfiHR9;E0yEF0whG`lm*|c6&b7dTRR8?w^*O9iG%^+2Gs;w&LP<-v7Q7 zM!MSkJ3kab8cC4s(Gf&VT~(4Py_zK0Fclv@5mJe}_ai6z%*ipJ0`8DaEK(b52Ko?396hlg4*xT?^oS{W?mq=*yiq z4dNfmUFVbKPu{CH7{&JT+6WxQe;EIPHQb}_2c)ErB#n=IFhH%h13-7{lAb?xsz zEVkj55t-ml{ALK4CMv*9cV#!Esu;JxxRg_R)#^E)3YI zxYHA7e%RTk1~0W$x)FKs;A&B#6&-bBZ5ARjpgsWNw$~#b|J}5FWf~8FRj*n9odl8h zx&%PgRzlhYtmO!n0;$pCAR;H379Rv?awad0NjVZD1C}ue95u9Kk~TS_>y5|(UbxNrzr*ETWl7T7xni~7!MHXiOQ>46YUIfAaN%vql!THZh5yT3Q+t4~AkG%=hYgaP;V2$Hf7r_D5A!rxm^? zY0Cu>%u!LzZ$wIdB zBcFOG+FH4_x6OCF-jOz)`p;m7q_tS$oA%asKHN?WR$wE!TsivPKd z-~Dh-7~d~sE&{;(aav*o)Ci(>AQMKzf-iFMtB0En{fb@tV3o+Vt*#s5b7^I|cpmK2 zEYUKa$m3q%*t-5+_DYoxyDVKaJd@YqUCAH)#O&e5VF%n2w?wqfB@= zdX9ZyLF(A=Qh+2)Rxrmv%I?N<+ttH%3SS=Vti1yseMP2%vfdi%!evnhSv-fLgP-h$ zG>0$WRrjYggiTprFh6+S#on!z@3#nw2g23FCPlwR3aEPvdixpDxfh4JKw`f{fQU9# z+DBRPdeINtURPIfXF{${UFVyTgoQh?vRLEBZ82?_B`j`ni1gO=-;onsLS40ov|upA zpo;+qvXcahoBlUB1?F49^VTpLymqPwNlPFWMI-;@j(jUFhLS!-t+)Q_Ja*a@f$%r z+(K0%;;by$ytHSwRX5S~qJrxFFh{U?om)&QwGO*IZ+8PlJ6Yf}5EW|IM^V>Jvi;{2Emm1$083qY? zq77JIxbucHxSXw$EZSuJ=3J_I*jxNKuM=A;R z^o)VYpQrBwTQ{v(s(rnuMhXlvp`ZLAd?x)hOOsTAhzk&$9>KWydpDb$%4HS{)O@1ysx^M*28IlW44tBFuOVUKwRpA z1`ejP#j-H-$y_PIK=G;$n{tTv)z0ET8yI!vx+1f>bP#>xOfs}QN>}9%z^?!e^7Pzv{4O2&R5_w@Y41D$?*Dq-2ZS}(Xx9;-OA3@PlYN&yj^6bSjj5 z9XB&~rJbBRk*ed-lhBL&IZ`esBU-_PzyY+>0=?fi8tnSyN6f?rD%fJ@5V6})E_xpu z4JSY~vDp->{9So^QYE2w?wTm-T~~3xjr9*Cy?1YPC@a?6`%n6x;>9B;2dg=fCELnq z4UVejsJpDt0R=dmIMshb=W6lOjenhJ7h@#eh6}F$=){@C4E$~aN~@h)XG2KsR{WDe zPsGMREO+th0}W6Fl%a!^u}9M9AD06%psRt0f&rILMzoRX*7S>x7}K4*?SGL(?tTHy z8E6h&0GKLrzN4~1wDyVrS^~WYe~jFq=dS2h4gY++{k3@amsF8|IMK5Ii>Tnm`9t;X zgc!KX59LV?l*VU=Q4I(Mwf9J}{R_*0w2e25x4NAqmpEtL9-cV9mPLLpNVX>x% z9+ACYvNejg5I;ekdXw-(1_1_>K=0v(SX|A3L%|)sH%LD(H}%q!RA%1qY@j`_k9S0+ zi`D`|tRJkx5V`oRvffof8M3A%PNY*nxN*G3QP6^G+(q0I;7cMM-fGgSENM1~>0)1m zMZkMV4eeZR&l0>?cxt+xd@vTyTA7X$QbK4L5NZGjsio+||69B=Gvd%rrLkYZUobEE z|D}IYCS$r`AKcHB4X8&-eM=iBPG=_c?%&WJa77_-^p*6TFO-PKQ9W;At5^QIc;pFq zUJHoX`MWbS%m_GCqIhi`zVryFG7|xik?r)t6|vX@jLX=*--#?7TYy=D2*iIy6Lo86sFaG|{p#`FL{~Ajwio>Bqk)YZH1GTN zI}l8r5TjHyaIr8b7UA~w_nGVtIfs%Hrug%%M6R*@>$jK;;z6paHSSSL^Jq>UobUOh zXUg*AkpSXb_CZjlnb%_6<4%esDQ3!tOR(1ZlUPF8OVn}AkohJ+Xr@0q{I^6L_RGG) zX__@Nq0r83gVt)Vams;s#7yCaUn{;tk+iX4J4z`9{~Ip$S3L}+g@bX1Jla{UgpN7* zMC2)>{I@boqYelhH*0R7z_Ya%xFPA}85N(uBeIW=fChTCmP(s_z9U<_=2_13y!fxP zJB9B%l>XNSk7pf^@4j11jh^_NfwKMnpz1itR5WZIRr3now3?|_89SITkdt`*g$oeR)r9)EiPfmBn?i#>T4l5^}B%I<)lwcT1wQo-;VhD z;JCQUVStRT{axu~;%EA(fTSt!%hbw^YojMD-F>A-4G8UDY3)eJfU$2-JdgPWN_`UA z1jT}*6f6BoooobUK7T+2Og%BfS%XX>8r*`gi@`#T|#P}m)y^Sznp3%fFvXefZW+Z;aHOwU)gE%`64q;1E| zonpe#`_MUjxFuWG4K$y68v!%Y1Iu)S63%nKC%^*vMH!b^?X?2LQsu{7c*H&}bER#d zP=kK8-7fBxuA;(3Ko@gHjncbo3iy1v`QVQ$<)jjYv@&WSf=@vs7OvT&3N!+%bBYKx z2qX@5bCIU}G^3uT`VzlHLwWqL>negr178#l?Tv_Z9Twvcu2MX7!zR?yeixkH_m}BC zDbq<_s!7ACo{taXgR|H@U_s#tI5H@6A|!G(l-YAFvlZ|5TLHWbfcASTvfQfsg&KZ6 z8!#xaIG=3FHx7Olx?HKB>_?#8Q?7IIxbS_ei1e=z`n!*%4o&Dwn4G+rOm{`0R)Bm9 zlkTTMBXOY>yJZ*hB)M>7K-dygH+A-n^82veV85^CL?VBtqZv7ZkkZ+hO0e>3z?7QL z_{jURZJSBG92+NpFZI&6nAyD8hDwM@#664Jrls+rzXSEEDl{5RFfnSMfqRg$ zpE4<$?gM0?pOQ@$#2`T2uh6DWs<1GpnYh&QvsP)o%8-fTQ_#ma(HV$IIqZvCvJ?ot zy}Rz~&%BTE^n@!%i)^}fh=!oyYCH<6Fgd%(F_8P*F#%?p6pi9U)%1{)=q+#M*Kmae z!$ehxRQ-JQ0veJ+;tz*h4=}9zC?_28__s6Y^7EX-6Dn@KK=R8Aq?W# z5JV1&^H-LrxjDT~k;aD-XAt*Ny^O!$OuGs5i|Fiw^8ycvsA1|yQGg0v$MXiN{+mlI zjGhs(5@j-kwZEnoPrW%D9B5I(&BYpf1IEoE2;v(yq#jhNzfX(UV&ISNZbdoSAm1$A%~7PW!DW1)4p@f^wF@+JdEr@}=X zGh#xXzM-OC@mo<`lro$->zDZOK;g6Z;?MX`GVN0i1Ht#C-@VKqhi5~kK$c=z(z)yPI;Ew=EaJT-=$yoQ z1o)Bcgu(<~>+qB?R7CEG{nP`FMK;8a{nGF%{GypWj=Tj$F1+h2KowyAgFJRc8Ts-k zJUxL}m>9wDD5_mD){)4}qiXbV*xsXV4lQ<;^&@-09NPp57NTApLg`XR#QRzVgd2e` z$la=I%Q=eYQW$*&J%snq|$#m=zh5WZN+iyeRa4NHb8 zd#hVfM2jg5a{$ZFOTmzd%}A~SfdUPN>5ZC=05aBnWBoh0+Q@`4J1r(DxYNl}pH2eo z+eSe#&V8BSb15dtT8NtH?)q-w+>C$)(rq6r%|IPX&fePAYpX{)@@w4HWP5$PRzK4% zR;Cmt<0d&ZK!ZCVmYkCSc?)k2>U2)vBH)R2vK=aw z`&!j$K~zLyK{rarERXhmn@1^pUuq@3vU5Q4HMh!Tf44xxS#FeW39wr`5(X<@x z#*}il1Qe@JUDv$x3pumeBAs4l#S2<$=8nH#F$}*t8(b3(Lbzq1!f=d;#s?&@2~)@P zl^=P-QI(Dc%=*Vft|zxl1p*OSGUR49i_o&4iy9|h>wSvG$xbDJzxl#@dH)-$t^j1}pI2D#g0>_?S-wxq$ACIq^q=$tx zuY^oYY#HODC_WKWfUk<537Dg{PMEO{l<65yIix@Un{lNA8KCpW1rsiXRfmQDfCP;Q zz2{NO!2w;!Yk|2mHqhs!F06j`ym5jN;dO=ir5f#D1}~WJsBI*!rq4Jnwl70Sa@Du-Y@ams?EH~?FJf|W9N(JUqI@hqXm{`Eww&_2NZmP z9v2x>K`QuGB?Q?rYDYZTjh@ct+z{3!Zkd?^^_+cS4|lkCm)CWl84gg3qC*$IrTR4Q zs$}S~L8Tt8Eiy7>ilP%Cl7usrHe z8^4LpKA*nWPs13k?EtdC`M|DNaNgutg)^5XT3TjS=iLZ#X6E#y8y;qjTtTo;)-i-O zKcM@~-Eq-MF6!|1bDzv{boWhdr!_||{;2>kfd?G#E!LGZTiQn(=kCrrx}K?lzKTB; zOwlI9xY+(TCggt3;$!4SiZK1P%k!R&2koD?_me`}&3KWMTMT)z-7b#vGihFT)DOM;@pt!e1gS!^@ z7Pq{I{{GMP&WBtfA-iYy%-Nl}=iZsmOd-3aT^)d5?vY>(C7~4W zA9yd?@>XEx{b!jhJRsNzF9yt1EpmvHB1$40G_of`hnn@Lg=I6 z$rb4;*(fUG`0V=ah^=HJVNvc#99fWc;{WQ^cq$Y}}s0 zC^$v#4R*R9kY7Qv4lmx}hI1u3B~kz*0`hAtMTHM;52vs5XJ=$(NtLQg63CoM1)IB) zfa>(IT&$qmfZlsaFwYD^;iG{n*Z<_R1M7tO#vdu|OPT|;|H4ojB>9RamQ7fpV6uPq0a{FsXcGU&GEPsC!bZwTlRr05&> zSV-g^kv>Ax3=5E6wo@}G5iclw_JhCSYZ`PqzO2`0B2`N>|7CzUP|QZwZ-4xgeKWQe zKt3wlpm9liP$Bg>lCkrSkHMNzgMH3T^kJ{dkNUJDfN$nKiczg;pEI(m;le+37MG8X z9Uv@}02$=;UpHt+@XaD|%dQG53Ouwks~St%zNu#q5a zr5Vq)UXO3&KmDPuG8@MuHSc}Bz@l+6jhFXZ+4l`RpEewj{9Lw%3>>^&TOC+5P#s1 z;4S7U5a!}lMMdqWZYD(I5JzP;wQ|QIDMPaxggJ$0LPJ$SWx4C3rrAI2J%!TO?|69q zkTbOX7Q&N8FXvc$WasUJ;q>1L#mG0ldlg1O<@ZN2Rw>T>_Lr2eI9t%70{d0nUU({fqeqxJ z+_i|e0I(d3J-ntp@446EhsCB2PKFI1`c8jqoRVH}Jdtn+o4DQ@PK4KAd8&T*GV>xL z6%RCmm>l7>XHhe2T{n)k+sY1y$P&qZa1f@L2q~3bqs|<)t8NAH=l^EajAlwvP|fy3 zF|gX*8jf}USeiO8EA1B2o#<&>W5G#N6MXxZm^LmBn*i7AY}B?Cd~-h6-M{za?e+Rj zSag4WGC{Yh71NcV8LBjtQY7Z`GH}JP_6`5f`+59?KF?UoNQrM59o+gz*$`rI!c5qJcIwpo8n#k6(Xac3iFgXkH=`FQo_y{_XpW3F zfx5f=wdcAJz3#aU-;>};?$auEC1XWq)vpQwTHh=n>g4_bzEr{Wkst5;H2u&c`qmdt za6rnD`%<6s?=FXvvEioBiedDU%T}N)ym2u$=ehhWYsznzxcPBrOsO3IQ^ZZWzfXZz zCynx758LtYVXwSKMIFAZ!ts5F!=(X*q_jj9y@>l=_>!PhwLg|(>+EXm^hjkrVe3p$ zM(M{l*}TNk#20bQNf5Ne`QX7xhvU?xm9Z^iJ)^x+mebLL_Dnr3msODy^T$V{TtX0`&wbJ{uwC(omnWUD>xNi>6FNG8TpRc( z6ok2SO_gIy-e#aw#FWh)BGC1S+)K)J$e#A99SGE{O7MWd*{uWHZw1JiCws4 zSH1y?V1BX>pu=>QuVLZ5Qsr<FH^TDQt?(hR^Fuav)Z9b?xR-*JF0+5o{_!e3(6XfV9@IL;cs2fWRMo>@B9A zofTiM7fQ~>E}&TD#ya`%Rb%2*eXGs;ggfwNKtQjNHPX!DZyOKQs>tGp$1l~j7ROSr z=GF((ZyQ!ghkAZ(V*o9W)d;s*UGaZ&h5cPBJqnx{RcRz~zuP$q$Uq$Zt`nXRvn zrZ3&xG$7`$eIFJQ1&8zMRkN{)rdq;*IuAE~-N{%s^SXb?Vb0xaeC0^H)Y|oOSTIt7 z4$|WOh{qw;C3dAw%V$JfYuJ4XyD>5IdFL}*_^b}lYF7n}|N5(IZ~S=3DWbzvxa5jB zZlovG)$s8iN11;;X|LLa0);qzZo-K#;W+<&Y|qT4VoUQS$e>NwP%3$kfZ68UwCL3a z3RP`a0Oe@dVD;-luzj3R=e_S*kAri^FH4f=9^ku0{_Dxd^>%W*+?twdz>U)IyL)C7 zk$df{_)x{FLtWe7mmM}t&aG=;*mJeY zk-kDJ^kTk2-X@-;XNH*5;<5EI%DJsA|E*v4Zqi}v&8%}r@ae;t09c!)0XyQk=^fm1 z#eaKm77pY7g_Rt4u2+-7yCc$e(K(s*`#l`w7cw%^$^Ft8LT-71+dkEX`dNGYT7)Kk zWLv{3#ZgYz?PyXsYd3MbXB}(4NO9JJhc3^}+SYPIf#fE@o7rj>egOfss+qyN<((aC zc`!H^doaf_)1A(`HwjlwuT!B>a05wYYU2aP15MD@D^;Yg^pbp$ro7f+VxQIX9Z>@C z%5V0LIqRA_1fj=yjF+-VYj>*{H)GCg(yGjzY0rst!MP?m|Laa{xz(5W@Q`@@eqhma zOK{-0%}XIZ+P3o&`LSNyqGo_*C&;8|YLg3E)X^Rp|E{pD8D~31*=+#F?_(2szhCOW zP75~0oJ`l!>$LZ;V!j?Z9&K(li%WiL2{J1hXqn|~I$xn)?yp*FK_40?|eM;MRm~n0p^Vt%!^T|iCzszKg@lbQMoysaJqgq)Et4;-mB#qjR#(SSVZ!> zzZU@VlFii5(EwB=K=D9L|EC=&@Nk2UyM%Q{8Dq`#qk{^Ksx$bbA(GM!e>G2CYgVMw z^p2e0HT(?-mqs)zg%`(+SNiJx6+AOe*_fS>2bOz(? z!_9aA{!Etmq3ZMP{7?2sWz;?ze~Hm=Qm=S0O*H3P|AXS*83mFRoDzWQT}=~mKx{dh z>fK!_EA8t@REoIVY_9^|f=u5_WWK~Ktkw}j()HXP_3Ax|{k%`JihIE0aV3$C*N zo5)0KW--{Nq9qdYuC@00KrXwbo>172$er{`h;lSe;y3#t78U6RFH4rx$O82*MIB!e z&A!bj-4J%E{_Ex}q(MAXqCtzz!qc!anp5n19M04B>k>59pnrBaZ~6bt7jbsBfj2DK zNc#NzCy}c;P*H%=(b1!vgcSO)xVjcRV_t=Ffr7w6DdqkvHs@=RdQ~rmUw>#%<0dW0 zoFJYzAY@oCFSws1^z`8*Ch`N?(=D}F=H9nf%{P+pH^C9!-LVSKH;5&l=YPuSRKeo3 zwl=h*9Io9LdP;gxj9Dr1(mk<+sO_G4v!CchmqF+dS?%M}^{LrAJEYY}vG$XKh$ZrC zQ;ZR^*V2D2EXUhjDLLf0F`_s2*qOzO2Xv@KeDyI1A2zyt0TMUI`WM({Zj_VnZV$HD zhkN`nbMBDCR~0X%rpailSxy4Jy*x~OzJYrbrbYj3dT5TCWR9-Ld^FYl*6|AIz-xDO z$CG1ITshkra@0pqX49KV#9(R(E$H!e-PFSCUaQxU%DG8VM1A4x%o7{b#H)pi%qvV^ z;Y!vKai*f>-@P9(XIDwlkj%1lc|5nSc(ZAFq@?B$1M{r=iS|i+u>7j3BtmDkJysmB zf;N!k7#}L)g7H6EYMtNu=5LMJT%!lja9k|G1=%7iS^T7A4_H0O=*r~|QFtj)1MbG@ z=o4?Y<9{z~WujOqk!AI!;b@+xNPUxSDtbiU^6KUhM=@3IW!F^U5l7U6o8O(HGAT+B z_9?#XFD2ZZK5Xi2slvqMWlR+b+EzK*u72L5HT!@egU{m01T919K3Km4VRn~_(ezw{ zBA13-gG&33A|Y|VzEnj@n3=sCyqHQNw1;y@xJh~$YL6&5^T{IP@}=r;JWd#ecUe~; z5xT_jp1)FI=hOU&DXlqe*;M#K{r_a;D>HJN40)ewW~T&-6?zLJgCff&>nyzE#;<ubE^`%NS{-BI$@LAU34K$4-OnZ}sQiMOr3tOSDQr(l4nR<{-jG%KY232 zZi|Gf9f+8-Wa|3T$3I!%(Zqm~19M{K;WRwkPW!IM%y*L)NiyFC6))Px*JabsudE46 zYQn$02lYyEe;x&CT-_qlu(sfZl-22>r#w<<2RHdg>J(Iz0q*+ei!H($awh4oq4DwW zNr#BqzY})5A9Ts`#GZKgPB$)cN6YYi)uWBmuw0O&yF(rPZL*Ft5b79X0#S@6BH?Q)8Zru)QLIIQ00-O)_rT9AcfR*~ zNAboMstte2u76FExCUMbz0?15VIEK2YdMsUQg#%*3=UDi+9@z6(2QA~9u!FZHTMSn z?bOhh*XLXvPVd63nce$OaZ;9``3y+4!Fc86e6s64#nh-)oqs>iET86=ZqM0)y3Z?7 z+slP7<9h0n-H`jyXw{7ulO#-IyIn;|&J`DjZ9@ZaR#xbYM+Um9YEttKtSORxu~Kep zi)SHma`{{QyHuCee^%oZj+cos$xA%?hgVbF;0L^I**LI-kEov((9$GD-Y-FH*&1xo<>F zbNXZP@iZQq8xDSdvrr1jsB?Lgj}=Z`!?vJc9RFgN7=?}pdROt%2u;jzmyML)jb!~b|6G+sjvbrB2`#I)04}~% z6wT2K7%@hahcMObqCkvvYKVec^Hx9~{54c!q-d zH+*AuO;Ow}91Ch_1TXU@u>)}f*P9PeU4#ggUufiEccwCiB+f#YCIsy#G$D1Xe%0?v z*)p}!zty0|l1r#QIj8rq`jKBepmT*~X!c5Zn3scl1^kzriQd=wz@Y{wfGsl2SXcJgnd%} z+x5$az&+~go9|x+IV0L%)jRO|W%6;?ZH=BOOY`B#j@u?-meZB%Wh|5|@mj?8I6vx$ zcV7qIEaB(laVYZoT?{9Ebc^T zh~skzhE*sDBV*Y``$vVx(l?i;q@o6X$N)Cxlb8${q>s`2`3aGK*c5$?E0F>1h?(lV zspb1e@h55+0dcKy&ds-LFClMO`Dx)=?jWDr-(gqG$~asgkw*bf_WszjwGkP;bq|z} z1O#fg8@X;iGnA_D@*D4m2mXe2UGQ}g;l-;4BycWdXtiFG@Z40$!Eb7c#{qik4%M}V zdvz#MrFC&7R9c&qc#-(LbD#ALJ_ntm-q7b>VhY4{sWXH;U5X?59QN^Oiq8XJ4k z7)W>bM)chH?AEfuC&nm{kPmG>j$dWcO6J#ACGm1Q*D7Z#HgI5%39eh0+4yUocrUzR zCSu)JkH=BYz9&&MXLqQfVj%@MV5Dy5=I3$mrI-zq{WtK>o=sGn?`I-@vtcoV>=}AS zP4S&^v|D3Q!MW%vFZAd6UUyCPtLrHXje4NuPwapT8f}X=8{dMM~meK+$Oy& zS~BT6J^n-0p{rijx$|P!m5QqK3}fftA$h3F&ox=9J1_e4{qmx(X=S$S--;Sq(s-9`_|9Y|85F|>q#~dFm zK=1z?b0U#w)mtJA%(_PPCYhiGy&fn?LQOy(@JGOJXU&RarVr^BPe*u>j;g+akrE zPGJNw4vG!f+tYY-hE-Y5Q#XdxFi&WPvb780=iqC zp*4`z}-BAUc6|V(v2{mBvPIE&ln(S@aXE$_2{2s=3 z8?gUrWQBW#cJD!FcF??dyRCKn95n6f;1%S$8rIyqJKjp1;vvGS;|` zOA1kHz{LY|RH0c@${+9moYkvs_kK59n8PxNYCmfBUdEyx+X53rb0EhXANxE4TcMVm z7r=beLr{B3;_g5@kw7;gT>X<_FONj#rI)E)NWl;xdWef5vGMxrSQN$^Y=YkR-9P>Z+d0abtEdHxwLwpU8>E<;YeIC2&|dy@o|Qw zpF)#_@W&)UZmuZDD``HPBFFX@w7evi_6pJAk+xrfF7b6fYo9qkWm9kMWOJ$nY}q)T zg-`=~(e#9_ZGk=xty1kjZ<%Z}7J%Mu)SJk*8TCYZ&kZ%RvHEfN6=S0#l@WkV`b(jD zm1tfHYoD)7$4dXx6-PP+B#V~_U4t*#*zyKv4aF`^TD59cwMuJ45c}>?Oehz7k}uc8 zlF#P(8m^sT;vm5_mQZFc-*MVg& z7ajsXPTdu}h!cueL|Zh~PlA&AfzYhx{n3aGPBQz4d!v3ezL|J^pf2JK488jxlbrXB zJ0x@j@{545T(@W-fXIbZK8txvu*LlxQfu5A!bO6es60iGZD4S-mz*$hcx6oq83i-w zPxQ}_0gnIQP_L79@uyo(?!DaJ&ufSknh1Q09*soVXRNE$|9nSCman5B9YiRGpa}kl z_qF#JOx}Ggs$kU#JGu6~6Kd^gVf}pX(=7I;Bwy;82;3|@N=zQYIO<*IK&W7!tYfC5 zqes0JJyFXniz`418KpF>7!P z2TzKa6(PONAsA6&gGBK@T$;3pnmkR};4kg)k&JmN@H%lIq`pcP zF!*!rTV&cSsx1wY@q|aUo%aweB`G+LNd&(oZq>=ttlu(OeMy7VnavGP(5jOw zkz~JmM#l7+ql`&&oYnmchxv%IAOO|`R!Zauo`s%UH<4VRya2e_<-yc9VV~Hj@W7e} zFH2m}9fprF|6-jfjLHqWVK0r6#rJ$VUH=;pJ&wZ6qwTOy(V)6~Ad3q&toVRBG8GeP ziR)gSfKx1k$=1eh$8R{^m#UcVdig8WV(F#+D8uT_-QmsNRzh8K*Z2#k$S5K{pG=nT zxnm9Qq!A5pKHPM{9^N^M?kO|WG2boZqNF#=yVFP0>9C0Fcj z1v+Hre zQ@wr%T+`i*GJ5{5k0hG?sQ!sHhj<{;=)mBXM2Y!U97ru?~B-{0A>ZNQP3p(VL)eJvuZfei zmJ@gx3?^FBDmS+t;ZAVyrj39V(45ez4t^YsTa`F>M6P-p%aE3Az}2w*?BQ?A`~CMP zpt8~d8AQn-lgB%q`K6_7^^bgCo>xAv-M^erUB^5>1a!Zfs<#h+#Mflf@;V1+4h2m5 z1-f8y>fiiNhkZd$?=4Bs4{l}yZ)KV9PaRJ;7-9SQvgr$_TVsRBA$VzT_D?*L7>e-) zHQ6TxLy7ZDVXtr|=;afoU!l>1Drb=OhilHSO}gcr6O_M#g6{LzdI}7b>81xe9!^c1 zn_Z8$9RLK{nQ;)M>&eeD^Y|WE1&LoRkT4S9{1L9X%SCjCJ&v1>{5~}S3`Mt-82jLv z-F&%Hp<6jWih-M>&ALO);oOjYlFCf!PHR`jUPCa7Y`afK*-C=1Syf8%QKs0%9?gDWM#rM!i zdEni1x~8!Ki%l+{Yk@Y6GE_Q-KyTF)86wp7+p?iNI_1?0MAZ$Eb5^8rWlK2R2)tb3 zW7~>MeS!C^4%UV9it0y{{G1pRXr{}9Y<&Ql$i~4zpzzhZ!nkVV4rA`TA@El3XA-pC zq6jHYMq0s$)n|fyof`HhzwW#sNBO`;>*^XveG1rB2-RNr;9U8>tHaG}Z!mMimz2nz zTzI=r=F5CLY{P^3R<$%bLFtEL_A+TiA5Ga^5}D5A#U zve-P-e9zIm2#N4p-DEh;;A}^Y`nSN{S;~h#lLvNW|KPQZd})mF>pE{&(yH_&RlKqp$Zv!!20u>WP)$89vhK+(~)-wn%S52LOq`(5wlZy$;XOL3wA_0 z41c&HhFGojtT4%>PXRXRDCL*#Pvn0Im5O%&#u;B6qV?%4C15bEtQunX`D5t+nYR#RTx~>8M%I^imTlJ?7FgG-k-qc z|8^Gr&L1aEHW*t~%l-N)6QDSZEwH`D8?ay>C&nt8JV=h?2KEMYtaWl=cLYNz4leI3 z0vXUg-U9j1raayHk! zwPAn|QxQB#0Lxg+>b0>|I zUd3Refx@J4o;sM2bOz}lSvuF$%R_f}Lhx(UhrD(|w*eYLM!2rfn)a;B5B9jm#n}u!QGy7a4(cOI!)2#6I7Y(Hzh&cyKqsY}DavPt%sNL! z?x>ef$&@!Fn7V#e^>JY5=eH3K%Gp7{XWwIv`<5Wk*${nY{wfN^m0*i8@G{}%LWes2 z>!aGk#L#4zRke{(-{c}*tVJ0W!oN#`HsHarm_>3`)5zmpd=RzF(a(=m25Zs88}>t| zMw9KnV2rl-v4Z_y9LSyZ)lDc7+I>n9`sFQLzh@mCt|0>5l*}>f2JGLWR?FCKl5!Ux zt!*|L#Gojm3seit+OEmLxG&9$*#nzTyVvKir-8MC<~eq&dpSD}{`&WJNUZ7FfD@_o zuIoQ{_dP|AUpp77%i}F^-Go!0D@6s%_YNv2e@~3;wlul;XTKvyFnZ$DUG4LnEQ3Lb zYslD1z~@7EUC`r55%(ZXXTabhI~dyj%Q2i@K01AzhhE;$T-se9&=(MB6p8u^Y=>o0 zaeKtP5PkW>wZ_BdDGcfH(U|$(`-fo2)h~!P2fM}PAF^J1-GirRA0e^=k>cE|r2E?C z?;sYNICrUC)k6QUfJrasT1VK*dz04Z|0z=;d{id3`vj@hHZ?@CXV)Yg#Kfoi#ME0L zE|HefrFkhh91iMR_yM>aVhbbY7H$Zv!$6E(;K->t#wmewwO=~MZQK=+v!fLV$~B|E zZPV^gUW&Q{uRiWx*EKgqTunmwn)Z%P-ddW-`5bz6hK0?9O@0Fk(*eSVF{6MqZq#k>?lV3Uh{^v5GNVEg2CK8Y)a{O7tuB7^^kr6sJPfqjJN|xJcW) zl@4Fx7>pQQ10%{zM{W|#vyCBYT1pFKOrf?6Ti1B@T8@o4*d{xlep8gAO01+sA=1#} zLE~b3Ll_W6@TW)7>o><-tQvL^!SOX%n!uaI<+o5;@FaR=TKX?mr!2mM>L&x5wtwmO zI5UTfTx>&It&QM!EQ6CDu+T^Bb+7d8**Rh9k^N-$(qqC!u33ha;JOIYe{5D(ns2VU z$@{v)tG>A_B6XY4I}amU&yqiM_XDtGe5dsLaLDWKyP_AN=oS)1w41mk=)GT)?(%p^ z9#+=PT-iD=>*gw${84|P=GtlFFHTo?a?CjCP(c$PTXS=(R?Eh?DWWAn#_e^C^5%eT|H%?_z#8nXGPq5 z*tdyJ_<&YBCo-KQM~nv+al~y#cVr;SzrwGLmXme|Lg3NkV)vNM&THX^-+%DLjFg>; zQfm{+k7UyAyV?jrdnMGo%n?69)B%elg3|4{vBBETAIh{YWu z7=6AvzB=@D^>j{+3-}{NYy0sz2kfXu)kZa2n==fvoC0TK;%j{aj*mwG$` z$!jeuNR@S-MNDnZ*D6oz=WNdq5|#8Pp9|2wtmO z>fA*#sbkulvq9-A4MfOll20b9ECMF_!@A3oaI~B^+ZK9-B*1d5D!?sGP#F?`cSEn= zZA>Kc>Su4}?j4o!;}wu{e$uVfQM}?~5UDoJ+U@u$4Qt&_&X&+w-+H|?26srR;&98K zKSHx#_$G{5_{|U7@!+zogARKbmfgIxp8+uFf@f#)Z|d#u927&O_in*~o#|R4@mqqn zjbs&kfN@hK@FS5vNAfw#!(cj#i}((vIWUl2Xr@wQMJu-PJ5tSDIi6T)Xd0X`HvgGt zV~EqvI7c_LLEHCu03c!LwfB+7NZ^oEr~kPL9S=*zJsdabFD2&K=>3}x)|CD7O6he` zbkzwq2a50W900p{Ljj`tLR6k5S7j& zGcWNCrRTFt&!YLmtSBrJ6R13*2-gH9+18NwMXE&yB0|97Y-Xttk_$|amOrz1p{DLv zoL6S;OLTny^;8TS$ux#@zaUG@P04tDW5&57+JV!=x9pe#56R`i2T$(jnJ^Km9%4n) z0kFHd{H-C^ZEbU`m6egWJN8<<-R9s2Nf~wisChT3C;dDR`OvPZX-%|9z>EXBmOtA@&GaLy zsoQQl+o=F9$s760NOQO!8<@&;=&2O1SFiKO&cXB(be)HL_pg5*fdtF21-T)rO{#G= z?uvptuL{sdizcTkWJ_npSJNF-83J!bJXvAcjm zQ1ooW415;lZ1ymOB`7Wk(u!jbmz^V6wrU!*($P_$hV!#}^J(_{^q>;Ge!s`pIEp|u z4m}?dLLk_4L@DzzAac$mkg`Vm@NC>rr*7hpT1|`hZm7}G5%r~V^4rf(+{)%kKosR9 zbmOIQhH~LMB$BFkRwPpd0m5(p4pSt)dN@YhZkiEo$}cJdDl1@)Cxyh;*XfTv?sM}D z-qI6Id8<*D*C-}RmG<9FzzvWbSM!HR{c?Vy-13`r2OZk(kDIB-z6fMpM!>zLWdMRqzj0Fd7-X!=T*dTAijU9jh{y;MHByu zhZ&-XC*2{|`{DA3%3W~6l|8wlLkys{8+Xb3NN21sQK`Draz*Scc&5|57&Wy@)G&kB z|CqnKlPBtyWcg2VGv_|$#t5$xkU&9FiI_YUL=Kid>X_?e$4eG3^c_$7_i*B2M$(9O zMU3%w6oWNA%(^lTY#gsGzwRcZs@7<_9#0bTQOkez)?6oV|4;r!9dgp2FTyfG zCF^M0ItN==MMAXTE^pTG^PuVnHwueJ3r&0WNFd6pck>2=iiw-U5`A2l@XJ|8H^u=| zS30QAR~cHw5F~Om!Uh#QMTOFYzEuqH>fvH&Ha@yO3lTE(A{!Sb*5_&+u0)wv{t1S| z^@>#{543EX?23?1TEW>D+j-R!64DJ z3SxLTd7q-m8kW~*?kAD+xg8@$!v)#jb)%(66L~)?gd2^b!WASO=j&4s1Se@4EEpK_ z69=G=Eh_3r-+doL>6_k@I)jaSe3YWYA(iG1jDv%oe5F5jvUk6Sr5pIXK|B-bbog&# zz|iyO`_d*K?qsdz7QGvPF+CJ8sK%1~iGkTu;9G%d=pNruDN!c6;l}yD!}|>p4csEf zvo!`J(%@R7wrEd>7Q^BuA_%+%CV*w1EHCw>XN#p{zrtlit3J>zR?-a4;6?qvyMSuL z0EIL~--iOBxM)s;`qc0@)6CqJKk<`Vom^r+Ak3!>*DHlefX0A4On}%-Q*>R8#7end zpBOnhiUb{g!1c*Ugy6z`9qG+t$T>Txew|Cc;zZmLfHV4`_{;{`HT+m~Z1$P7{VYSm zyowPLTvzS|s;^$UaYmwc-mW+o%~p&Gr6dsu%|+4J{G`#M|Btm(#2d}KO(~aD#*7>) z1`Gr_v}dDh$Q4nv=WCXYo;5p_qhsu4rW2>kmvK16f2{+7llF#W+rmCQ_Gtb==AfGt zzefj7!#>zU*AwT>Rv>I>i!pg3b7qw7r2Hkn_&;+jvm{MXV8Swz^i))6R4@oAd;L#j zpDz^Dt^A3$KFEY75TX%!T&*6UI$qE;-<$BXLcNi_cF!PGj|JZP2*gJX?9|4}|20ZIPKbnfzGjak5*|E|Kec z6d%}&b`wPrzv){WpnmvyN{bo-*z0a=YN0BdGLBYSd`gHYM8}Q619~X3&x5^)ZE;6^ ztMFy*HHA#r>X#apZ(hmF(*M$e0N<7`WGXZUv54&t?v)aySJGD221_OCBj~VU5>Os) zIq45QHi{kE=9^QXI6n=#-E2^Igk4F!o86dTHY1!@e(gwy2olK;<9&7o00mxf-A2wz zG44v>JX!6*(D@Q)7_ULt;vX1v+~FM!{Xea>bN`0N4ys@|kwxQgz;$u~2T2g(!XZX$ zV)49md&#dLeRkPgyI}&`W3R4$X+w$q?|0CV&)a{n_+H`gQ_~FdRDY?4ocULf&_{K< zBFYBQYb~!upAD=~Rp*uyA^bOikSsYH4k$dRK*Am=(}ViH!N)Db^jvPO`{Bol?tr!mt4q^7BPZm@Be`&z*P{s@#C}a zu(7|i1}^X|1@FHnIFFFAv4E#UFT8OrLW|~S)|(8&e-8sN(Tv^F zG0gT&hc{QJ9pTRYr!v#_VxWShV@i#?eW<~p*SfdzNr3$**^w>=8Sx1cA@vq3;fz?4h73V43tW;$r(?pi`=P|nm8HnTKF%G4<8ipz~po^;c?(Y>Ct-bayj2d(DvTQBb zq*Wa3LMC|MZ~oilv6)1&I5$6M#?Z0Hb!7gY^F6dNt$mqC@o<=HtR&6$gGkw+)Qf9; z$-N$Zj1;czhOHgyVtrQW8nxg`^GP~a8Hx;F-#X~|Zu)MkZSx^rnSr>El3Cx-<^dl6 zsbegMPE|q9M>?4ft#S5L88ke%PY$Mh!7^!7fiRy6XyxmXGyLSziY9o_wOrbJQOT|; z@&=Bximk10b}9FETWwr}65Hp;sLI|~qJIh@;#EwErD#IJZHx;BtFt(@$I!*&gR{H< zTb^t9A&I7n+i)9?-)Q3)o&U1_r2E!lK(0seF5EKm*Vo#_@oTj({Bc|RpF_6zO-<}Kun)DEdk?nch zMc&_DM<+)X6Ljz0SAhY*=<0es;x;#U>%i;o=3*{Cfi2mJXx!uj+^BYd`mdJnxg1ZG ze*?GEG_*7wW};51L3b+;Yo3Qs2qYR~BRn#)9pB9&w=om}a6ZsRym^E;-w&?qN~QFu zYmGB;AdUG!0hKNphBe6+m<=5BJbii)?{#I&ceLP*IdOV&Ubhbl8~8aF=9p%7FZt9U zSS^5yxb3cb>a-IGLorzmEyw|Hl6%Q9et_%l;5^;vjnPq92uyNt3A7>3_di23^!hU% zY@3+>gLH^n>~mL5U6>AiYK|iHrwsI>>=gZcBfK$<8hTkLtc$E9w$ur^dmT${q{AO!pvnqxs28OZ>EH`2TD zhd#QxM!~TDY7yhTVt~ThL!*MtZ*eCU;KL3%AL5#ZVdR3O)Q3MHk5#pjsZV; zUMI66E5U{rhz1SVA0x*Q8T4^;sRKw%&wE)Y=1BF%E=AdDo1pvH6Ngl}iO(yUI}zdx z`g6;@XD+7B02kzBkYN+9{03+Ug~CNwqLgU!V0e6^X6QRB+!LmKPfgKOg zf?~Nn0H2uCP@)9k2wN~O&z49ET$?8=jo+`VS@gI2uc&vAcY_8Af_Fd&{YLfkX*~Bd z)DVTBuqLaPPA^L|&a-+yGc0ni6S^otfb;`plPnOnoknopYQo`#Rq3_YrK>(i=~V|v%Cy_9$ut= zL;S$y%<}gnVr1R6_uy==)8e&#Wo97=#)+ss=!=(OB@ZUv2O}8V+!7 zW;7yK$u)^?BFa{(+6spS>XX=yw#g*Br;Q#ctA#rxr&9j*dCtggQ_tqNrQ)~lI6@SD z=mC46^=~D>0Z0Y0rq9;B--b_{t_*$NQomts1PCH3>!&z z4qXT6(jiSXp-ST$d}2F$1%QeH=;wC;^a>m_24k}@K(Y#X({1ZNSW$}KB(GVS1Gj^8 z&fXh9rLtcCidTbV;c6)-y>>Sy$c5a~t^&#p7}7r{2`YuOzlP}pxZMj`z}P9yX}t&( zKkF_80Am~K=c~}j&m;mA@z*^Xw3Ykh`)1a;)w4}EmR14a)v@V(NepO3PX#5wM@-|( zN3)L!Y)79*h5tONfPS@DHu(+j z+fhyXV5YqL9UvYDDXJGy%5w4la%Lmc=Bql~+6hdTRqd*h4C19HLd`bO;_y4RTK2-G zX`vhzyFi=3K`?L>vweO!3QBERq1}Q_3l)*qG=t+piH^)8v}vRf5_ilp^Kv6UPJKbL zd-GFAi?Cx1q&A&n?*6=FOmRC+eoW#OuoDGCKl4mU$JF5!bxg`Sw2CTK>zafJ$bJJ3 z@aLN7mCYYA0CsfNYjoi0hav(og1u!`CV*ll5v<<^CytuOl3dFC-Iwx0h*_xxDAe}s zGyO`9Yt6~pb_CRn*CWH07Q&bvXav`E>mWfYS68=Jyx@n8!HS`)YamgoP3omHk%QZG zWc}D~p?O7d#rT-ZuvxHV8NaiylP%(*Jn~)CQ!u_+#5`QD60)WBoq@PJa?K=J-K&Pg zc&j+TT=b@#kGBIk*rx?~rtB5B5~tXZ(!K78WW+fBZh<|#mT1o7=Zh6`6m#p0`5NlI>Q~^)Gk%K6($O{N1m~i{Yj53Xx|^rV!AbX zU5h^7u1NEx_oHpK<4P*?NG(0kc^ZmT|zf@nik{=BjK(zk_mNM86j7MvZmb~y1G0cubZ4Ljax z%sMpFJmpBg$_iPO;|nYC%cCBj6JjPIk}K-B8_f+_1wZKe7JJTcDH~m}zx(qMu`31J zn5LCP-l^5Et+4RLfST0`95GYX*Bs$MMIcASHv!^>i?;KpJgL{8AD+g{77$rH(MLb> zh$tf|GtD5X8r%uz9rWERgBQ+n&B?lQWe1||(VJeqW5th_cdX9PN)$RWz!-@5|qt$lsw&je_)y1ALMu$4ybIF1X z#h_v!Q01Fqs0o{*;?W-AZ?W}Q?rpJhEt_=t0{GF%hrgE58<$sf702RNHv9%z#vr+~ z_J`;lfOjm}@v<6|8J@mDkWe-^u zbf*ZFQ^O@E7wXk)X}~c@E9^gPN6FV_=jG{^v;Z_lIXZB)_g>j2ibS4*?%+}`?ek0} zldb`UL0W0#hho+rj5R8RX0ejGr2b=VNVEL;h}o|qH&-Z0U%zSrZQd$$I*iWTrF-$gI3g(G0>#)JbLqM>~CrHpV0L1^t#DimSe zu6Ds`=wnqBj>3D{{O+a0c@- zMt|5#<-+{Fmelr4M%Z1^Td7)U36o^H|qokD4I8=ot#wR^w>&0KYz!eC81$2 z`EK=q?hV>(Ilj@-A!mGU0?uMe;>j?%L&*?aqnirLG9{-MvZcryyFat_5D03T!=sLH zsZ||SDAj*2s|>ZpRoV7eco>k{ZQ&N{)qlq_B%d2Xh#=_FZkkb|#RIUey`o!GSuI}B z<)yeri$-W6<#s%AZG5wg?=n0Sm0V9fkM~OH<>Zj?Y8Eg3mP!b9>&jsFXwhouroDjjS|xcEgypu4vA3=_toH_#`N6<4c^o z;y*G_!38ODbKHy~iYprjEC@)}bHE12*~4W^AIVJBFXfqvJ1Q=G_!90vT&zqWJp3QV)!%VNSRY+BEanykY&)<%zjyItUvUtR0}u(D1$d}Qw4j3CS9P8V!&|7Z4$T0{(k@G}NZFzd8WPA`>`oTR>+1 z*n8Pm65UjFSTRjyg1O2*!9cU^o9y z_`U$N*8tdfKx9)>hu$Dyd_K!_2>!o!K$N&^q#EHL4HPi6KE2;J`*$V4OP0p}j(-8+ z`{I%R&Q$^*7rhz)BKrR%OW3~E9mpo}pTx=0Xe=ZMr*{00SR5Dj|2s(;kL>A{0_tlT zOVt>^&MIkvt;3zHv_(krFE zvOJoZnZW@e@|%IBE@_G({54L%NBJkVClz0RW<0;$Q^R1VCe~rK6%YY+8#DIont0ZC z&{hM06||Ke*HG7FXp~%lO7SZw9F0U#QSs)k>dQv@X}jpTB?d3F=6|Dk3j%D3=TVa3 zfvee&y)OqCX4BviJ0;i2pZ`4G9tOBLgByIrz&!4LJZx$4*+MoB*thb|^Kxw6-nR1F ziW7i3H8Xw>1Pq9OZ9P5q$V^ep@*OdNUs4Q1Vozj8UloncewX@zxRH^Tk9KGi$ii|X74?_&z^Hq{wgr( zOM=cAi zUbctjl+6@p;n6&*h1M)fV}da^Vr4=Zm2abo@6kt|`MrbyFK?!Rrq2rW6vW4U))@%B zE#-FoPF#7u)p&(XYaZc;G0Ehf8$k;N$aUuZCZYDs-1pXuer^|n4kD1zT8k~xp5oXv zG!;!wQ!u#hA5EZQmSeydaQ5@EXvE zFjE$7a&yF}7L@agg=y|2@=QC35(J-6X3fE#5KNLxMt*hrOGKmK*m!eE)61NrY4Ga- z@NzQ(-KQFDx<4f;-(7(~=?8@^BQ!(jeRzOFAFWs{tNc0*gmk4o%a{4@(;vC658pb| zR5XKXNqQwa5?QWYnGeF<3OZQlI60~xQEIrWkQ~T=$4gb>~2SVq`O(RRoF8lo8 zkhgLTWlW8e!N>E_&G@mZ50Opcpf}<_c1_cYqP{e?^ z@@jOOmG0XO$SKoXJehxX^(5q6=@I#k?Dux8|ITiEk(IxnV~)8e|J2!mlU-X{_5jy(9dQJO zRWLhN`eT-SQD)=}+q5V~zflMHHUiZ7xnY!bO{ZYT;sfx59|_Lg9X*4yrAXzaDk|%NS9{5!Df*8i4WL zwP^%TIZG36Oa3t0lyBzT4$@pPIexXLz{Zd;D7I~2Ul2DCZF6o?mW?ZTq^_ersImKw zH;N~=(wlc1n-#c0XMT3Tt#JjVfS#4b9b!V0XLc~|9YrR=C(~ArSsSap;=)Mv!Ql$2 z#rN;!!YbTDKF*XPx7P>1?TvILH?-uzDCW=hqGDIJD6tCOSu@k0R8u!dYuX`JlF`nE zRp}RB&Oh(EzRD^N*zcwh5zJ)jr_-yS8FPkzpC@)}5B1^1u&TZsy-GkpP==iIejsd9 zJ8&o?>$!MS)RY$m%f^x2AqZQlG~$66F>alv2r5CH)O$Wgz$;G(O3AMPy$Ir2{=VpZ zyy~Avy{e}1AkMsF*V)li+k%{5o`4`M`cA{;Z3OYT5890`FBnZb?DcqWF@NNwdZFQk zASCd}ftt8NO=k3ev!s@Sr^LllXBS`AKK~mi0)Y?}6QI*i%KAFB@h>$oy3V!}i)8n& z5C~KU!1CPY2J`Gr>)~Fz^LwS!4;}u7h*rAmBlkU^lSFm$H>dhL6z73RBy!`qHo5Fo zf>%LCGvVAO4JN$L_kXTU;cov6-GjH(mpx#W(AJQO5((z5)|0c|X)rl4fdo}hXy@a` zc)E?Vo0p&v5cH6bL;*8-%-)jnQAuWtjXo*mBOq9+oN*!Z1_~DE82_(3b)$g}KN}d1 zx=pJKuMm`}mLUZ5)>yNzSS&oe$VlcXhkf^y#_4WXa!{d#Df^s9Xm|(5Osu zZ_?w{EWdpm>Mj=h5Y_Cdc(c%!p!4zF?hlu*k3lv2>rMdYy?V-LT*{4j9+N3TO?j)T zYAPny$%0YWcrU>qSn59TpauTEFNO}~Rhzm0Uhj1#A=KqVy+A@}o}cY)M4K3! zpB@2N=G^tX>l|!tzR9r3YR>;3QmKCvm`&Bu$!87lkf&O+s%a>r@}y9?>k4YmEn&m0 zQ-;-CiKsGK0EKAfe^=c=XZ|Z8Fg0^Bn*sMGO8ElSgRFbULqI^=a*-17H?jg&djG5) zL8k=kzbnt39(%crSfM-)Yrh5xV2x5gN?ij!ArLSqzr1J9SgBi06}_%X6#147jNB=& ztu3)A^ZFJHOePV0#tjb|!ipdB0?($0|$AW^$ z4;)LurEHmL@i9>|W$_v|Y0m~)Y_bHSv8RR8yOKfI{i~2_LZ|qI2$jGk1dFPWV|859 z>}g;^f|vP7$64@vBTzSj*;L%Y{?y(jRQ4nLVY?JR@{?08|KwuL%F6;zOLi6nVrckK z2^C_U;j7Z&E}@ICeAGMA_ffX`xl%vlI`l87&eV(fBKqtGRr|FZ8)l0_*{_Pl>d54L zynkmYScjo+#8*AAPN*($dv|KbjAo@HusMhL@SHpm#3J*?AX&X6r1#4m7S<~DVv(7^ zHkrXUy4X>ngtW?SNjGz_P0HK|jaXXzTy&=>)aJ1`}!-W5-nGqf(cgUTS=lbqq4-t5$z5*}TnOj;(HmtrPm>x;KxVA;zISGQ@u zwUa6{~ur?F( z!$T?7P5o)Hr8KL|B*t3@T~CDL4ozUehA=mbFn8?oMWu~Bd;mAz`3S>b3_KsMxNR+X zZBLqNVD?#0Gg-!*yxa;bGxR{RrD5A~E%WtozHZihD4)^bj!r8^IHIsVCVpF$OR{0R z@B09*t$wPX3xwSOjrbNdKk}7<(;`!9mHM%>_kDI#pt8m#tS33~Hf=N8AgoQw9Y)gl zmmBoOaqQWv_?#bVO6FyoF4lKvysu4jgV}nW-#9PjZnkQ>EX5#w?Nbw1nMdZ~*F9Za zwr}i2RuxaW!c#yy(!J|hK>$awoI$2Im`^d2ld17PhY_?zRxNl{8J_F?+onxA^ceUn zjU`6+UkS_pN)}VY`P0X?383Szg0v2ED^$e|!ILn*k3*Puwb-Bi%-ws5f(K_gw-eSp z6arNo88Ik|iT05MRXqAdzYmYx4cy?;EBLMhZM^0C>9tQQoNqWojFQ*3W$qtFFk%vl z$XisTdw&uqb(IQydfz>qVCC%f0=Wr1Jh?FMV!UM{ayb=<#hBgOLi@A>pCFK|>qtjahnl6PrDjBfmT zrBm~}-SApu-QW$mvPtSR3A-D~c}xyJ4+~yurEY$hBUQr?kGv7Iht{bKZrx-rb zr>g7qWmAP|Jls6_d@c}g2%_^!W}{LQRXxS@WqmTM=_f6TjqeL(Xlg8|-VC960SY6o zCboU4+Ot3Y#V_1N=&f})5H+ikyr806fiD=}lXBP0Gh`eaPzd*;tklZ2d%Wl=SNKgr#>4+%hz{>63h$9-xHJzN=Xr*V!rr;^KKONoOVVO>|9O_mprnP($ z%qFJQ+8ey~nT|hotv!LV!OJq$K8Y=}^Hef*KUV0=ji*6989pRMDpOH`a>BG?)>r+X zH(|Z_IR|tvFb7I`l}n=mMNl{t zaqzazdO%Ax^#~@OllPBzj2Ho^1 z4&u97dn#MMyl)A*D#0F47niXq=%gG<+04>HFU`oH-0dXO6s9fJ>U<{a2do-$HZ(-voVB z2(U@Kkn_?k`cdAq2RzZedA=a&YuK0Zr2uliX$WLQLs~!g=GP~>_I6Z0fg6n!dsef} z`nQ-L1g4hIMZYdy$X#kxnk?}Q;5hP7+7G|Ahe}vEwJoT~{y^K7u;meoq<7;87WD{ zy`p(BMEjWYT~=0hn!1i?6S;soIRSy<(|@Ln`cAuB-sZ9Ow+B~d&d9L=Y9o0;gt4sC zX_`q_pE#Gg9{;3JZ~W+dOYuP*v42O|ObHQPsJ`|anH{EhK`ts;1Xp;x;D+}-SND5~ zS2bd-T8ed`kk7Zd60Ljy2P_7AWGRvNkJ0UXf1LuyN1q9T6 zdb`%=z`-%Cu7h)g6(TgeCsAGR0b=B5YX=AD*um`;dK^B@Yu_$)a>+<7jbF$Uks*=^ z|Dg^zstJNhA-4fJhwkQb6U0B^-w^EExm}#@-wlvwTtt6zTe4}_r?sw_$0MF@Ns>5@ z`2x1z7P=Q)RK`-X0VYKZD(lw^*S8+cc|i=giq;vU+^Q)zX26hGj3V{;u#tHm=IE=p zzHs+G>D5Jn_(!E>dij~N@;3WnI^eRH7_pHm&HI-w`A?%m8BHj-wRF`^L{gkr{$~$S z=h(WpR2>^Hc|s1r-eEQqdI<^YWsZn(Hht@0>ua#92PteZE>b5$PqN|{w5I30wMo6$ z{Syf*QqZcopVt>uc*{)Sl`UIN5V3nYH(b?fEiqx0@Lib)rtI6&71%l)Am)afTKaiWk6T)2N z5>}E zy1R!^Ln8yg{<%nw7|Mj#&*KCb+ckS=i8^ZB$Z=ox^n;3eopnz_}h1 zft7Uihf~-BFkLA|%JcdS6WX-??m+`YfP$ly?T{S9z=Os@EA~L#ij%Pc*yWch7QOgE zt_8}ST1Wimd=$ukZTK8ZQne1l>yxDpV&r6=@%2)y7(tB25*8*y>PL|ex4^F(o_lWf3=Rl4hH{CshWGGw%x5GlY|KQC%n@cFKg zM5F}KuyKzld86&wfNexwASa4~`>CnxlD54_y$*0sdX6M%SUzha0*;|Zg_QjP1}G5n zH9N-87WHYIJzA*f_0I~u>T;x4{y^ZahHO9(ALUi5{+WD*TC>T*IF5roKpcKvG4Q06 z^~k-IV`kU6mNn(XGZ5t48Y3e3gJIV(3({nXrjO5^(cuj3TysZ^8j2p>G-34eq@-mu9Pl1x!SIsNDU>jY39{j zIr}+PJ<%UxG&}3^n?fF!_ErJJr>vS&j_ki6>o|(!hloiE9-)1uWMSCsCLtuRxu4lR z;hmTX1sB|MR`CU)nL=&BdUs3E)Pm87i`VX|Y#H$=@z@U+yT;QAmIXwwVMyA*SqfX= zs1tfVssk?`%E3>25&4voeZvR4O9)o?4gqQ3liVWQHZYZUvbX##=e6#yKCE#o7?*rh zkH4506a%!F9W|C^gks|?Z7aCIEPwRWo_WL;m#}TL+wNK9p8b|)0~xwsWi|!xXf1?K z0Gfcdrl2=ZiXSd;e)y^kHNgN6XmigNQD32n<)VzrUrzd@0<$<~5Q3ja=W}}BP-gyy zrl=mE1y(J1n?^88bgk|E_w^gk-AR0r*!Q1C?0zHDR8f&8(`4f7vQ0C2Jpmi2em1z1(K{N;POfg z(E|fyq=rLZI7xw6S_ulIp1ORi7xWlc4ljm|XASJKXEG&&H*4UT180W2)f*h4*pv>} zojH@Kq>BrdHySvlHuVqz9M5u9#bz3IkCOP(# zP@>t~CK%-eHt}VN-gw^e$)ddWWz=G)98;mdqr+P+n+H$C`rHXU{lR^$=z}mO4~OL0 zTp?FUJz~Sh95s^MCWKkA z33sY5-yi?he+cWK0?8~GYJGPEiS&+$HU*EqMo)1yS-)Sij~+S*`oQKB(1qem(4G0Z z7xh1e@yZfB-y!8euHe(Kb6tB*f06gk!V)jao9Lzjdo(KXw|XLd=_ z0alCBZOeA}>RI{CqymB7%HS4|%Oc18&Zjc10Fmn(37Slqpl4CxZ>c@oHL08!oq-3T z1Np`u(VjP=uM#9SO%^8814DAWSMm%4j4$ zBthLOSHlWphTJOczTtLa1b!CwE+r)2dt5dx3$VyRZQxR-vT+DOr{B-hhroy)0X`$!D=_%d|s9mAe&wVI+InjMD0;g#A0F z6)PZ38jiWLVYAKWu}S*+ghlJ%$Gkb2)6c3(Mbx1{QjTGO$<=nmJM`1@+`K?*XUgtV zy(_(Af9D?)(?nE(*n!JHO&LW+@I*srfKUkl=BG$pt9jKz3-|5?<(OmEe9apto0Ovv zbo4&cFE!l?L_*#p=R#fExb1CMpElIFbW|Y;?2DCLFPHU$B4IDD){~Qa6zT|bzBExu zy7eIp!>p5yrf`ss50VKz%LHiNk@A#px=k4q-iH!8?Ia{X5|PST7x-4&^%j8!pLA!o zB>)70#v|vdWC?@2y>*Td5!KXZ`?Z-?OUI~2vBrAhPeq*L&`p-du}gQ3NV+D6vVN@! zOA$88tD$3V%ATG?Mn9!)>+jae;L|8Kp#2p{#?~N z;L?Bfh!-RvCg8}FeMF&gDZQ`cVVnq-g_+UrUPu-snnY34(6^$*gPF`WF)HJ_d0e-BiYIJ{raQCzXbF6WIz@#NaGH0xU#l#gR8-d2dVS; z@aEA*!H#aM5A7^c0z!)8SpM-|TyVv(Gz52vl5!qmx z9RiOmj~wDlDDM`75yULwRM(X{+*3<+oT{!ae1D{lo@HUmCSmfM1o2Nnw;S^yhG!bA z7LoF{V{|A~MI^EP2f~TKQ||gfNYh6EsCvIzc6i&B?_DQd{eTx2!DAb^XFU z%*}JJPNMJcxXqd)<{`W4L-`-_`nL!qI>tpLH-MZmAW>RI&WO0mqfQBLN>w%1nD^ba zcI@Wv-jnh7a%AsAQ=)^z;e0v_-)N+%_@a8>s zY@^HXhfwF&Vb8^x0S@O%xko}uRN@HHC@T3)D}VKpGd&D=1d?cbBA^CCL#~L@jRQut z!(0(1rL@k8XFmsobvV?aGcQteHnQmmIBx!(03{&k4Nq$rj{$ydm`|FB@z~})V0Yt< z|IdYr^dSGdRK}$%UduIlRSqCei;&wvbrF;HrISw2oEj@DWkV41mx$*?UhGScEiP~P zv|UoitRh5b=4+{e)Z%MGO(hy9qTDJ<{R3aS^SG*pu>|xyXsx`Bm_YHhf5qQPagV{A zcUjku3HarVa!-`&B#NJcfw<4>pewrQW)H2t6A@ia*|yUDk8O$kb5U(GeQ^lJm9Zq* z&}?prgQ{;>CE3c_liNn_?z#zmC9LgGMf-2`r=^ChlHJ29zHR3l&!z+E2z~bjR zt5c5-UUX1mlHR$xM8HA8}Cl) zwL%k@Up=6f5cOegH)!5588TD-o${cCI%XU^82p(=eYKGS)aJvhZaLZ#^HwI4m|Fv4 z@jj2MM{Oux%uDLJD19FXHf*15=H!EzMQ!Pi;qRqg3&g)f(ky@A8DGh0S~wx%IBY*H zhF;g6OEEOl({khH98$fQ$37L$dcPi}XbD%>HO9xEj~Ce+vubh;_xtHTS2ag*=F9jv ztqRpd-y4F^Xs*;<{J5TpeI;J)>?51+7%A37nz<<+8EYk7B$5$)|AV2?`Y*rOPyd`4>eA%izb(@-Ss!-E3x~rO6-J8HB7aI`iEd?0<&?Hq>k= z2VO`eAB3j$2&bsYX2`K0yfn1C7Mxtwzpy0tIw|TPVk)oq;I(im*XEw2YVsOJ=|Gas zG&R2!{kWWGJJn}6^Jd+yxcnlo10}LqFO~6FT9u?fPG@$&%}=F=Uoup~fV7TvBjs^3 zx=$0CJOtMidfw*`kCXSZ&7`P!67s7#A^UlW>cs=AB`O=nrn37MsZ0v_%Tzf{p8VV2 zf8g>b$l^r9<2R2}k8NC}+ZJDEcKS15)E^d|V{NK-{m9c@#`Wlzy%tX1Yv$2Oh@>rN zUVc&YM7ZvaAIQ2*t^H0r_eLa1Y<+T9s|xtyz>dFI(<-kbEK3~7a+|;y3e`BoRsFBwNE!Eb{`_(Z* zR#)6J5l~UE?(wEz!PLFc=IQPj$1kyD_dr%jW+QjCo|pFGFIh|W$5nPBabGK!e9RxF z@bt~zne#nMaSN_9Sl8N#Oz20{IZdRHkOt<<#}}&w+XvMkcsOf=tM4csN&1JV&&%bf zSe_iwzRo+Zz=H)5de{y60{@Z!y zpN+0Ry_NsB^Zycz;D4Ef;C}^!fZ+dEW$;DY7uYa2v%JX95Urn_!K_scY02ZV>shz% zBo>9D^WDp}G>&nn2hi9Me3vlr=^yRa>38X8bHuY0lfk_tN@Q>h0UIayG#sr4>&lfvhwMDY#NJHc-iPWcoOud>iq0 zYKIaUP|uc~RkR}&X1%&Kp>BRM*SJwH>z}7@Eju}cfwZ0};f$DdNmlemf;<&TX|lKs zbhaCKg9QRpaQYobAv+V2) zAMgUv_d6w&lmwifmk8Z^_5yx!@z%gCHR&_3t?^HL^${pakSK}&z}Nn{${oMP5U|Kl zLH8gIM->ZZhPPL_OcT{!^^`m-2V*Bl|Qwb`=) zJTAR7L#l-buBCC*9okmOVJRg?SVEvwCYNC@Yk%<4{hBOY;)WiZ{P$`DLCMgd3t;Ez zpEhdgG06lx)vexM`s@I13Zkc!A!A+dh8v}^nFqu2Hd_f8`T2TTMw*0_>Uv)_-kM$l zkNgjx=;StN+g1rQYrFmCymxuIn(R1RJ(#Z!$naJ|&R2{DoP}$=K#e03O1L<-GZ#msFF@}1H30JrTkhcPn%I0yJ3=mC?6^gi zk)vD2D&wE7E3t-36E=jWxdY2U!SVJSnUO7IIT5eoNvjD#W^Lvq%Qp+>mc zY4Qtc7|8K$LRkhYkO9pLj$FZev#IlEGlO@~WPfH|4xi=@zqd1PIE@J&XpCD0!npec zs?QYk0t}nhH|_DZs#R5^{w-pn0ZSb92N8N}{Gw-#=%5M?i@EVOcp-!+EEhs`IeVIO z?ISx@I%~u%2^6*(LPjs%RITTO?TRg34dl|ddM<0p;7b}CXk!8d_J21CMdoa=higrg_5eZJn36+NRYvA1j$V`>GLJC}+{aPDf_axYVFV=**q) z>B}Oef7?=60g=aB+2bwHLOycxcR&0kbAYUGjbTHJ&UY8_&_b`@K7U{Z;(l!)CeP7= zuB)uX6uW0j8xCxUMC&%BgZ3#kj@$6-_Ojh4pH-F|N8*y^5wRe{KWn?}*+~ciz;`-m;Ya zG(k4$h^9~?gFq3X^mpO!)$GbE{s=vglKZeB&qea{2Sfu?!#wumMs&w;Wh}K)GE1@A zr!l+s_z!?0$da1Sb(PXFQUi7-o0lpkjuDP0vqpSQOBUL7tlP7!U#%cB^-KsmR>a1K z^QT<$pVh32+y)H2Sm)L^-|UyS1vpWv#n`2{LWYzeQ>;W3K^&@E;E5x|99aWQXLJ?z zX^S>Uu-oa=Oi7}X@CPomO314fVgt_+-KOn|T56|l4Q*saWYG>+)SwDv1T7-Dpzq3M zP)pB!qq4HLE~X5a%9?fZ*r^=d_Pk_&Uj^?#a0)LJU}?_GBOyt zr$;g0|AYK1en3#~eWwL$y*z7N7m1RmMYu{|$ z^8P|ka%W3nT85j54hk>qE>4JBRQA#skSfotXOazZG$qw+%uV!7 zPVG_R79Th}+0NQAtKw8Yn7LlM+SYo6z`+kKrYGR%uR=!hhb$e|e+`&sNl$;+KikzZ zxKt?B9TwBM-1=V~{$;qZIiSK)tu%jj8ea_;74)zqhI-eQys$LY^%0`~ zjfq7(8wqi=FE|+r%^U08U0#@;DA0O|-ZGp*pRBl^e)-wepzr{&XO|13%P{a9hCZaL zn&(;>ogk)NkD+No&t**ObGF_3ybICj4%laKZaq0jx4`e`?3nYfP4;O5tg<@Xgl#&t zhV70FAhv96z$2iN8C)oHyV!brWnWA6D)Z(R_ORz{kNd{9iQlJ^wT||}zSEsf_$HCT zA&p5Ed{n1xakFbdbA6V%3*o_G@SN;rbj{~GUCEBsiCg?K*KoiBuhzfum(gVz^$Dr5wI zgdIizqBerBphBz#oK47&tm>q79#&bL4d~~>+k?wj-gWEo;}NlT!yq)E5Bu%jnSX|t zlw}93^Bd}MQrM^ZI~7*Q<29SmUsyQM$NZ&Ur*41~WqC4ep6h?^Q5ezxtg_}DD;=;# zBit(Vq?16o%SZ}k z%gKo`o**?3#)Y<(ESxt1X8XJ3)*oS$@VV67T1_jP#Q5pR4>e6%8}d(3^TUrF?(C5D z@X8`4X*#?#=dW*KVCC$cFfvhJ4(>;6MAG z25*h1w4Out&4X<5j%?)hdu0~$li&1;7cO2|tlutMe2Z0#f0l6^8|m?HnuT}w_iCmm{O}bM_hUV zwEb@)o3uC*5PXiH@8Ms35M>PJoyiXM%C2{JoGt^=v z4@ef*U%JXqwwB=OX#Zp%vCBsxYE!#8C#)`uw|7>w+)=e-3%)>N4sIIDyt;@3|i>1!=v^(_p%F zuLZNTH46Kgj0+dVLmG1NAw_x3U{782%tbg&(8j^EfzQRb!&9O-&Bmj_3^8)}eb(Sb zX^e{G>-N`@bwJ9oN_G_y(#qlmb=} zLuTo>{sD?WBKL2o)+62QvZ2UsvniNgExUYCa-@2~r|Pn1@srmzLU%Uz2av?u^BjPi z=Dkl!%;J#Ln&&bLfAsc)9_JdS6s!8?;g8c*e<+qFw`w6at;wUavOMkYo$U2i!n z;r-;-*A>?xdC$*W+y>If4?;cb5pRd)$^=ZH>vX+=@-uXoUP z%9H4$vHXoo2d)aSmvW`&^G7E;aM57~gGoT$yt9N-%CxtXY;dU2v=+! zsEnn=2?CBx1Rgdy`ZY3rB1C}CEz}6ngTh6a+B3Va1FjsFZ)qrh$N_EVzmP93-n(|U z@35HvBD-x^U#W5Wsd;F9HN&m}V)KLoH%L*L&L`$`@kY@rsYQRg;LTh^5o-hy~5nIqN?pbrg^*x4u!o z>1IV{#FVPb(OJ@(_Y%rv0kj=e1H^wDXGl>%aNDv1D<_(8nTM`G{0FU-@r%qTvzXB< z{3!dwO}EH5RJep9M80JWi5C+E`~W9+Lm#Y~zE_gZ(LvKLM8;EQ{$v*_i=M^q#zDbb zkOx3uosA)Hluw$~t!dVOs%ljvj`ug1UdZ{;i;Jb+4UuGlz@DD zt{#~=K{nSRlvNO!cC=GdhHhiw*`ljEsZ0a5orf?qIsNPW7B0-qmYTuyuVYELVHZo1 zunW!lz$l*MI+)4m$i)IXDgYizOOOv40r?z*FBWXGXmMw|)WV9?6dTZB+$uKC#P^1l zS&(Dc;}<)Jgg_`}r};YNn-cu2jR=Nsd%X6T8i<9DH1Q+WCT+U(&6eK{YmmWdy|UQg zw~;n9ct2Y`Ap{d~N~o{84wbzm+T?719`$l2zuU50*GoW04B%Tu_7)BR+l$GWU3;LE zCA%qR4(#Oq(=Jb{cyO-qyMu-9U|g5(TG2+C8bVqRW+%f#FkSK*fJGNBrD+o)rnQy9 zyachwZ=yj^P2 zEbt?2*Eo9n_i;28O6nQ<<3E0$g`<+zwW7snFkkz7bKEj)L4%3Q0g&~8?Pz-;LZ^Ge zA6D~!!|{w!X-BhoiK0~{(C?-CU*9K`L;J}gLp*{*cmGA;=N_QfB?RO@1M2>QeLK(< zuSE#2p1oxmdfwX-&Sflfghh5tWnc{j_6W1-xMl`^rOXhf7>0mv(r<4hOt z@;hm~nPSf-UcvG-103O|l;3<-7O>hV;X5zu06@7qY}*uy_a!E!mvsn~oos_k`u!&E z@;U~WzI}?n1xDRC`m)PG0jmZQLMT7}KuFGEMtxb0WO+sC$4OKY7x4wo)UYnJNo+!T z@8C~x^#eGI)EO>|ElC(W-Kl981B>+Gw@)x3!c`Jda}Qj%l|bOL4R4WAA?|y%5M5ko z8EkuV729>Q=u$6vMS@w5>)&e+J&ch-wSe}*=gq5z1P%iw4nJb`M1Wk#flz6ZQH%D} zD(XvF;*Wvo&`RzdZN#r~+2bG(Rf=z@Y_6n!LWOULWQy^S&3;THN%xmhnCBgUAb4aK zQ6&8)kxzEWf*7LjOV^t}%o0QmY)cU9tey?fvk8(#Vpfsxe)0#o1pY6 z=vLTMqYW0G(@Mu^A@smBSKa#Fb!ZWJ^fByOq@Hjb4xZG;k`^uI+B3U-L8SvkUWH3x z&;f7aCV7dVCpLyzwCsY&F>MkOu-(Wp#nLy~B2z^YM^)*x@H#Fv+L4XHr3m%FrC(k0 zFCo*i=VBQ?jQpwpo}U7sBu~<&Bp?)4Iy-MNs4IKr=j!C(Zi1O`ycV4YQcP~Gx?it; zoBa3@=Ew?!c-xiQAKjK&qOmF#xYo58OtU#ahhUG_lV1``_~NbfeX>V6% zFJt3$1)`9}+Pyu4X-?wM@7P-N*Eo*<~rABG4-v% zbo7%H0&ecbt>rB2Z9<(G{W$vllt6{?mdQo=CpK&P(#O$1N3=a96DjCF{z(-4tiN<` zzE1`jj)eN~)}t8YbF~8od+I*99cM2py#6c?kwVEkj5(cTMr6?@p1I&ZzlG{}3AaIF zDyBdMl|~vRd9n!#w@bMUv6{vc9v_dd_r3_O#@8w)Ph~{2jH_7}4F%$wfVy%vdD;=k zZBO!W$v<2n7dIwLF#J{k!M)JJ!N2s~b5l*9n}r4LNcM}f%^N1)nLXO0vSNY{KN8cw zp;RiBxo_?gsg|;+-t|hi$f6!Erl0qn+$5Fb?&Bg;y?P1%y0;43N(C0u`2)>EX%`Bl z*2S~&rlRTEaZGQWFT(!sd4W1~d;Sn>b!a@vEm&iXJkA^ROqO0K8<$?+N53EP#OS4s zP?mU8l%c{E992E!sS6pt?RNu~nD=V5_$Fz|1ungq8aWnY1ynynLvPq~vyyqz0lAp2GB@rvp>K}wML+YaqT*wTY45V8 zaRK~YE`7fHa1(p03!e|elE1I0#^CW;9nwf_sY}4FY_aa$ySEwM{&fZ|FdKj!=g<9m z4*OAU?qYQ14pHjEhbXouVJ=VaCcn23pF!CK?nJ8cq`cnaLR||Pe-??%&?TJcwtaz3cyRds4kd2 zjUBu?gGJi?c-}b&1@8xrR5dJkl->LHm>h5h(+seUAM2#wnl#i}3=71;wuktbf&}Fi z>eX&7QqQpWEoid8edZz21*a)0^>&&}9lkcWnx8}cmKsFbq|&Jz4q5zWw^-jb%>c)= zFMMs;re3}AFWj9T-Th<)y7ki{Tusf>M<1U&2|#CBozCdvuZv|z77*1KKQ+3^O%~~K z<&kO~vWsPDcTJ97qjIjs0HX1%0?vQlQuXdX8qih)G9n-n;1vC6(2*i=?!$o$bgJ#1 zK+)vgYW+wyqH~`298c?ZI+}#|vm@P|c8V6ebwqO{q8ci5ki+ip{{<=RPP}{y;f=?v z(`Ba_qEWKdg+k_K7DJb$yzRW8$|e~>oo-Yf|A%u3!oC6dw4V<__F8e`h$!IccBsY4 z9s5`+8>Y)ckpHyK8^Cdl&gZLDu6i1;^VbExgsHdX^BGu*v#|cT1vnc>ZlH3d{mXAK z6IV8Z`M5cPf3@PYo#Tq|e^U{JEiW=|+$2z8HYN(r3iY@Cu{50feRLf+bMvEiEa~i5 zW~=%!Uv}dh$@f(N1KbVN=5`Oge;&+68hzi#$g$TZ&RTD(2lvP43408b%Co6z7(R&; zpXysD`N%vy^J~0=_xa5%eJ9crfZ85+8&u-=xO-*I$^WKg#`kMH*LWE<4%eu`-Mggt zJZTiQ+^bK^Z=&&L2bkXNgFo1?$(lqHyk{FSMwV9w9j4WXjg+D^sRpKdLH686_cfUf zp7IZ~-GW`?nR|E*6qOOS@O1Pm6&y2n=aC18YKT1i=^vbx_%77QpDfuyD_rc9e=Hr# z8x~AOEhG2yE3Z<6N|5F^Ki=TsHIx2j^x&1idGI0}vefcB@!O%X{|IWI)G@Nch0Qqo zKN@#Yg|ZVXHE(^D0|28vZmy56)AMKJz9LL77tqT1I?0oL{nv%Z(k2BDd9_BE)Peb2kl|C;o5 z-WM3(VhN_E{tlbzxHfq0BBU({w`%EcK%Ei&HVw-u8;5m}*hkNNZFK1G-;G0}h2MN# z(3CY_?7IJFTrxu-nRv%#zT{T__ib_6o@x8(9get_rqSz!?v#7TuYAe&%OBwvf91{# zP$>x=CLh9nH)^56uns5d4ub9zspg{`*|Ku_MnZ>Qqa~zF0NMDrDe(cR+#8}H8reNB zHwEN5Ibp3WTDeu#-(EV=Za4^rZkIcJkU+Vvl6K8khDf6NrsaxjkU)m+ux67CP(x*~ zFES3VeXpgZvE+xT+kGUkuxv7yW%{4MftBWxApN{Mh#Z9a>m+HYxTz?I@LhqT#fthF z8HdG#YsrntUp*$KY&tx6vs3kN!$D*bcXs6Z`8LvIUy|N0PM;D`AXVkc8)Z7&oXu5O zN!k#VErrhCJKX%k7Vp&nbXemjm_~mkpkLG2W{;Guj~<_28*(~vswRaSnTS*a%c_ta z8M!%rv+vZRVX`zcQ99>xDAiGy_cv~(t-ns9ldh6oo#thn;Em>f74T9~|D@%Q?*y5Kjhy4EYu1C^7=&C0iO>K3Ea_0F?f3cRyM zWuNNY(lmA^<6nFt70i*ob0L>iSFE2G|Apv=U8RGLfx<$;u;646ZgGicJt8RgZXs-} zs>f^5bbio$nzPB?gG!~2PALrB>11y0h{SF&zzGEn!2k^?r(cL>h}+ z#elpPxWcV^bd~`k8lZMHf?4}>tB0)h^OSzOk4;*izb>JjPeq~hqU-s*fu%f-w~%=c zQu|pm53qxT*LFnU>28p?*2wQClCD|p0-!3+C^gN%lPTp$+kMA7_neh^-z^9oocBz^AJr ztj4dC1{e@URJ-Nc0UtdOn=@Mq>X!4B{+slyS-N!_JKmhM0u&|7>Bn55-kNXiC}BMi z5mCJ;_q9}Uh~dD3LD5m=_pc_I{xovFLT|9@Nr&heA1loh`^(DS%NF+G{&~74!DDWB zy&Ajf8}Q%emYJnTWclM|MwTC$D)Tg=vxcKNI<&ly%X~=n>|!ck-4K=O zO_d}bigHP|t7_Gn`L%Z}gUD5C|rCbgtKo0g_2hmyb;NyPdNDszSiFo*3$9om+xB>0WB<;*;t% zLDAKKWYTj;_xEq_&3K=z1o5`k@om+LW$OVF3Mi+^X=g+G`WG-1Iod~h*_&uZ1M|44 zSyRK;d;7ts6_4xsV)e4;;bM-z+8c{+nW&6Ak5D6zHU>khE`60OR4WX@DXW_e-b^+9)tcw41&q*}z4bu${?$xbbj zIURhWR=1e^v_l>pFl)ZC{ieLBH)L@(Q*MRwIMTdbQ$JyC;$;MNa%%eGM89v2p>Lb+ z_K=%o&Xp4X;Dgn(1{{A8AIU4Sv|;Kpa#&7{q;r=cqh~8&R-j{qU6q^O5SR=qE{&Mj zNnWr|>D|oW=&G6fWkD6cQF}f=ovS)ML%3M+pSvWW1Egu99!Im%HU?b1TXAL-rKGtJ z@lN*V&Y1QJy!s|XY0BzT(M;7~`wv470QvfcL-XVV)*P=-K2T|>yH_E#`~PY0J;Rz> z!meSD9?KELf;4F=RuB-RR}~cj0hL~((tGbsL_tM*uc1ij1PC=W6(LeXP3Q;#LI@CA zD1pE`QP1;S-~0Rh^<5`_xGvb)%)a-`J?ma;%}i0u%i#~=PRJnMv;n5xU5mL&Jl%k& zz}mY#6ZlL4=tAXdT?VrC#@;XpAt|ad_C3}w_Qs&%9Z|1)g*hhu2w#>;{W4F3E1dvM zw%=UP8t!CJL4g@FEXjOH_fDFfS_9>Y(~owke_#41&9-NZ?1vt`Z%7Fp=v@pS-C;-P z5Qg|_og}OK&HVBQqkdYm_eywNRtV`>KNm3d^PL#I1%vrRGVZS?Rk+Nvtj6^1N+$`I z+bVc9Pn`Sy1IuEM!W;}E8GSrvg?Xa7@+n^Z+OpqEZ&ihVy#NGz4@(r}QNEy(e%`;$ zh`hDkA$jP^(*U@UG#6iZp3z$^(AFid0$o4Z)g4RHa%p4fWdGF14vtq#-6#2r)PM~40$FfrFdrA32i$ayzi1>os zj?8_Dqx@0^h6}c3RrC5Tys`o=??W_pohzul&lU(D9ZEAA+HzR9FXXiIl<8e@kR$cd zZm+Jm$ovfen_rFFwRNIfyz(4ZE0Q*nz&MD$#_P+N|KbbG&)_6^#O2)@8HJZEkc-a; zcPTEZ8aVOfUnCQ0ncwvB@S&S|b+aD${dJ zq;qd3E;Hn+k;3eqeDXxJbF7FBCT`9S;fMVVo}kAkZLqzZUfxstWkJ?vXO(Rl4A7JE z-YZL2-aKy!yw$Lm@SJ=ANqIljCotX9;RV`qwne>lQ|^7`$0K^)`w=Ft`?2EYv*J<) zsUthp=V$<@v2kX9>tBN7c5L49Q->6;{6rAGRQaY!#^w_`lC`AD48-clO#PeJ62eLC zTI8}$@x3iifk>!)QsxoC^Ol%`Yr~u@=t{(3jt-ZgQrkms2-GOVxD(qZE17&dSJedO z!ON2?zp(CBRpV+6sp5?=ZRgHyKN3BF#r2e2SJAv(rPv=YQt0?Z{Q+AbY~4yqKfN$` zL0tRN>ZzcQ%zf`po`K706wQrjcj-=C&Xs<#dK@PW*PXZau*Nc8Z5Nmy{Cw2zf@rOV zn#Wtl)5bN&c^S+JV`ZJ6i)a3Q0e6MVR1FXQ4tRb%m?veX9GM~U_u;?vjD6jaN6M3K zaU2h-8d_|uT1h^-C${6aI!st?I=El5(yX6sO8@Q1hJxsV)2q~>jyqTW&J zn)%MenV$rZ85`OF=&>r0UDC4goA(;A6+U(K!5V$jRQ+Z~s=zu#)|V=F^hjAick1%% zc5~M})B6d|D&CVTsoRvr1xxq*{MKv=f?%DeTx~f1oxsp;erI32WjYD*ZHgXDj@2hy zH*e&Y>Lk_5<(N?>96!O)CEeP&BNxW4!Dyr?!;z!7Q884z&oZeRHG^ngrf)xc`R`5d zMmg!ge_7%$86bhazGCk2H<&kOiIutEj_sapo}zDGKJkcC>~Tfl&Svh5oG8x=y0P5L z=!AZz$S#42fPV+?tGAd-ha$fp_D`8LB0uJ667-K#oxU_UmvZATsA}NZ73B8wi}e3i z&3AdH1WEsXllGJO|7-OwegAv=gg=+Oe)zwI5$#vEel7R<^G6`2{$Eb;(ElydXxHfe zU%v6nzxJE@pKt&7uR$pOe-rQ-8n<)kj6=>lEB&&JyLYacS$$)LpLCX0ULP{69v&EF zd8%Op?M^54eYnFpvZEgp4kfTI-269#f{g@dMeA$V2!-PZ?q*NW!&*`iU|=czsoYj`sw~V#>OP7G;an#JpLv)!>%exJej(2FWcPg;$09 zYhhdqvyd9Q;Z>H{KxWQD%Lqzp)OLruj`hSw>OE*~c1P|qR}*hRoohjX!twA*tI_3S zX|j_{L3)n_`iTQ|B^=pAvGBpgo5N?Ri#rr9*|jZe*_8)5yf#RjNb`^vo+3oqZ$gJs z@O9n-V?l$J<5EWBIaEc13gTTvc)GpLZPw-w!7J0;0)z9@8<8d+a)z1kNhgUp?AYp; zS>E=ow;a1v2zs7RUh@39P2+^PoV22NW6rIaAy^9J$q?cI&ux^|f>=N1mmX+w&{->x zRe z>R(+o6vDkUTo8#B4&NgdMVdhOTaBqpwd+ArO4pYev?XR?c7HIE{{hLfaUg2iZ z;O}&xv?SdpHK6f?ZNfFAp1=^toMS~8lQC+tD!M`dk1e~u=QY0NnNwgB6Hq4KPt=5A z^Rs*-;=8;0Pw5zKlTf@Pfj2W8%kaU+U&jrV##)1c%drW`_y zxEcmEA*&Rz*Pt)IJ?=C(u=U*&*4CUd7b)JA+4oI^KRqp%Si-@hR8X*l!J*Tze(IVF zw&z3VY7(36`-9_Jf^jL@30H1ep5=oFY$kNJ_1C#g-C6uT%rL$_&nCNPTZu&C4i=9@ z4b>nAOpC6(ycep=w#|V?JK0QZa5PXq_C|kB4(6gg$^LdV!rGR=KCRa}5%+RJ@!!1o zo@Mu``k^l?Q|`l+PFf$hcG{Gwb2gz``mtgI8p>8UMIUk-`*mXNWO4t}LFHYOkQZ3T zTTfCVbKrjFRaN`;X%p@{^EJjc`=2;u-BG-L`wIP840`qH%`f}i*ij1v2z*Cz`^6PD zgXofo@!LuUz`zR~M?Ph2rB`)JnlfEolwq2CR|31F#ExYZyZ}qSi4%4k%{3?P_y`PE zvbX*)XJ26Zi)991Q|VgbB%06>&&1b-d;Ig$bZ*6MRp{E86|80uQZ!R&6Y%jNWq(lXJqE4r{np zmfx7n<_2r6##iGWDn~RQ#*D&Qi;w#|DjDi`nVLzE(*(Qwi=nAELu5rE2VYA^ZIRY? z`RNq0wclot#;oI~dhA7Qv67oYoKVS|Dj;f%A}QZ*{BR@sRCo3Z9$1vs6Pis{FXY=b zx1Z}rJ3Am13S&y&b-noP!-1UT=_jv5=oC~qdj9>gt04L@%i+R1*Uhe4f{jLKA6A;< z_I=9YlLUWn;^78TvXg>r+{;T{xE>aVWZ0y?NtrX^7^L`Ro~@x#mb|}1ZMpC(Y{P=A zP6FZhfgHqM$F~V1x7Ym-1%t@o6>|F6>z(482G|L-jelXE!y5HLh2t3r3=G8yCL>rJE zUe}b5+EPX=%n!14B#t?Z_g$t=`ElQQfD2V=?`kuj)))k@ zm@=He!ce$*^fCW%l0dN`YomS(6W_;>B|m-rSlFa5f2Bf-2Fk*^y{5AiWp|+!n)@e^ z`embP^cT%!ckYK7kM+OU*#@a!FG-*)H8v;5Wj!u|bN@6r9es?06F%Pq5>Qam0{fzL zUxB==7TBDnVK~3NJ24f{-XxP%Vh{OI242XT%UFAdQ(=*akxTCEj}+#{iv3O{Jxa4j z0s)DRFGTQd)S67KCd5DCO_3rt%2gQnEeseJZ^xYuKCoZ6!tYvMEnCtS9P^Q0|ADd8hGquHO(G%@MjvNS2qyKKBVxGGn9Qw&DpOQR=Ap1Qg}U z+24n!ie5qQx4%0|soqlUjqvx_ z%PN!RmMgw)EWzCstEHa^Q*Q|PIJGUvC6Uv|W7ZPkoZ0-6_c0hu*=2`}^U=6`Q&6?!$2)K6{q% zId$~lz&}$*PB5a(=To35+3FLU*0*5Ej@n18`mdQ*>z*A7LP&8N1*2Fa*Q2Y>tU66%2a(Ko$C ze9VcY3;Q!Z*NK8D=zQ8=Ylm(7w(OJOi?=i1^Ut~=m+&EO7}LPY%52E!mYDVK#3Sm; zGLAy~${g|fg<}$nVkwP29Wq9%Q!LXLTtCF2s!}!LTChV?rB;LA4%4P0vErMer^=qN z#$-Y#kWaby&^j|)C_ER3TG4V5m!;5JUDMmsk}Vyzlpjz(C4CV-9VqpSX0frMrT5sc zX-CGO_zr$z+t7ae8TYE_@y^s(vkMj5yB(F_T;{6_>!&eLXo=bfbf~VR-f&dxWN%bO zG?++$l+SE5zMp5@OzSn+Ej5gE39E_zl2w25^J1gtc`WWZk1SWnMaQrL90pmCu>jt1 z#P8be%i{;cGlzouNObdM#rVqAIXmyU9Q}S1yehi4QYT!gr}Mc+lVC=%^aA+A3O5)4sjy_2&hwsx-XnZA@b zdLwa^Bw3QuR6iVAH3 zF+bN7_eBR`S^wE@hsS-X-~a9sa8rdQ=KNzKe2cs3=9`wE;H=Q6p>iwS@cBY{SyO$t zFSsh=?b*OyQ&|}_J5vA0u-X(H5C)oC+pS|2|_w>vzPqm zzGk=*myWy6Xx2>$VT~lUO_ZZOs^?BGi#1)xJb2n}6g_cJwHj>VfAG%nqh3e!<1wd6 zB`vHwd-&vbyi<9^Yhiv!9j?@hFQwX0zo5-bv+{)5w?z7`#8@Wh#brfaO*6*;JC0*? zLGm?xRcN_0{M8*L9q}yhI7Xiv=PvmuR4a|t6kM6*bE2;8Yb-3Tv4t!4shQ=)o%gJG zp*??+j+!CDi5OH-89~w+cOn?{>;=j!BAEZnA~L4YXs|LYY5cMp=4_<>f3T zmR(0S(hFm%%fIbs7YB!OM_0V^Z=7|Z-O|=LeQKL01x;|(vUsq5ryqO;eqdYA?y31q zUpXPZx}9`-0W*5~!ZBTt%qDg*PXDB9S>GO2YN)MOGoUY!D>Bs0SUfSha3!S~^z)yd zDO1~5*VlLC?%prb*UWeVzcZ6K>>`1bpv|7&U96q3BfW5oYIdCjHt~@Z;bPGeLoI7o z`?2zDwG@xH`yK-6F@;&a>N2^L|vV zFUBSl0_q#P(eaEf=>=2G6K(Sr8g1G^hrYeOiF=-Xxfdpy8Dt}RN><7GL^{IT=wjtRkA#fm&f?B{D`%boKsPy z&#S?#!_8$Qt;S1IJsiFDMV9tNY&Z6PLR`XUCb~~}k+HGeA-(3ZdXDON#iwbeS6H=T zVP5?T@(D+z=RH9ByG4}exG(b(N)__uzSzjYkb;4qX!v2=2nX9g_=ECfzNf8cP$yV{ z9jfbh{B#cOK3%7%oQRxybOP3@)}g(Cd!d1xE z0qvkt($#gkN1Yy`zX$nr1P!=ao>)IlU3{|N!x`oexhqJr6XAd)eUD@Mgyj~7{T^B4V27z;5GCgs;lHW8%oHP7y`jbf9r*SKtD z%Zos90MU_VZR{E4mlqMxbZ{8Vm8QZcyv?>=Mk=SW@lT`0ay+#{OSqcA3Ch8^30I55 z7L1(PAJ30B_}fkHq6;)0k+S=(`k9W!ss3*5>&JkwIKyHj>+j~qesE8|KV>hVM_oHa z{jGqVfD+=GMVozvpZ|N&N^(kgZtlCL>#*<+5l(q07*Ceu!)Z;kT&v1Y`M55;SSp9q zu)Tzsop1b@fPX{e=QoDc@ttjSlAGW7POa@8c*)z1>p6G^`_hhqOGRZjiC9yPNQ=|azb}5?0T{Lf! z<%Cz!v+X~f{r!19(Ai;=+?0s1=x8ze$dlozV#YJwD^jBN72<)2vTm!V%RaBsGyZJ1 zhp$-nV!5BT)Rw%*n`!ApK=8y*1{a@ji93%>aY&kRY&uEVC5yeBd8^iGtE+c8WIV5v z%I;w(UbSIGn!-e)jH~Kzah=ln`89y9d$jT}w*+Dnc>m})?*j*@g|e?d&$*7o zro9}S&P0qRd>N(}Gzb0*rMfe*2}@#}B$52r!Y?$RB~J~3ia}iS#QTt#xU^uCmZPmM z?Dpa5VsH*&drjwwpbu4T8AgGV+ym>jkT@Y)vD#qUZhDKgIHlDZu;E5!$cg_JAX{hv`=^4qN(*8 z;`D=#Jgo;ND$q^N+M17@DWgy8R}EV;!%W4iM8+$G!{bOlGozQCESLJSB2A8mR~J;R zPLt;NXIVmqkJ;+SAW44=N59jF5cra7J+frfm7{ep@I~Uot5&1ikkAID4qPO zw8v3G%RBn>?%a={xfW;-g6G5e1(gJTzIasE!KvTV(3hVpEZ0C5w2a^3-cV1fcyZU$ zoatUYq5JRd?-xL(IK>y{5s4AoEP%=F*^h`stYWnRD{aot&^N|Yh_BO2+WB;){y1Zo zEq*utjM?&mkonWW%Yvw4GZzJ&ACJw&Qe0tK|+9KuwiCl@HYO_HHK+0jSe9{zePUo z8lBOS;hOk2f3(xrfbsJC%|cpyH3TBTgGtdfn*ZOpIr`*~Lf^y*+YM{sn6PTJuLycI~(y_9|(cm(+6k z7ZC?DVm1J1`85v7O85snoopiNc6N)8C03Gz3SCzsOxlSeKJ6`A@Mix^CJa?w zlfl~mgY$T6nK#ian;v!KYX+A$Oe*ls$4;2&HIhl~4n71-p_nu>(!Dt`wAC45h&1&N zG#1IX{o^uAq!Dc}xsC2s&>YX;x?zs%oMjt zJD?<|Z0zQ;rb>&xVaD3CW;^)VhZBU*^}2=qT5ZGKb{7ZEDSN;{tsd+kU6oTWVA^vZ zdFJDv6E6?Z?rQz3tgu7Yg%vHNF3374@e9Y$)xpa(1 zi$U%7xbyStzjYgGo+eH7G#NLnCK=gg+JE|4%Yg@V975FMVNDO_=WI{grA&d=N7riGl|;!&9ww-0VDt zT7P`+Uz8SKLqqv3fRE0*3zYeE~#_Jj~`_e|7`;}=}AsyN^0`%))};ujcMj1nulg-Hmo)%a3$@Q2@f0oL5VzE?K< zImcy_g1!hsXYHSI-89VQDLta#oYPh)abV> zXXqE29OU!t3-n&F4x3_1zPzeTZH<>(k{v5}h;SCXz^;2&&as|HAhX3ZkH$5+aRbM7Q3VY-iYPkxBHT5Q|$WV{%EH(Ni0)ne(O8JuI1`_1(0LX zc2g>?ds~{anP+_}Jk{(U#6AB#bYK4k%0J7g&awCHKDoJ)v9oU0?c0F3i_7iH5>b)g z%AVxJ?oiS#b3a@vwY6{Dr>w_0Np3}uBs1}l{D_X)z|5bHL#{0!d+yOS$>-rc^qVHd z6R_{-^&hh^bK^KGbVc~Y?a}*alC)CjweN9OKdtJ>J`U@f;CiKz3Yf_9z0hwm>SO86 zxsZZE!2?%b0etvT8c)l+u`6-rO_{Zem)(yH5Q_EKfA!NWV48kiqHj=8h`B(z@af%k zVLT){{-Unh>x zGJcA(D89v;ByD~xG0KK@M%J-jt1_%19$g7a2gttZd>I(T8(|O*wFT^-Y|-|C2EBcp zJc1gx)2KoRJnkw!O$FAk4AzjrAK9H|w~mvGA>6%br?u$Gny(YPD`NZtqU5{0RVfWm=;y~Ri{ zATrZG-b7SgitoyFvd~V)EV0G zq0~1$0NIgi55`&6*DuR4a5xMGP**Y-I4p#YG)Ih^_a6%q-iofc`bK!`U^@xCgr7?| zg>XB-;xh(33Cm~!6f~tTg5iOt(hCXX)VlP*@GSd+6}=BEF!zQ&#`Y$hj;$i{GYG84 zHA|<)Mn%X@+dZo6x5#f#g=`Mab>RtfoNkwbm|04+l>gmL?JP)W7X?7{$g|ws11{3U z5O3bchYxm%Jd`dd-{lb{`p?nt5YAeuq<(ztbb3PtD_EsP?y$JTH4o;#lt7-{ z3gOuZ(b#Fc=H|8wo>tW_f+5YeA1JacVSriJugtq^;Bmzx&vkC5DE1$)yUU}Pf-3+4 zWLwMss*eqJV-s+VmbQSQRs|}V3DZ&(^p8iFhqhYmEOCA5!Kze%aH|y}3+xxo8~d)s6nBvnr^4bgsD-NJNn)4t2g2jR9DpL9tB+YdPw* zDb9#dp*$CZm+oPWXPIv~U!UiC!lY9YZdZ4h@Qt`Vo&Ly9fncNTWN=_{Xq&fN3c_!K5H+qhCARTGqH;%sC?oRH_o~2$>3w3)RQ6Yjmda#`S!(;J+6>){|#mUC6BVhff6?GBw?hGc`(&*ob^r@^a!e2>6|vpy`VpvkqD#A2hRHCkMD zHIpTE(nmGP-+fZa&3z}UF<6hV-g#z;=~Y*XJ%_;j61(2iVMI^cV>*4-qnD12k;8JH zL8Y5*_M`+8;|ik>qciwg=rI^hazWnmz*`}mq+=(ucRzQD1&I@2p++8p~{A z_iM~(B=6KdgN_zyJqPM}$J`t!a9Z=w+;kS*ZdSx_ZzCrqryr|>p(jPb2xNdNFBhCL zhvxnj@U#iZ@0!& zliDS}bL8ImdcqwFJfiD_WO^E*@03p1AV}R0{KDeJa2Syf`IayDDu?^T%9*1=Ps#+F zxTz}Ctw1ePFs#*lKR}5&co}E38T7JxxB?_;z<&+bq)ryxy`5LbEeVL~(V|Ekn{lpv zJ?u$S&4K0{i{Pjk-WYrjp`v9;lA~tx>2dxmgzgYt`XFXdFRj;IC#)aT34TR<>>RWS zn?%vW?<|vWg4{n{{;c!GusRU`I&>u``f$WcD@UaQ_HW}$r)Bhjjbs{TbNvTFWcUKd zBR|Ay6Tjdn6WOb{U9|R*NvP8a)0(yp_oONYHl=%^`M5ixwYOZahCCRm81Z~29L41e zQ?|Rt#0LQIKhAaAm5i%VbH9q-OLhCfT32C{9Usa8>1@^V(FPONmzP!XclQlp;7$O7 zL3gClLA%!6;D=jVW`fWkgw|vaj}TD98eqacQufR* zMJt)ydD2mb`t~3Qb0S(({>`_eFG*jMGwY5s@*9pudK$Xo(yW%LuBJEP50#fxUl!a<{I1)txt{@l=2*r=wjQOs8 z>b`B~<1EuT798{LP8jJc0$(@qvQKWV%iBAQg!QaUUa1N5X!O|94es63LyB2gaqqTsN8V$Ku$++NyCxg>%Va6X{w*-z@@;y06|QhDnkV007GW)tD<+< z!c_HHqhctY-cKvi)QkH!S0A~TssQ#_f9*CQ5~6+Uhd9UNj=siW3zNm}5H%a>$5+j( z0bW~I8Y*&yrq|OYMl&1tUr!z0+heQsw$F9?VRC!!i74c$yfd$u7DseihZPo?^DY=C zy`|`W+MUcABHVfSY*5s)keq{}PSfmqBL9y{_YLBgva0uUX4ho9G9Ml*{zsdi_bCj^ z_Uy}5<7MBP`#Nw@f1~}`@t6uXMc?#ipPulsFtch~&TkzBT!Bkxi5Wr(AndnAozJzC zOC&WAfa70G-?gMpImA)EhsB&~;*;MFUq!BGe!O(rym10JTFTjD>#ax|RtLS9M57K| zl}%e}PvBRezQ;mw+8Q>H&XV5?3tmqFczEb@q)Gy)-%X=DM@xeL?rzlu^D-v@b$T%h zA&lCByaPaOm*RLSky$O6(V(bbVQW8M+BRsT;P+HZUQG!rREfE4+1oQ#*kmu63v6DeB#nWFUJa2`J}sw__A`lX z)byO8k1f%QhK^pj^M{PX(gKi%UXm;UD4-VG>FQ-2PcQm3O#YoDZp-w7GZ&x#02Q#M z1g3WuV3wIY%S%cgvW71u%n?f54HMgwugrIiaRIo2)g(|2@fEBmJJl`f*M0x|Q6XCM zoYLErlC&2RG$knXtTwL@U0!UQH;+^T6DTraxHwUx_->8oKYI@con!<@pw2 zCtxHzS(7s~=ZuSg(7OUKg7tH%b${~A|MdHMz)ao!s9X2Br_}AW>r0e{I-ESdy}CJs zSub!{5akFU=46W&+~A*Hm#Zvpb=^xNDk}PRJ7NTGYMQ@SK73@KE2O2~w8GOpU0YC$ zAytO@Dr`imsCpvuGoyv{DO793YO*%^ed`{f6&-nnQ@Z~pK?aT)&DMBq*m0K)7{KX8QFFA#*B-a|N!!?ZEZCM`EMj|~5 z>AmM|uV}g?{QMcPHXKmD8TOkj`^c>Mth`k!{ra++5WSN*`u%|o`4!HnALu$-Y1Np+ zt+uFjI=ILW(&Fj{jPeV83Pk-jWhgB zG%OlOHPDELYnQ%#F0fvG`i|gPu9+}w`8*1rBOB)QPn7-WV1_^B;!Gk)IHu5{DnN z?Un3Z4yf-bhK;+Ncj)0z5i+q=3p`_Nf32B%XOzv)kN6He6tig&BY&iAmz z+bMIJIViaTI>Ld9S2M?_-w_=ZVNH4*_~NOD{3}DFM;9ms%)gj$PKpbkVV+rO=QjzP zg!Anw@f=Huzf)9XYBUbMdgyg1&BG#pFn_MWrD64O^_6j|<2wcp^+s#vBg@{Ozq#%K zS19-Dv?Ji(JjMdr9mmXL8h2Z~MoNV#=awJtaE(*Da(I8Zv2(32c2r7vkJN+#$fglp zvfEf~NNRv}Zq)2T^9K0fqKbZLimKlvfJ`z;J(%Maw{aXije+05oYG;}LD9rg1T%}d zc+#Toq+6+8F(>sb8qJHaW}~^tbkB@x^94C=H8TnGommU4ju1C|arB#zO>gf|U#_3x z^i~6FNm@&slIGy_SBruH^R*;b^2qZrem3Nb_rtrMKRpYr*~3OF=rQrmxTl6l6rjqj zxc^WcCVOt|hoU=E^Cf9rfsiy=)LT!OyV?+uYOOv3f&fMtwgWB(ED+2vf?a~5vEQ^u zKz>h~GA?=^xb@@@+VB6e8M;5*bgO=KFOZ8$P*zQgwDNoc>@*J4g~t!@s!YH#NFYL! zviUvWqIM~lm4I}8oGK-=wkVkfCkb&tCBziAe0`E0B`q3@yMU&T@8=vXAN^FQw?{$e z0&0QIr{oD-qmY@2H5}!_(r|@ScD$ru#J+je)SBD5yj%m_^r}8mFOn!$9D6uXs194b zoQD`Vc0>P{T4`hW!6HV<^J4G6NYe>)QeX=f(c+h}uM;pZ=P-Z2g(nQJ8%Y`WzLfCS zI_H=EJ2)42BtpCoA39T7s@TuYmMX?{Rot~0nAzNzr_2APah#QVo+w53){Df zbtB=uEg1KBv8oNioFGZNx~*iy)Cu3rq+i?P=|lm}s)Z?wLLTp8PypHQEc?r@1gX%E z-UHL8ABC#1(M>jSoy1v?H$p3=jF_ZSX#gDf^hkt<+BfAUpW!aH_FO$ z>eaYCedep!X%0!?s%YnaKY7{Z3Jr!OB;We%4|s3ypC1Zp1U_C5)r&z4j5EF;-9ckL z3d>q*a{3&FX+%oI=7sPSE&mU3GzXfk*SwFlHk8ux?sNLnPU31Wd6mN3if#<`)Yto}JZ7$LaZh$)i-o3XRP(W=HR#ls z|9AZtHwNuQycl*VM@FjZE-kwZ{Y!vla?q5(LS= zVd@iA77rG`h&zK<#eJ~A#VK!M=q!8TV4sTJ$mKT9YBS3`B6);PGUcI3qYsTR%kHyn&nw~<2>utVl-MvW)2L> zaInVb6{<*75#aZZulZl|@=3jb-3*2*r0gGTE{n95tTp1c17s%bY|*TOKhHQmMnuKN zW}G|G9(wm=Tj*Wp&js!Ge`Mvkei%6+nw4LmT%1)^kfr@GtLk~q4SvClAw`9r%IX6nikGe&(-oICo=2toZoPPga!$%ar{I#32eIo18B{YzXIoPH3~?3$zOt(z%xlPmeb`weo}(#DE2D)8W^poc-0S z^vQAHMB~ZYgO+VkQp4Jwetl`3Q$6D-lV+MP*rl}CFAOJcST`4|J`BCNCAaaMd|Jf8 zYPF=pd*Ne;x0D1=w;2(5Y9?IUyuxs&>KTkP;=|c9Xgng>&cVQ3TcJ{0X!lSDjcd47)4h4c#@?rx@OY1m8#6U#nQ*pws3r>X@w0GI5bii|YMA!S0U856chQKq0c? z6?$D+1q+!dX%_togBDm_U13Qbl4>Zu1X=cKT-vs9(1W;0X`}TrHr#E09Uhe`4Ib7aKXd8>WukeP7%ymF5COL59KHSw%`{oR^)5Nl(wGil z7$XC?!5y-l?6Ut0$oTe-A~BG=NybDaT)uA0bKD&tkHk564E&J1Q2S(XW&Qyb6?}v& z4e_qGNBWuAP4p&3W*iLZ`pv0V4B1wWGgern217bJ3_ zy2NV#6J-_C7{1>yUOMYIiq1tWZP6sbFT?jN|8itbw5?p2ZR{P{j%lP&jL-vi9`^Yj zev69akbuhK^s&L(+!>3}eFYx3gWw}!xbbl#a$AaEI!0)-LBXHS~1>#j+vNs<@t_xU= z8L4P+QD<)QmYZx0a4_;9^0?u#?wFW5N-hVw-qo?D(I0!qjcOM$0HrpUEJ#yEbgtIU ziECrZbC%+3Nn;utT3UXJ>H}4|$1b28WIF8WxnzX(x2V|t)>TO(BR675uE)}P2kF~j z=mMvM^~5VMF!eOk_ENoTx`ZZOTH5uIp7zHr1}3&W3md&ibaqX1{oJ*t7`#)98K1Ql z=}qgZJKwv`;IEmh-t}FRwOdUVswiy=ZA$$))?2wx;dWhKRr&cTv42p@!3S5~x_Tr; zaltWQoiWLx4{lUm!Q4rdGeJ#~Lj(IK#+Hoangk4GE45gI6jW^Iuh zSywA9r}7>C=9HGx_A$PY+>0aMfUSeZfZbWVI7sn2c_vnSf@4v>an7Q^-W)#j_Q#?r!4&ziFt z-AYNFX+ime4Ri|y9X`bN>a78ao65qpn~L>LU+n?=-Bi|;BHH7wesPp-B6-?P%05l0 z+8RVd*=_463a>y+^byW4aod8M^zObbF?2eD1rxLD>?o-BoUZB6{lly#j-=1DxCJfp_ZZ|!ahye>pozM$MqC+)Ns{7 z&r0m&EQ04cW!-vWOv7W8ic;&`UO3kg-(84>^!PF?jmv8u2{O6k-Px~K`^w*_v|z_! zgwS2*X2Yz7F4usdOmH#eb-Z!XCI`f>_suf0qRY+sm2G*tf8$Oft^Z=gMGjKda)O$3 z$6whXNyE0fb=EJ_nzAJKhp1y^7r3`3e|e(!BmNcK4qY?_p7`IN*OCAG+bjRGTiA(z z{(!7Qhwk71!(Sfye|~A^_lv-jLf=X|Bj8tS{-6Jc|L*!<1pbS_e-ZdE0{=zezX<#n pf&U`#Uj+V(z<&|=e;nP(Gl8Zx-)Q$%dZ_lG +- Amazon: +- Leanpub: ### Sending donations directly diff --git a/_freeze/index/execute-results/html.json b/_freeze/index/execute-results/html.json index 1ab70c08..94307194 100644 --- a/_freeze/index/execute-results/html.json +++ b/_freeze/index/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "7eedbe34469c0f2c200651bc420da095", + "hash": "9747d27d8e8f5fadf3da395f3899d9d8", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy an eBook or a physical copy\nof the book on Amazon:\n\n\n\n\n\n\n \n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion)\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy\nof the book, either at Amazon, or at Leanpub:\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2025,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {February},\n edition = {2},\n year = {2025},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion)\n", + "supporting": [ + "index_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_quarto.yml b/_quarto.yml index 64a60b8d..b3066403 100644 --- a/_quarto.yml +++ b/_quarto.yml @@ -6,9 +6,10 @@ book: title: "Introduction to Zig" subtitle: "a project-based book" author: "Pedro Duarte Faria" + edition: 2 date: "today" google-analytics: "G-6CHJXK4CEV" - cover-image: "Cover/cover-artv3.png" + cover-image: "Cover/cover-artv4.png" chapters: - index.qmd - Chapters/01-zig-weird.qmd diff --git a/docs/Cover/cover-artv3.png b/docs/Cover/cover-artv3.png deleted file mode 100644 index c9f280288cc1592df80159b50c7a6bca22f2131b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1030663 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 S&EF9PQ?EUfQ0=Y2iZ%!UB*hB0?yAP98pG?l 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%0DD$AQOn=>-gMg;D5ctO$bz%f<2#2`-aGnVzpn# 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

    KpsDuc1V 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 z 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%0DrybHM`B+VS! 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

    v&UT!iLA2ED7e|hoh!;|hU>MG?MkK~zd zSJ!$fbPjUg9lY*?J(&KGXgz;1-Iqu@#C_Ziwo{SQ+V+aDQxt~x5Q-k!6?5A-PUN4= zJfCupiQRQLB8O_gCt#aHPZj>s#?Djync2d-_6QY(py$Pbg$%O2sr}9y!RvmBWrX}x zya|L5I;Pv#pL#Y->*;I4hd;sk-U$#f)KDqcq$+o)ml%r9+yFU$n)S}rfe9-oM=h6f zCtpEgF3G}mp@$8MwBop6@1o)NHN0J|U)x<~!_B2s(#7+JUjO73@pr<+NE}V~l?|MU zdO2fR|BYl7NC@DO^b0(^mZ+Zq_mwtZYaF1$g;PZpliTeN+FSb_em$r&Y5DwhUL}}} zj9GsE?*SjinnWv;IrEr9Z>!6a+PWjp^Ht?gvzl9@Yx<=~N*%sN%t;=`?i&H8eUIB~+ z=O7G;nNuY*Qs$2R8ErK$pz4kr*CCTd5wxu)YbNy5rM2KraJ}hxkDn-86JsLr86rkzpoRec1Np=Og<@cJR(nRPq1M}8dYTc9qe=!H1jxd5$`+_>t!Y^L^el-X^PAi6eN*8WJN^{nb7A12T&3;%*!Jc( zIu9LT;B_P*?yzgXMjme?XpN6gvGLk>A*ATBV`bylC)o}iw+ivX$vQtj+bvREx6VA* zpL$Q2_9xKrp@8auGwoFwwdXf%aJhIhm?n%6O5rH<)+IGapSCHSx_6+^kUdl9+_M5K zL^9>Z&h)^zd5Ev`!|<5##EIpm2}HW%d@uw;w9;G-&8T1}4LZ5oCaHRHAX?pAqvQ3Y zwSWFN!y7%CdHEQp1J2NY4ntgIP_6&fd?!TBdME>xJX(PIcd355veTxXdgGn@T0E2a z*4EarHU5upAKKIu=Q0u+717nxnvT?RF)E1CJ}Nl!qFHun_f0W4T9f}=3cLY9=QPfu zG_iq+RET2{_Ml331pCHS&Em%y%zYeJ{5^<21@4{ww@2oWU~nFG?wY%4Qpm=L7?9Uh zU0ap^)uoV6p1_tIf@XRDk0X1TU0z*@(0eO;hKTC=hEiElOy{6uWM|GBIH;ESEe=9M zUBKzI(WYwrkw1S^Bd7?R&oa;Ji7`1XJL)pL&+h%{vDP*H|8#w(A{Yz?9M*YmM)~u0 z+BiCD3p&p+mVj;&gs8!hmWZbamV0X-RNhKutw2?w&t{+z&&Ih>rJcDA4{N9l z0VFC!md4)E7Pg%=ZyZcGhVkI1iT1F!Zu}^44bnvnA`~u|tY1O4l@XZ2F^*@R z>X~Q#%$_H+I{!Okl7@j0>UVMR>7=+RrM6z|>m4ff$lUSg)^$nR8&X+bRe3@jUJPBNJS*d z350V?=@W3ys6GxnGVk4@r~c?F>~I|R+5ZnF?zTf7{i)!`PSX(;kzDV-k(u6R`TS3t zLiRoaM-m9SjVkAno|4hxb}_h!N$mF3!0gWxHydu{c}-c)^3uV?FVBMyy^?70oPnsn zG4okY;LcQm=g&posg*xJ%}xWp^t*scn!LQcsw$dNOgw z#8BV~rDGa8-uUYD2%_Pb--rIIM5FmUM&;G8XBs zVw=EGvc+huGy@4bY2*YM2{9Eq87?GtZF)H@QDm~8-*5r0fhV>p(H#m)c%sVt*qly4 zogIthXz|e2g*KP=H&t!Asr?;kl}qe@Kzp)Wkg4Nbr0;cghz3P2y5v90;EEr%$xYv) zeTqu}NC1JYySK9{K0dx14EoX!q9&-HVb4WnS5s%S&gwHL8aetxzW0|0q%~xYeEe>k z8XL7eRkSSC5tx{gl7^rzo=$M15$k*Nsn%xPrIu;lqkGG3YMm63a_lQnuNZS)aK1j0 z*}~GiWJpi{AfUp22r#v&PT3UTng&rOZR@S#d*9-JR=jDRvh4SeLi#zr z`0Vgkw*h?Eg$4UXzb(hnWMN!!!B2)V{o$8(18KECar=+^KJx#`50%OQj3Pu+Ji5`V zQlIqIFfVyjDzNp7AmrmW!@H1Hbw3L|)s&J)V}{1+q+L{-^fu*zE~K8 z7;KxZ)hO*r`ORTieyV#Pp8VAn>#A^SR59i#hibr|iBdk#{*>%Ztp|yC+CIhWW2KlgPwmUw`B4O=(UlNKMf8Dv`f)my0Um;QVqA@6CT$PU}73TmMu$ zy1&-|+Yf`b1Sraj70Mj4Mj` z=)+O~4DhE`HO<`rpqL5<(gb9 zo*sS#M)ofkK2UAO%!=Jwj)(H7;L8 z&?&kGnOKavO?u-B#2cb!u76Ya7S~xcD&+e10P^GSPTTBM(YlqU3AY0HBcZeBJcGit z_wXB#jfjhn6`hcvu2d1=)zv9vcsh65Xj?z0*OwO$U5*ml!fK3*C?EfxxP?G{SOS>1 zhusuKDBHqO$D-jVM)~t|*BL)l;2MGu z$=H}975NmqG$yz0YhP_8W#$wow#1+xNq+T5`R?phy3=KXp=vtX8?-$nc@sAjuJMI$ z>ChY9eZs@Mle@eh+`qK16902QhR+!}&!YIC10nl2KTH?-~v?1{w3{?}b!_Fmu` zc6@sxAD?!vjTzbj@$0g5!_M;bPs5(mSp7}Ht#V+J3oxnnke{<4h)_awMxt@HjcAS~ zM`^f9L6KM4XO@g-aTjXyJuCb4ysZ^$H>G#va#VEF7kvbCF(j=a$8o}# z!lBdHF9F)=L$@^4yvQVJ$2MN;M7-&=dfJJHA0|W@*S}CpjdJ-Re{I&~qWO@)V)jc? z1v5X@nQ2qplkA1Dyy6M}=)^NUp55073;bBb(At(UwBMVD9)*Sut%Vq*e<1jo-b6j% zui$e|4VP3B`tEc1fnOd6av z6PIV;Uw0Rc=f3o6S{TG%-c6pqM7t`3gcfZp!l{&n(4+j6w2-wXL4GPSt^VQi{3Q2s zZ}VgYZ-J)d#J)qzkOAS;qN&DfSj#g#4eMqvBjmR72db8>ssL_6+WVR09vsEPu1-yH zvyvk}yQrT1>n)v}1)bo;YWDOC4-Vk$y;?N-fBl2)T;N_kQS+{b_&d|QU}9U-tF`_a>ILco}mBU@cc}B8qL4vV<2jRi@t= zRKh&*T%0Z2ghem5S?oL&?IR7+^QXb`G>DWYyx|6WhQc0ovL@|^&SmEc;DMK2H@;bH@l4-52=Ixr+;*VNrZ4q5JX9(Rr5EPH2e2-?cIT*8< zr>`#C>tm-TrLZdf3p>lua@6_I{anN#VAVa@o$U7aIzayZ(E^C$_pCJ%+gi`OX< zmL-rg=DECj?sVg+erPE2o+yFL?AKKeoeWgL<@eOXd(K(& zrNd4W)@sSzdtcMye#!4Kr8Qj^_YG7>Was%@Jc>){4VytBgPKDtg5R%0&$sBf1m6^Co@6NF0CV%~!C2+*bqhn@ozO6cY z9M*YGwN;nv0~_CUaNcSDJNaZbN7$raG>mVzBQ)gUAdABwxokWW_EyT4&NUnjA!pCb z_^j#&ruFV$;wbAq_$!fUa>00~j zjJ|!Q8f*H?sYJtrC{{8tinf0t+P>+2yC%}nw%cPiYP&;~Wx!I?+h=My834?iNG z*c6TBsE_pv04ha9h2Z=R5%I0ws*;^>66c5r&Sid;YmPL?N0lcXL+91ce(ip!;{SnY z%Ivq&%N6T8X!AB1iR=?3aGXeOYj|sS@-DIa<$zAfpoSqrMY^`zR+H`*hM+O%X~cvW zTwDh?y|{Az`tLcry_9ojD6XYLUOY3oE_A<`W?Z!SEC=s0zqHF5)pArNl(F_zAN#O4 z(1@;O2rZ?uYJ0jh!AWx;OY9$QsI}0m{=?>a)O`Ek(n{vSLO|p$Pe;G~h-x!=1QJxF)-yUWSI%WPl#F3 zA7(?Fx!cQUURq~wT6*lT z-XMxOK5D6*RBT`FufO)5L~x(1a|Re?UPP+uZex8{R@i)3@XNXf8p8w>$lmH~IccWn z)h>3Ms4LT@N^@ zc%?+2!e4G*g|^>|9||RW7&b;1aI_z_C8t5JI^x_^QkZdI7|Rmq*9WGX;H+ zVpmIDW6oa|^pQISveX-%0!)pQi^hGF+y}0CsE&Dp$nKx8TLkySwt|DT{KD=dlSzi`lq>r zVU`$MSLHEN+!-`Tc#-6^)p~G5<41Y#ji^}#t;0T1@xOYRZH8M}yID2oQeE<3qun`75+y2nI-?XW*Lt&N# z^q9rN6s-4n7+oKtBXu*JwRfKh9|ax31!DM zrZWDCt%^xKxZ&i)nL3x|g2MfM(0BT|xJ2RE}8ry}fxhWew0C z{n!U%(m0M0? zt0N~EOUNmctMe>`683K#U45D+PG-=N6hdVM9umr6xWoPwzNo;_9E4~?x5rH zLeK;Ke@Hf@kelf`aOpx!5o0zMb~WII!H2cMg`F=y50Jf$6s4qqF$(V?h@xAm@#Nl$&=pk>-oM#Ki184>qgX|d)={Bmamh-ggnfgoH>gL zllyyAr)tvVWaCVrcHg(SAQA_dzl_N*gvkU6wpq{XN#VbZ*N}O*jOn@jrZ}hOfX2|U$RkTdELQ^Zia~oOd($SQQtXrb zYC;yST+i(`C)J=$0#-EFHOzfRq9U7P*j_2r?=Fml-I94Y>3JTh-(D zsTBzm4F(37qA8ATsoxi%0%FG!c+4Q*%5nIx63Xr|LCDl|{5Z116oNPMNoM7NSz?(S z2lx=lJPLqulXg_JvBVP2(~P_Kjw*peT>@hX>s<(QKZ`foy5kmjLGW0x`F((^qoc~{ zT;7P`nvd4^FSp3YHaxHDxA9B?l^52HXy$aZ{~=r;58npcf-&GLV1$cL^ZfF%c= z+>tJmWzhZWVKqTUOtz2)d{l>rj!kjo)$~oskJ}vsVFq(iZ7i>CeA})dy*>jrSeXSM z6PSMHw=qv%zbxI2jY(v##W%gxNfBzsr+-ak2zXkd;g?R3uGxC#A;6aSotf=I%C+JFY(NW$u~S=hWN@y$v3|LKUl(zr=(y><0q zE+nTxpHRH`44PuJ{VD%R73Hm|Nqa+%Q(N^caP6_e?A{ib^})}k%dB+hkU@l_LP{``eF@Ec5#mBIcDpy zrnjVlDo;ATP(Y-7w5=%xXb=^NU@ov62^8&7x|qno@6S6uIO4IgXCa>x;`#e9&{}n& zD|2?-#1A17?-=qfefy{N(a`X4-0;Y7WmyCIu`dJPKZM$gK>>D?@L?kDNM&`kmT`7- z=d-sg4&f<{4!Z3c>@}{lI9ng$l(+hReP)>gsxt2es(vE%)n?o{uS{|FZ&MDWCp6$> zOe>9hXpdQw1>o4kP!vE0atSuVHSH*GFRD2Kj9`=+gi#v>~3N99}LG=O(&setFcSK^)vZa236+aL>vfT*pGwFSw-B&Bpf;uAf**VX+X-H2G; z=&^tSc}pB=A6mI~$u0WG?;Dj%?T9ufOxpD+#uGLT=d++zbs5g{Fpa zBURm8*)VYCxhE|Yxm8w-X-@q8FGvgG!O=gla5B!*n0RL>UMC^_>!W~f=UM8YW(WjF z74ji5Wq9J`$P_@hjmgJITSX5)#5CU2O|d(#8*x?!#%sT8f<_j^ewimSj`T8W!QM`u z^$&JjACu!Xpb2+voKz7ivln%j2#p{48eEs^?#f`>P3d^!tONSO%e)AptN7ZdwiELW zh_N{|$9h#3=&7A#f?AAPG|%2cU%F%R@;2ollK(BC(OvWSd-oL1<9(dob46|IA)N(q z_^8@fWTdO3U>6?iU` zAZ&Qsn%xc7^zrtEmS5YCt1<{~R)eLk6Fub$s&_hjTpM++Fl0JJE-JZ7&W-lJe0f`A zNzkG7`Af0=-3OuhUQ?!Q-pWD+wS82oECmaPifA5^IS;OC=Lvf5=!8rzy#azZLoe?2 zO(-tqUZ-|}P91kwV>ywSz;R+jbT>t&b5w_hU0Fo30=`5}O+N_&;dq{jOKy10R-)H` z5$0Hq;^>{RzCNr+646)vv``w>^6cn(0FUmQvogaS$az>|dFx$&a&AZXh%Cy9I|Tt< zkO`m(7|4X$ddQ*3hTNmTRWsQ&PJ;{~p7S_wGGtfjGPh}EYnQ54jZJWJ&J1&hP1hqg z;y}`9c$k+)dQnaOxzAts=81!?@J<%2-$CZe{OhSkjjomAB)pnzK@$4{S0#alUyC1D zxDCW|ySWV#toCEo>F6dzSZeZ(E5>>|d(6~B0}7bXTEb5r=Ziz*IYSjMWrq07%s5D(c5UqzF06eg_go9ra>*!j)AT~A!d&X(4XAFoU>=7xLoLOS5e2Aj0Q6+L~sAt^XhEpzo z?h_BNcmxH_TjZB(Ug??Q={JSY5~@u5F$)-ERG}~n zc4ZfdXQz&c?Ojy@*JkD|0b0^|_P4a9A(wJCJ7e$WT4itas<40m2so(WztDX`&zSnG zxt)!dA3~TXC!6t4;;dOohOV6pHow{B40pnJU$hN=sRf1ChPQJK1%$bNGd64VG}(q| z{0*2P8qd#d?mst&hkL>#ZkxDxE>^^ODy*;9`5t<<1fQ)b@XVZpP|UT_W76@%`GE|n z#Dn3=#-n9xa7yZ7&a7xwR@LTD?NK%9)aq<+h>Zvx{VE1%t{%~;g0QCb&a>=neJjWI zO`=#gxy1SP-VxHGoZInmZ`(QB?dt8yhDI?0La)ua7TW^%n_H@9SJ0i*XD`Vxo*Dgh zrge!{h&br(r)?zAwhFJ?8~a5##Fgvqean@Aff?Q%)8ev<3pm0nOzkO8u{5Tiy>hKR zQ9yBL!Fi;@hZx*dSVUl4f~PTQ3OjD0+zYS;@XI}BsMOw;{G zvnR6sOAw>a3hmS&E*{QRk}z1jSaeU~PKeuZJZ4?-rIcCs}25k+wk_zLFMa!- zFJOF4>I1Ou;N?UT&&1>9`hB)T8jrU}X65OxYe+sZDiHcPg6th9*V%fp9HxTn{7yi1 zcXw<3TCKO}YjUU5dXrG_(6E=18;pptYk-X-6GrYi9yT5l$2e~rKR+B&4uuf8Rp53absd5{hxUpAqxiMp8u#8&0 z_Lt&)LNObjw9h*A4gIaoTJOGF;cV^$gWd#E>wM%}Yr+ovc0%WNzVTFHZ8r~&o?lZ` z-x{!2h)!X40$StC*kimfFh=_)Y8&}!Rn`qIn?$&5w7CKX4rDU0=uaMa``6+b(kI$vQui-< z`5Z18Hst7yOyn6fbIT?T@ zH?k`}+MzsLO7ngu;VVBZ_@CZE>Wy|A2wk4u=pFFa1@3;#eMtJ<1}$Etp)2PS0>qyXI~JYILGGx;J^_7kvfb2ItX-Js2trr`tY>w{0n?D%N_3=A-`7mP^w z(x?0M#nj#YB8z>9I+|nmLp2?^8>;gHfV~oHxPY#X{ZCYy4uHX1W&UzH?fU6AqldNS zPDM2@8M(S+Ep%Qkoq?1*@3drGY0xn0=n)mNst$aKA%4v#*Y2&(!5`8LTZ&(!xYZy6 z`rRyN&KUf%v|wS)~|DqTDm-?WCUmfB=%}8D1{gd4m)vW-N>Zz;;BKy!!^Ib zqa{q4g0Rz*>y}HKiGqE00Aa}4*4wElpQ>4G@<&K`ABgq-pPg$}<8*hwc6{Ak zo(H`CL)1D4cb*6Yatr7e%&hYBZctU#!9|qbF(qiUG)CiCR7(6+CK0BtR;KSL5`c{z z^7wnQGpW^xS5rwni145wMc1;+Jau^q%pB-RBS}-f1L8dhm4>v zVDeTy$vrZKT56trB`P44%KlDevCbN&QPe6620 z;&aqYgl?gR>buU{$2(sFHxT`Q6#ip`v;w$2XU7xb+Iix#q zJ9n|y^n;eV#t~|Z8htCjl;ADJ2Dkc@!0xG`M^U5$9nqNQ@n>Zeu4oS7c{q9QkVt=Q zF*V2Re5H(2vF&F(V%QMKhmnHamiIkmbp39r2A13q?81a>YkKPY$Sqh-gPOH&$l= zCN(qBp|uclU1(*k^h)_xc?*eTx@bY~7f=aKo6roE;fq~m8gkJHvAbGs5TIRqKRM}u zpY+EknJxEaRp42>%NUBTK>Vj?b#h$9U=xTwIwJ*HlUj~~Uyz@N6M)M?NCyN4&IwD_ zU~>xQxWK*|(!KLJxXNN_eBTp7@fs*hJ`Gpv?lm(D;+Cb&;@73DqUTqRHWxj2_ql=g zRKNA{Q2YE<+vKUCxdg>vo?Ox2gJ?9sCUSJ;LdkI6$dZ+rnare{tm++BkZ957=Fs@~ z)JWfQWXMO=(d-ie9`cBM1ru`V91x=(g_^?+xRv>?l3jG7TxM~Ek13=KXGlGH0>XMK zp*CL3fd-a9kS*j)vq-q57i3x1^TOi?FHMQ5WaxRi6?h!0rC>(JWTTs&A5qp2dwR+x z$Q57*_Yz!flgEdEGlq`dfFziW6LPTOxwH6~1dW?(4^gsD8D3v63#{&`TEL97kJZ^t zHWsoM8xFvyVl`M#AK&N%TI8U{#HF}aCbwAK?al$8AL# z^p@SpFh<4?(O-E-s0~bikGi$BwU_`f$bn!u&kOcf5s%*5<>OF4wfYo_#gFqFH{z!T zTl$`i;_f8!Kry&f!G2rBk6$@)!*Tyfw~t5JBradYlA>|#dv*A=Pck4u+ohv$9w^8V zlv`az5&Qw}Nle_Ezd>~h-jaF(RN~3bq2>B7DcCNblY>H|H|%(I$KK2R)Bk)OsOs4J zog!W{03j?);-;RZM)A(-i3VzU6%L>*US4{@5#L!To=|ItuQQN(3Avk-(Ru%y$KTUZ z%6<--%3_uJ@EdRE&&Yj7rS5NS)cGt`0Yqh&bMDb{s&}wxI7|>$;p(WMM^y!~h;;v} z<8P*;T!wwR5*}4IS(N(N@B0UUH7p-q0O@{}l9ryY?>8RvS_|*HX?;6;HGP0DliJbT z^Hy|pU=Az0WoO*XZM}8!*sx>vf3X0P4m;vsSDK64-yTeOK6w4~ip4O`!liGn=NHddJ8dY*N*<*c2++KYOyvCB;LJ6< z+8HIWAJbp)o|{ol^=3hnfJW48VkC3^LeIe4;{oNNg(^XVfBk8T?`y9h9z}yhgqHk6 zN6U?#82qK&%3*}Ph2DmDzJ)AlO7d(h{?4hU$-mmMud|n`t8WBmAdnlZ_5E-?y_u3> zE4e|5l(`D96A*2(70k7_*NAOYhChc}0%#(jD6v#}i4g*sL_B+_z`L8xq@c|K0=ghb zpw|?(w_cByQ#LsVQKi>i_}1_TW^>mfZL!6Itg-z010`}|_3N@IoQv3p`+!L}A%`>P z&2TAE?{eN;v%72QZlN`)L}*1yN8wU}sytJq4aF1YJ2!;SoCt>?Kt)dvl8&Hsm6la^ z%>@(FW7T>Zt-yMgB=-^-Jqx$fQ>7 zwJv68;pljQT5kBU&aKmkw-AUv`*~BG;T_pJT{ z}Ds5igT!xRKVtg z(&mxHAC^t)QmH4=JVLce^2<_CQ0!SE{1J4a!gx~Ha?vH(DykNe{ad^HA$b;V*uy(% z^J#$@HgMtGR(mk^hs=kMJt!kMxT?RYJtk~!&Z~=iZM`UjDLCHgR$vR&$98Hs-YFPG zbXwL9%()0^raF3%IV4;jJ_mEze!ab^cl@oIf;mZCQ8_xCXW?xKP{8ueCA|S>yTtLY zfVymzyBZ4;Y#OeX4h%$qS;0%4Rw6e^mh&4jeFc3vcp+OpNQ~LsEfyERMjKCzW^Vp1Q zBrb9!c`-73pTp3o1mNJ!PpJ7O8Yy2T5itXz+3YscoU8-baFUM zt_qdNonJKI1 zl+-`BS0H(4ogya58k-w|771$1`SHg44VIYk39*u%86+w`*)XnEo|4Csd{peWpRR#a zQB+J?H22OwoOyxjG&9{y$)p3D6OhBz65fKo)6GtjT3kBVm-pn4Uk2q26WyFrOe=~` z&-Fp(j`yL?cP2lHDe{Eb(0klgx{p&R;pMH}w&6)T+(D( zp|_1~CQc*yldiW>3EXdJC_>a=vH?4?<*PS*v%)o2hha&^VobSj=uz>8L}K~WaV^yAyZfzc_vO@mL{%1cGYL=D1%_Ed$*Idd zei$dQL{_+48(xyE$=0K{M+seNdVdZ#R1#d3`Npo{%Fyq2HM>I5a13>MWAFJeT!k|M-xJVN;batdC{esKH2y*_iK6i=h5Ll%~jcA zn+Lb4fe{Kd`Zxd2hYOV^hm-N-X90ZV4>=U-`|QpY^suImahqXy=z&qO~y65DQ1$xiXkxKigVwts(kcWF<4Zc;vk%EZzy;Q@`vV zH50bR6!$Q>%zY7oH#0IQB3z`vN6fN|Rj<>HxCB(QKTP6kea%znX0j_nD&Vfc1Q*Ef zf67ByNHwL#!N6S*oUF?}Cy9yM9w(SkvlrIq8qNf#iuv5+2S5s|Mh7sJH6FTJ9OLgr z!W|lB!uS#_D!7_Z(o7`HRNSLLA|uX55VD5Vz=45@y?2N96vA` zL4sY}_HO?)gd27wbswFDMaPGy+163S_w7H$E1Fj5Vt!7(aHaL~TrurIFc<3f#%USE zl(v>#gQuvfzOMG{^rEibtJ!F)4j5a7_w`cB6c7~)bGii{Ro=)!xA!k>ge&lpXy9pj z6_J$DhCY}`_Jyr*?nNW3%B}8M6B)UP<<2Q#^4=O*!4g+U_zUD3PXZskRs z;a~hAB@fkAlZx+lTZl;k@3}~m zcIg*#{GHybzx?a3JUm*JYI9#xT94m3V{PrHCwUxX2=WR^t!D<7=z(HzayCyF_*}RHA(N9xpSa zLaefC@=05V+dI&Yjr4`A3lme^P!*1eLoeai1dLvwTMZg|i;UuzpN2jdnAw~!pi=w3 z)fHPK8%tnXX*kd;>Q&$!K*WqEePaU2QxzMsnc5%3e`EjwGWJVF#2

    Ezz1joNGADU&mq-J6nr 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

    op6=YrFP4Hhn`*O62Wwq$y7nsR zZOp%rNxjq!ls(__?`s!70LE#r;=&YK+og%0mitgW)#huw;MG7-0 zCPe>|vU4%!l?Xk=f7{6p3p6PD&SCTVGS&Y?JfJ4GyHlKxUJ5Pe(l2*`uZXVeN#LMS5$%O$0W`;B^Ox5k`a-|10zBqE zQWf8 z7JcRX+Zyo+o~FDDgj==M-`-2$K=a7>Y&PFM2< zir{xtc0e-%u>l~(lPhH9BT$F=vvric=&Ln)GNWTRbLaF?;HRkFGuLIlkxq*S^ELMa z6)Hv+55RKGloa-L5KR*_&ZwZc@X*$F$==G^Ug3DoZ(maIWb;BaK0R<2p(BjZWF>Kt zK)yvQCXYB^g8}4py1~Mk9MU{j+n^$t#4e{kYFT+`ZSeA)S?L|cQ|HWdsJ<$To~e_} zeOlQk>pgR%oO2uZkf8ngW+M{X#RCY0wSCqAJ`TFC2kgR>GE*+{bh$a8%5Qq+VNYe5 z6G9H9hf9(K!BXf`DB#=xdl&HooKjMh9>@sg&+;^=L6~~Zj94n*iWA-uq8R7Sg2I72 ziyB36sQ+odcOH$fY4>XvfXOR73i3w%tkTYVdnzB^%gn58fbR_pZ6#hLOt2D~@0Q&hU zI6{#GaInVmtI0Sv=x6Ojx`sA7fGB7i^ZGH^(q!9C=?eRky8QP5Vr<{RM3=z0qF-`? zXDiBQFR%Lwg#{IUfO;`RY(Z(3BY>am?@7~t($3*ddU|Cvu+6lBUcqKDBQ9d9sk8D) zSD7L-1Vc^x{8nV@%^FZyoe(;`!VWwhharoBD zg1u*+lxZJH-5)i^7PY?Uv_RR^U45jxe5Ac5dL!AL9BKGGztg+Rm6j!S!>(%nf%k30 zqgw`8z5170_EOWD&+~oBSU8TyitYC>-GqsxeQ9Vkw|TTx;kzd8ob|@MHp~{u&Wk#$ zykxG|Nv}IUi^@TBT8aIncu^$1@k9cqgGUM;-}1bRiHUu7dQ!T5#7xVLfgYhWb;(nU zD=bM~^*y?$%?^b- zez;Pz?^7-9B4&wg8WL*a`TPvK#&<3M)=xgx4I#*=adN~C`D7uQOEZ!ws+e$b*(!+8RI6Hx1=U@8*5nNu7!2C=YRC^ z?KE3C=A&;NvEnc`J#ZmL?@f;%mm=)qP4A;Hy0?7Ye3yup)rxs~h!^qd&UF9#rMh|AS z>ndhV*AU3$4ZHi~KHGKdog9SbtU^k@b^C*nE?yAGPzriK|sTFy-ATR9cgdx)3DE~SJ#{=21Ygg-r?`B^{dt5lWa+l zLa{G)*GAj}iQc7ia<@!Of3=CkMwp|&yX6lkseeq#xtJLey%{4wxhmj0+QO09RWEzn z#I(z;VR8M&eCR4Z-k1B3_M)LCfuvyGCBvQafNi;tPDm^HxgHe*lT`+6yD~=JR+g9; z?RPGdbZaIe+@Mgs)~-*Ob8c3|K_>OYnqE+;qv z2DdUdVn`O6y*647^Xe*fR*Y?Q%XxfLy7ue@^RR0`?9l5ZQ02GQ(Lc5 z#8Q8zYnJcfwLwu%620OJnW}mZrApuj0Y2Yd`37l6)@7%Bb0V@Ju8EazGR!k!nTcXj zR$&utX}H`&-kjQn#4Wg8t-(oMSv|RB~shJ-V=P3)Tfb@ zWXovpb*4RKO;3oTApa{`qT1L-eX!F#kk3HXQZN-nv;|+WMRNw<`9+f~B~pT|*v{&g zGxp}{U<99q%IflPsTWW9i|~)PcR&lO$AgV)cQcfVxAJ*jL}#(sb`PU~{eG;NMINzX z+q@$+CH*?t$-{7k8%j_kOF z+Cr~gSIM9Fp9V~k#+lz?&w>hbprTi=R?#Bd1@~KWem!kKaDUr3ckc+x{ba^|42SJf zd-JWJ*Bd;LWo=2vDu+djJ{e_Uom>HxFvoSoZn7~h@9p)FQr`Qp`{<4mvz_g5ix)EI8t}dE;LW!_<1p}*LlW{AxI&X; z=h>oyR@~n_vsC*dY+v#36Mg<6V~Rs{qde8Jr((m(cClXw$*Cqb0K?J0AZl2=R#hs|aV2Bh6;aM)|Eyx%d{$kA zE0%}t?50*jHQRay)CbG*l@DI*J|2>Ah7Wg`x>skmPiZvJBsrx~DcE1r%5fm%CQPpp zACq^sQWUCMqyB(P#vj0%_QHjkkRUSM#ESOtr}dn>uC+W5d(?brJL~o~u}^(y9fC>S z0!QnRCT20$ebnpqg;X-PMLReuBc?nruX>AMN7qo{rGQ@v$9$ctzOs{qaPqvhdOhaR ziixTRQY&q%TbDfJLP7lYr>ou`60jl_+Xa5so-a#`6+(kB0UFZMQ+F)YRcR34O?xh{*$)HNl;adQ~#%;pQcurY$&(jg3bmJDY#(n7oD^LoyfT>+cJkW^?OZFi z0h(Gvj-d5lP9}(z31Ak9D&-C&HZ*KRe@zCQe0q3n5YdLhs)lc9t5+Oo*m9T+#jdGx zftSYhL8g+J z!6(v%|JBvV%s+tZ)7M5u*rVKg-4u@7nvS?Dy}Xq5yvEB^D^N}+rJRs|;#%q-S@-t` z;Efi~$tTK^dvr?2zdr)ssbv2RBYyJHH<9wBli~SIH8jc2NnEGG&7V(b|J5sjzc0V~ z{|y4J7=NCE+`Dq^-$1)3AL*O?p4OA!{qH3cOo80?FEtZo{#!1P%dMi3|M$gLW~PD$ zugE~kkbfVCd<*>sWP<-l3L=-Bhn;6pRA+MJ;4T*H7D(#nPko_50W9)6(EnF0gD#lA ze@P{k2YLuM)B||lQ9P_33uCbD@G9Q*F2a`ciTmtn^ruQaC=IM|F?bJwtw`1 zrv>>Z^6~4yg*p>fkPW^H2c8@HO=9gO0LY-TM(vE(|7{C^V*j3| zZ_zr|LpIW2p)(3bXSE_Zd2>4}jJ!_Vn$n@3n4)FBgHmW_6uQ#>(An|M;ceq6@c-8~Ez9bszx$`}Q)r&$D>SfmPcxUUAc~7>!#n}&0sFb?@qy5vn3$Z> zCE9ud1oqDdVZ7YO>YNEh7lT?v&k^Az?F++&db*|wjXTq%z2@ce=YQS!lko{WA9(M? z5BP-QvvJ`r)=k-mOF4s|y58ISax0=mmbCQ_H4e8F#XTP3=0~Yd{Yj)QFga#?cSxt* z7pkbP&V78e>Hq+g619GYjui6)KR$~H3#)z)6^Pq9Jdw@+(94pqzjZ^9_ejeB2Dx9?{-6v(vOS5_p$`j8h;L=i#BxB*sfN#Z9)o0poYf<-RSmuKW|=klSz9aMy+F1}ES9|XDslg>|84w}l8!%(Uo;L^ zt){c)f9~Sdl+9mCCGSPpk}Yfh`McYisx#IcoS=07Z8@w4Xs(VhP`6c8SGzhnWz5^; zw;A7H><`;pjq39HWR-8*V3l=xRt?ZlF? zLnV}p;1>nVwaJ&e+lU%*4T?)%y+Nf>|HIyU|22KJ|Kr%+EqALztpgQ=Rv98okv)>u z0kRbpWGho<1leTR+bSvo%1R+XYFQ$Cj}U?bFoaPE5JDgkLcoxO00BZ4`MjXj-jDY` z@crR?pT~m-@Je21T<1F1^}NP8=Q_@3s{j&1*=4uivE$89VypSL|lAN155&6RHdqT9dw( z_+`sROYyg$LQ{8acG}#N{5VAs z=C2ibC+3Ks0b4`38S9}!TYC9C2lXWe#%cz&Ngo4KbKv5bm+UsPa_;Yy*HxTSz#;AJIR5t5PvtPW|E#@?Z(E@L0jeHNlmx zkzZ#Dh?&Xhc4c7bswWo6e5JAs6o+g}fMlBrT+(-~2Dg+zAnk$;K~d1rrM)iSe(NT? zfK4j|LR%^vj*Grb*&Rm&a5Y=DEz05Sv}l;G)$-H0ITNxaZWv(>6%Is;<~jG&z75jX z06b6n=DLHugHDM=!|6X&HaR%qKEuY?y25aNcFkw_k4_susWLUfj?tF7qkO zc9fFQTMyEdkz8~oajtQ$`lxri1S`6=d;fd<%;RFBbFd05vUsAf@3)YGoEa>MsE5vS zlv+!dz%PmA-tW9S&tc9g4n^~~uzg?gg>RVPt>h@WqfPylKL%?RYA?(vS?ZA#qN^_# z{YTUwEpGy2umU~Lqt$Yj9~qy-*_M4M$#b-lRpqwX71rZrB)>-#Ft-1Xy( z4_LckOAjnEci^o`GGp@c9c)XqIvSHiKimm^V*+)DZ_R#W*2yi=a=g?QqxW`bMMJN3 zDg(C_;jS0Cz255XfJ%KqULT2QNo5F8;Z!~eA;d{LqJ;(_AA7-q$gb}n@T6i9!sk@M z-3NsrZIZE@Thqh8LsYHD%{Z6h&FWmt%0k(=nZupIC1(!O{K0D5C{!!yJ-J_mp9~UqWou7Y+rwSyvJ7QfrJ+p z72cPV;~Y~CE?qxZ!~DuM%kvHsJ5P-I15_ zFYNy7tCeEIgaku#o!q@kiCgM}2i*f6AfB75MXn#xw_~tU_BM{GXnV~3Mh$yz*WU!GQq zYK=knFPfFHL^9v|#|2#TFX-!k|7i1KV{l6??D@K@G||rxKeKYBuj?01-8u{Yr}+qj zaU7X4Kr4q_ZDC5V>O{fD16;-}%(rnBx@rUC)4MV7iF4j51QyDGo#VDQzIRasvhKC^ zP*~!$gGwU2%SyA9jzJcDWnz9>4ZozaT)O1@YzNTA`4F?9Ycp`iw1=|m-lnFe_#wEE z=;`e}FHAIF03tOQhPzEgqlo%sa zNn6z$;51PcU~3`Lt!BIknFNQ!Lx1if&FuY4Cm*iT97`;4 z0!s`k#zGqPkrmfF#jAu$5}iB2Z{Imf5g^3tR|Pw8xAiN%L07jb(bH*3qkB~pJhE{8 zJtiKgxrQqgCXRk(P_3)iuryxYhFJ;yOdX68dwYZ*fGqzphJbtu29A&tkxuCOMWICJG|q8sjjXb zF-~%u5q|DdQ}#PZ>K;WOWfYvZ68rw6&>L|G@a+Fm!D4xOdzNyOW!WKB2`jS+?Gcve z28=ZRMqztgSku*xJEX-_JVg@iG7L(ddIQ~Fo)4)Ka3Ba&x9@YnpOs2%AX+4CSg;~G z3WP?V?kw69q_%UeNd!J>ENFUcIQA{3z0)?XcR%0;zNhE}l3F-{5E;OQ(UCW~i;Jgl z!m*mW2??eqYsOihXVy!8oBT4%ON;G!JVJ~Ro)3BnBz#tmv##_3Gf*$VnpI{Q zK<~xH)Sg07=Ma~WYc5ANs?`$u2r`gDbZNMwDsfz}C&CRSBB#Sb$ z>Jv;;x{v#SV0mL9hTaT-BYv)~u31$;tRvex+WY9%>Ge1qI(DSAxR@)_K9ph*p2>{P znP=>N9n}Po{W?g*Zh#8d%yD+1&L`51Q{1-U>pc(P%<=3Yw64CS79Tblc3{Gzh9sB{ zLNmHk6qqgk$Mt~7t{>KWfh1i4o^#rN9j1~7^N zpT2B+^*m9-RUjrG?@i8R4^gr*)?iTyO^y!rI8xvUwRpW+w{UK)n_KUx?Yw>q07fnL zpZK zfA>X3W(xADTQ{4yf71)7^-kG8>;JP|%FqAAdpA;n+yNjURy|^%nabSGs9&zmor(cM zF+jN&cW>tv@$aSKXHi2$$H~S_BSV`O?=qh_H{Bd2W~sVjd)@2-Zh_l*Vb8eh&hgKi z5o$aMmVNBl-16qhOs0XRO-ROQr3=fm5V(YP_IOGK%Y0`zr$0-#-*y^;wg_H(E5nw( z14T(RaY_`gh8dQZ$yW}L-T@C4LUX&v#=NfW2bwzk^Ig)mbO%bT50<=R`)}sq!}5}8 z2S-Kc)p9u;#*8d?n%%M8F?R9uxN$8#so+PLtyiij95S6=K%D5s>QKCK4hCfH`|X^z zvAFfPWlBg~ZUzW*gMVv0&g&QM^~}*4n6jFo8Ua)B=WXwW+;zhyJ5DvE%7~tzz*T^3 zx^bSytu)v=W02B1#=6qmi(a3HrK?bKFeN#^fTwxI*Qs^HtXRIN}_R zuS?aVj`5$zT`sq=bzT};xZYRc;U^f^S*tLJ(gUIKtbWTC+Q>f-tbbvqj*sv?QftK-eQIwB9^PI?uOa&gIF zNMRGG_QgePyGty+!_Moe+mz$W5@68IdGwzdSrNI7l6!INmX{rg3e2;c-q#dt`UpW2 z&5B&XbzA9b98@%f8P8KsnbFDdQdE3th}YNT-RfR*rJXUVtqSQ0L8%kigH6+AOzTAW zm@D=g1wl0g=41~9m9sv8nM!MPU=f;wN944EU;+{R;XeC?1|=}`nIIj=IMl?4Aqr*F zRp!~`U>5=xjlOafH(si=IM$KPksiY_y^e7OO}j}k8O0k+mcE0W?7_Qt5fj;+*(*I? z+u}A~>4htdYFm{v9WWsBV_r2Z1d*Fz{pD_VY#5i*!_#734MjSC{jd>Jfn30TiC%vc zPDJrrrwzBbO6C?nX4AP~>v$eVPJj_6^;7s!cU+-jMO~R`06Vmx^^Z zE${)kCLOp2{A!cEvnVg@t_O=HQNWxoUpLG~Mq)_~SUwh#L=x)R=GkB(DX>t~{TNcK%LeqGON%+%pZf&XB~;3`!C8F0y|m#tsgn%ins z1*_YTvqLdY$6M;X*(3kCr#9eizDb@eDfX$n+LtCy)4)f^r~FaSKO$FfM`&c&aOFvE ze<1xqBE-waXZ}6}XQ(!v=sIX>W4jo=*;Jt47QC?Zo)=naQ$UB9QI?AWc<+}howSeqlkTUIm;X54~Tv3*Z|OZ{$iOw?I*eRhKRB(YsJ*B${q zcflbuM%~=7C7fvGaJDDqtxkEl$FX+GHO+vc$14Etp_zW6A=690Z(8-ub5gFDsY9-44g?O(db}i1uI0JqHA}2C z_%1Da&8;CV!OOPMaWB*f-GN$9t6V(VixS#$zXOv`Lp!egu&EQQk(ui9p0-r$jb49< zvxAYsA^Yj_qpFg$n8dUfSvJls0#1co7`;<5c2%%mebSi29gwwXX&JsQ8mO)a?^L!U z7Ej-KcC&)A1irnSB{`2fQSwwD|I#4SzLba5>f$~;6EbNZ7;NQ z{OirJ%Xy<_N1(yuBVp^CBXNs;%gu;_Vit>VFgmX5(*8e)_8IUb+Bdj>M*JU`v)}w! z;&8U_w@a9-nf{rP^TWU_2UfBeIxhpv`n+BSt7C{g+BO{Z`&_yjqg3y<^{Dg6)6*c2 zzP0%V>TFy|jbf-qM`?i?#=xzy->R+I?(8|#f{td1gYlbUsdFBXp}f>MoS|)f$^1Y%6an27grzymr_bbt4o*qU>ycW{A}-PI`kEja~C#Jfp<6- z;giSAxRJucd9isT?DrCF8`>WEHPwKMg~Q?(?s<{(UO5}3LkY=3m!8Xc_>rH$_ur=cU&U(Xn>wlp zBHD6yTe1aB=5df6lyEb29ix9|8$`C;hS#E#xnQcvOMW&o#l{jUjhvSi(XVZTh}M|T zAd1oD547w2TIy#~N|1`e57sP0Z-H6gLdkror@^)t|_;pbM3 zw#}dqaIIV}x5VHC_a48#6)OSm@w}iiFtM2o%!oC^LlJsB zLPb6}={bv_1srWDLpA-}ne5Y`dtB1Z9}S<7;0K8aMtE0L*SL#7EovF!XZ}@bDTwz zd)1MXx5m;1#!t`w=5$^LfEEQa@HCY|e={@||H3r>PL^t$iMdl*(n?acGhi6zI-u;; z)k;)ht__PJhX^1R!;AFYy*OZ6fj0t-&}9XVBL)ub>t?Jmvx@HHc0VR zV^V|+qSF<}?HnA@Ae9=6d(Z7liAt7AheneE%uw?$ZFF_pJ$;a)AuFwO>M!}3{EgM& z_K>z3 z^%8%oQLcfSgROA1vOO<=7Q}gTPi3?@(*i18;RAJQ+LWuw%6f%(&CNz}=Owb6+sF5B z7x-xLSV6!1j)UP|aaKkhF|j20UmN$TMjX|1RoEp3Pbm-!RIFR0mrJmI$YMgTfdihN z=?33;Ex%o@TEg1LTjSHGU^E6>?0GXisYFLDInzj^!A5yNgN$wj`c%<5#CSEtW1Jc~ z#PX~XtvO#@mbESAF&+Lb-CT~5x6#DU3?FAz4^QTtNZWPk%{8t2G#w%wR_a7-%` zY-)&1K~PCBwImC=`8rv%1P_6Wf(Hi&>)mT0bdcn5lLA33gg!4ziFuWCP&Gj?Wopqsj9+2Nu6IU4SC{AXk*+*XpMiS!Z`iN3cGy1* z2ORxy4!8#+S?Ks(ii-Nq9kDhXQRShE{*8sAtQPO85z2M>34I4jaTX=_87(Uj()&Pu zg8~(2N}!wZh2-c4G*_03LrWwQ@jQ_>hgb0N2X5E%w3|?N&;@W*}ITDO_;)#LlXx1PCYR-~lNc+89ym(DMWqp}irJzdKA zB8DH+TY*hLrGuu1oM;pZpceW7w;xFGk=`NQjGP?57D;tb!`}}^p;aVzE_1U>v-11Z z1>Gy&X=U?;UH(P`Z{=mb-Z4*_2Zv{lZ~QA+(fuaSURXhCus#K~@L}_0Z@OcY_~WfK zWzhRML$e#Z?osM)=mIu+nCba#_4G{DaC=dw{)w#ju8vxnjsDea*V77C`{>f4L)=$3 zG-NTgrfS_*GeJ76tzwY}Y>8c%l9!j~Wy*v5hi8UQGF}_y8mVzP4m|7RB*9I{#$<0( z$=nJw4;K^l%(}rwodKT?{lK?Pb4)vXEJ1mkO4V-&HV(TT;|`PwDCu%M;{Dt%WxjK;tz4S5++AEp*2V@F_tWuh-$Iv>=C(%x04OB} zX24G4*vC5prz5HXLuDd|>O0(v5!2IUAtQ0H91_VC@SNy+=TAo%?lKyU@j8SgF-dgY z)n@l5=6JZ(piBhzt;9xdqi64;8a~==;PvaDONo(jj{m{v>!^WEe`6^0icIqyjdaU2 z)q06WQv3=WUJu@Xn?Vhx7-c?>8%qiZ39`JD5w?{DDExc-vP<#Np#4Bz{=}80&iQxe zff;R;4XH9kMCOe}W#6a2wO`;F3=B*P4Gm!=HO=5jbq2%e0E`yYc4Kal4R}K;%quOs z(lHk1Lja?1$o?yE>rdY^10gZeo+lca88%7gq8j^28}&?^Lj*=umORAHCdvXemoCTG zSD8uF)HMCgKrnY(Z-J$&m&2OL{`FX71+Tu((r)T4f9H1I4-whhHrvv`-OUdtyPp8A zZ}ak&hHbYGlrXz^3TPj|7V5;{j6C;HmlV{W@1jAXkT8F&XBo@>fNbpfmL+G=%Aw^~ zhD=e$yZDvg_TYHczZu|*1gh4=mDm^1gA<}V5cSGltTSuC9ADKx{7Tv4+0(=0T5U{| ziPqyMKqkEgb6*=MMm9Y=lRe_ky$PYyTh<$FBVvKrbE^(qT}kO!1f0EcB~NGSd9kL$ zhJ2ZgQRoD9ycu&od)Mw5`!eFKuck6G)OnHtu7U%ZTJ_WzyVN3ppUDl|GGF^JY%}TM zUJ(2UFq*_4Zqw;OJi();BSX(Nx}zZ;Lz-mpRELg9ad;F(ov2P=U<_y0N?|L}MSlDZ zjo`kG7)L{g`nX!b`fxKP;l9d<#c%fNK2>kp9r6r}!_hUsl*{%e18_|Gv6T=8vcpXd z9+XbnWUhzY-xxa7O!mp$+X_}GR4NPe6aCR>YLd6WTtH0|@^mc9RPoRF&jrz1=j%(t z>sxRFEX<5X-Aajl+nF5>?L`D!q9iqgof;kt&6c*cfs71M5kb=K=%3JxQXHnGO4C6- zbAV+;o8>=`ZNG(BIM(!K#SYU$Ya+0YEnBg)wbjH(*`{5Gs|^CC+OF|ilOnOzZgH@T z710cdrR&v##H6&)HNNXdE65aZbx#Xo~@=S z*fPn~M1M_ql$#%#Q7x7H6b%^m$CLx%wNm$96|e<sG!*d{QU zqx0bJt~*&@eW-Kobirse?a1#~)=+gZdD$Iy@YPgh&CJFiMm2ZuzndJ?9mZL@con#J zoK$@D`#)h^4Q@~Z_7bcpacYTIQS5I-5x1YR8FX~I>TI=JKsC?`eOQn*kZAcsKUmXE z`%r?2pR8iGfTHE6Vpw+gXrm;7QYTBa6YE;mZD(re8hbtSa}b>5H-LGoi3J3fZf`R2 z%9qbr>t+f_q?`6vZ^^K5O)}=eS3lX=sypB-VTOUYbsdN9u5K0W+wBmd)7D8H zycj+MuwegCtUewun{IsSC08h3BB30fI%IS+P7%pa*3rr7L>@lG6-lz`+>)z5w%{TH z>2*TuR#p(}5Fp5c;FBL29vxa|1kTjt&8bL>5Ec;uR;x$=t{Q`46R_`xq-&7C`T&eY zEK3)$z95aD(2$<3yP7!tvW%_IZUy&|IXM7kwk`yWY z-Ojw)D6^Z`1uA{L+}r)Y&H zTZvm0h|Tn#s{Tt`t2F6YPj75YVfxk_y^8X<+Ji4xt1(8Xln3NV?sF)b^O*DMH4B6x z(2#URPuj9C^lVzEx(`&??J5Q5IyNBUmnVDC&}DCsc#b<|HTJcLftaWS4)<@*=5MG9 zI6jE>l{!`c5+~wIspFid(?D0((NZ5p6`XtZSsFUrje_-m+jKHRbwO`13Ko-F?^W?f zF{|A|!X~7qBUVuh!6=UBfq(?8+sl`tp5x~!!$WI*0_J>5vV~xs8+E4<9orQ#)AE8F z>J43i0z{?KM52T{Q5FDQA|qo95gRmdLu#62wqb~;C+(F6&mG+6xlx=`bLRSlgf|ln6)=Nz%5-EfZJ76-Ij@-B~AhcdWx4I4zK=t?*Xw zHB)n+h2i@k-mVmu^aU@4mybq=_nH--zHDRVVZSQsOBNN)&#r09E2E1I=$3Ig1e@^+ zkw7~c+~{@oCQxsyv8^UxA~09}B@=JGR&ZqJ=CV78(aJ+9YbQ7tn%u{t`O#M^+(SF# zJKysfA{G9CuFM*g1qBu5d;>UO@UMXDvQoKMuM$alj<2$l0%ndtB%?bYs1J+=9u-xh$`p4P|1Y1>s2760oi;W=Y#~t7X!k% zGcw-_P6lk0w|T}1&fVY|X4_91@dOs(#M0orwI(N0jGHdf?I~{M$CgT!1Z#X};!@XN zcFI(0UUY?SX0Gd1Ab9o5U-9k_TjfpjVnOhD#dW!~bp3*%kwypai$lU{rz%)pvqQoW z<%*_Kk2p6^Zw9~%tQaJoDp~RY>^Q*8bnnGa=pYG|u3ud0@Nj_*kV6Xm^J~3bGb>^M z*P;1+s)hq`{w4yf(JQ~YJoC0chzEcb01A8h=tU*Q=9TGH^JeQ0>rEap1Y%xFg-YpH zu7!k*vtr}jmeWq305+B1Grw}Rp`&xqKQ@|leV5G5mw9WF)(XfD3t;}32b?=8gbE-E zVjt9y{iFERtRSV%W0;*2N7u`H@DmP#^%8`_~a! zmqQ0u6Q48IXFU)t-jfVYZ-*!FbiK_i7FU!C$%u?WN zV`J_e$t^B5NVpT7k4CIoo0?gOf2q*|e!Zt{7CQl117OL<-Fut{_sXa(v4OlY*p_VY zZ;#B*98b^wo+>4_NyCrZE+Iu=3Ttq8fB#zM-t@@devv&<@V3FsvJ_A6ss?7Dj~8u$ z*$^aH1rjo_lWpHo_jy&h#lk{*$W2u>hAD$`cW7l<>aw!3f{#I95#X5O;yV2iH3NDe z)Bd-z4G?x$Z}ThDq>bYw1tb%*w?`N<5~JpdY|vKN*mu8X$Gh-ha8$Jb$RfEn-GZ0d z(ULMg0PhhN2;zDC^+7!nQ)s+;&v+}}*Qk@8Yvkn8_G|Gl9h z0SN8)|d)w=4+2CAyhbLmJ)!L zr%?zqaFmUQv#m{)p_eO>1h}Lo=L1QvI(>rLItGEP6agC_1oZZBFzw6)$dv^GTnNxs zupNHhyk*_c)F;N&<69Q&>b5nN%*CS7lC?52ii=J7MvY7h<(1(~`pTTDdCbfTZP%XX z&2FSB9viPfHn(_BeGM;dAP>mqqHa>P7!_bv!;(|IJ13wiWWUp~%|oA@iO(GWik9Cz z0Q2Dqh!+bBs-vP$o7%mtc&RN_8}-W&?wy5w%#*;p1nr&^ztsP`C@+urFt9& zzgyQo9G!9Brs2xX8m9sBD?%AEMVodhX@H@3TrnAFavbl?Ii+@f18Sq3D{roew2IZKy?M=z|sphQ-qO$bcU~ZBR*FWU~ zG;PpU?90o29(Wkj#=c+Lz1<(H4~*Rtm#f_LT$vb<17#{ETt;T%GQ{v2pb-Esv(Alm zL$tSU{YMcLYBKaQ#edQ$*x7koSyiit+e|uVWUVy?lKH^w3OEdXA5T4ohqS9W{O;<9 zpEu@{igL_R27=`kiy`kyXU^6)9%Tj&>O`BoQfw~HHB{JH%5AT7JvV^*9#9E4Yn?;f z6D)6@2VB;XG1-#0=gG8VSA8R`WIkB=VE*!(1HNLX=%#u6nEsGLMSg#2!s$?APKJ9X z;OQgtbB!D}ymghZOQGJ{q=Y)pAf3}21(VGKZ!t_ka9EL--rNk z)sColAlgr=+TfPzJG|!rjYNnE&6xOlTZA3%jvlAR9K3hzdg#EIAOJ9a)f<9spHEO+ z9BelxGu$Zt&Kadym7=_usy27N8|jtL*D_1xfYtvue!fuX1JZjY==1aya1YpG}&(Ot#yr=n7sAL z8{dcB2Y~$wJ(+Aik%Uda0Ybs2)Wf)~v+x@>R(*$4UkLU-eZg(_EGz(oa3)!m!Kiol zB9#DYSZS@GMyYAZ~9<}XYIOXi#$^-;L3WJ&XA=X}i; z$0s719R?!Esvu5BrS@FDD`aaAff3Ea!?M<*+<`Li)`PeY;x&C3f8G@qY`ZmskjO(` zSiLO(fd_B`u#}dX1`}uUS2NL4?E%H9OSFfRB=J0Q= zD`ru#>HEB_jgut>jF}=1^wteMQo_m_-~j;(1-$|RS{ym4gYj8|p}`_!L{5;8#q`Hb z9M5NKnw{FwM>rh9;X$_e152DF*(5;`SVDguYVe;tPYc{21io$&vp$a|iBw?E=*hh; zm+NNWJko+&4SW-Rg>_u;cEQzV3lElPw0N}bEwBU+NO=fpZ)%#QS?>I>D2ZH8xhU+M z=Q*M0X1fJ^xPxX=a4Bs%cWp)^Dc7-?{c}Dl7T9kfc2zuPUf{&rd~1Dzbi36(lSKeh ziNX)f3qR21@2)N1o^wy7yGplQ6(4+K7rbgLO~J+NHaxnt$kz7}3u<_GKsI=mv8x^i z)BqUR8er+iRI^y>HlbJbKts$17ES8L8L8=nR?%rvvM5-C660ty!dG(wBO3TKoj6A? zbP)Gujyza!nzC^YKw(TGv14;pKmcn72i4GqR=1q^cjG$>Sl1*%u-I%`Xh_rQ(=LIL z9YX;1-3jARRNLA+`WB=sc&lFJ0wu=g@ck-EdE0oNf=|c$*+q&(p@yy^ES)QWjM&RZYR($fdQCPq@E4@o^m$|9|@!%L@ zei{2uUPVpAs2N*uov6lI02YQvkt*kYmVPDecW#X{2@@S|92~@z*DV=MQ6`bwnR__M8)cf9Q7gN4;SXwWg%Ht_MH5D;+zRq@ZgBxf+1uXKiCoeg zyy48MHJU^{-5Zvi5tx{vUkg!lD;@P(^w2D4%q;r~dF&CMR<7E>a%Xmg;9@MZp))~x z)J(44QP=={QemW_`K8Fkxh5mAz{`}IXH;_JR>zA%&J<58V1m0TpSm}!EVAco@6>Sa zpruZ5kcylxJv@DHR+fDbaT{1SABp!7=2hEy=hsBVND}?#_>p11kH-l2&U;Zy0)_E+ zXttc1*od&-kIYCad@Sv%AW3i--ro!lD2&o@{bFtl*VcuFACOC0UnekKQ4H;+9>Ua5 zJRxa={Tf{yEZ-@VLUv&Ij=23x<{G!a>|O%_w|`1k+P)oI?DLa*zxuvS)U*&&Q{6mcY(c*u!*rve$muqATv9ZLn8{}CmuX(k-x+~NEeE&D6 zfB3iRMVp6F^~Fb$0*j9f!O7DCijh)M8b7|LxucoXo1sR|xb!&V@N3ooymv4#D_gvL z3;a{V9V*p71SNZ*-?_cov z)3e*p|BpQRUlpH7BO~)aTKta|00sWHM*d-g|3A@!VZLoG--}f|>XTB2GtBiL@2`sL z*t{>X3H(Ro)+RjyMC?5;J!GgA_a_~EC8NzM!}K45v31FgJ0XdG9<>(?Y;R66zsCL3 z>Zy`@Y7|802_taSSijDDpl8JMOerM0$eR!?e1th?M0z@NKlF@AyK;AwWmI=ySY@DJ zxSGP*{fry=n!q>qN&&Zb$`9Y_aRs#xAvloz*KS?=HOnmAkKv!{2Y z@;COaYeH7!Jeh0)4b+Sh%zufiZqG{5(%aiT<|-`u@!4P7!?&wd{%Jd@qxO7OQs_!9 zxPAY95ed8!+RzrL1i~sME4w`=!OfJood&IYHKr`(3cR0`b%G9((;u%bRjiHC*$ZX# zcWn>iw?yA5Q{v#pJ9Gw2 zOS475?4&;Gl&5!n@*n%Q?Sp{8Q>8?X?)F;(J*SIdkv87k4_43_oc+6@t%YB1`$^zUv+su!yD0aA=A@QFZu8wkfj1I z&TfU8UHGd81@^FqG|NUdD+6cBYLn<>u6>WwmiW%-xJuOaKAOKutrnnICy4ceKqYvz zsiRkZ`Y$k60Z2|J3Ao|W?o8C3rlucrAMt#0pWs>6MOXGehZWnu>#lLQXhfO(jrt-r zey-dUwdXSz-IE7quU2DSZfy3Q;DO1;JKwpKR7VxrdzRXn;XNmuhSYMeFO~NW_vXw_ zhDvPaIY#te*FO*j4*7`HH|IKdsMjy6T5fFTUH)A#4{yldvplhXUy*f1q?qli1ob!7 z&ym|z`{kb08fzzn4!Pre8L~T3{?5m>sCu^t&L=ihs(Rj;WATAIVU3+?rX4C}yQ*DJ z8qQAaPl=or`>ySYh!&d2EbkJfRjL*kN8L26ZwoY7e6=P|iSsuUSO7EosoX&W9q_7v z#9KP%dps#}(zWXR^W$2i%!d=}a;2143j3Z97#B^sreq7wjkHbcA|Y07#vH$C^SSNJ zoWILG+J1m475@7B{CZtyN6QZR(w>L>T5?W?eWxT!_!b9KbUUE$&}%|$r1HI`VRlBYS55BLm0%;-sZR|7>6u9YE^41# ze%)jebL&Sri~0lPurjCfEr+LY%A$0a%>KOg>uGJ~C8`bgu)#1xBy`@&P|`1Y*h}(V zTMo%^yJ}20W87xR|FhX*5D1|DQ!!3s{L9~2bE^X;(Se$dg+7m7OSbvM>-OA-5R1rQ zb$lfOtaymE3%CxzK@{qS&3U}&EP{_ITIMe)3;WXf;U1N7(#Z0)v5W!FJRMckUz@(R z>yHKlk9S_VLKy`XOeyEbE5)AyG2I~AR`k&e9 zf&s&gZMJ{6bz;mU^45<%PSqDmi3_{#y_;Xk@=d7z4trkFW_}u8VT{k8{y6S|#rtB{ z$2_O7y8neQ;Z6X1q-E(D&HhE=b8CCc9xKS))CjS9N738U(+#n2vItH1QNteIm`W?QrjquGNdtZFafoF$FCG1JWg} zjy{%LI2>lxA$|)R4*U0e(4ZZ7Ld8d1({daM0j)h1;GI1aB2Ukhf3Ec2G$6r#>J8A} zC+n!&i{HKbOk%v@IX{^$W#ZFEG%@{#r*Mh$Q6=F~YW=_?(pG{&X@pA#I=sa#U-R8| z-A*uGgnzw<{Kl)4w)hz?-@0h&tKFY#U;Y^&p;_sT>fXA$0E4js2HOz;(W8lmieO2~ z`IY__4L|Ad0A!*9;!iJ8SxWJM@S9hnF@&m?BtMvrq7x!i|B1)MoOx2&0X;E}Ue}%x zN@sp<;9dm4!oQz*C|}uK!gai0)UuvxBvb1VUKv1d!F!9 z?}6@tmP9&7;h`_~lrrTNhNQJ}UrN7iAsmG&CHS5>1(ViOy6 zpT~iwFn!`_-wv^p$amGfglPTWZ)`k+ZZ}dDGJ1A}im{Ajl)V0};N-;%@3#E3j_vG6 z|5Q^g6431*-3h!0ty}I0Pu!FOtD+4M%bz|6eowpwT93{SykJjz`7Rsz_3U6%VUqN} zoBMs|8xNWoo>TD+dexo!-;G@acm7uu_X;j@WV+IfVk*8Tc{9@=YgrD5`J2J=z4S64 zpX84fjo|iKN}ApuJbLA%(Fqi$MONu~6@bnf0t?d$MyImMo3h1N(pBCA%LLkI z+D(K5gkzgDt%ps;7wJ`F&Av-H`@m5p$d$lA)k$v{TFJZkZFVK@Vf&j#K2@shdHq|6zAHQ|M>7xj}(b@MIHBJ$ez@yi}1|!tAN0Lfa(4%zRWm6+HCyF4qo+( zY#YL9GA>@nO3t+i5pTKLT_t%|4e|GjEdB0mi`^MungIAUaf8szd^fG*di&kxN{CXt zzp0g6<;42@epxU%gC3toSrmSdILgC zmEEGexptG5PbS-!gGDy;(p^d#%(6>YWlWS54zx(8@Ms=GRTtxO&P+yO~_Gz9&)-uu@5w^QA_ z5#~AmE+OP8Y|_ZEMvgE0hM_*WkzX8mc6KSXuvK8?(-Bvqv1lH4!c+Ztrw~WGoiNzv z`D3Ao^(9I;xi!3QBI);3vdEqf>KX|v@6OHE%>JcA4^RoW1&eED}iT(EvAnr=h2P;m0c-Yh9t&k4CP(!G`KMD$oaf_H@6? zrdA8=t^+6v5ZAyb(8=G2^TqN_52;ggR;|Y5L`SM!!w@jo^3XDZFh!cYweVxuNkFo*wgfT<50+EbpFml4!OM z^6-!L#=FXy2M~iOve6W{exH+P-s2Uz7XQ@i3&Mva`Wx3$dfiZeHw&!tSh0p*qPVj! zds`g+M2V(hZtR*kIPTi8BD{MdQqt6UgZ2v~mgb;O4$L=cIUH12km6f{eNMGL0^lMA z+?j*vuvjBqX|w^bc;YBSGUbfjsU{M(XTAw;B8QWOE=ELKf+Pj_-%#2>gNkY8sO)g? zTNkCIs56DF29)vmlYnw|(&_DdI~LEd76D{lGGreEOdVxdAP4}CPp6D%nXBDa`NGk2 z+Z`bJa8p`*4lnlI+$cKmL>{hvR}h#FkJVL%g@6R}Z}?gO-kT+HduGnst*{Ui+?cbU z+$rgqhC)dm>hN zY5DT@A{D!q{!xZIi+WFm+z!*(`T*`!aP{G&6Trt(6RRvKS}HD`6HlFBF{c2aGT9t@ z$Tl@z=#dGi<{xyWyxT3>%D*PZZuUpz?@IL$eaZz8jYKE;O*p)tUxJx*JqP;R15kXO z@k=#gi?KTJKJdg*m5>dgwb3k**0vw^R*@2$1BkAb2jI42IPn%>?&yS3Vm^zNiKBqd zV>_4W4)*Rx1|COo)@(qxX)_^Erc*>O0Zdge_U5wIB5xAw$&c>(6h5H`DVW2us*V zOlqN*N$HohInR>*@j|LJzNL1`%QT(>ES(26j@@KEcE@FIXISSE1svRX5Rs7BTey!} zGwP9UN5f)y=dgUH3iXj44Rh=~JrtO?wLM|)O1M~39q`iIpd9+F@sbt0^1=N->tED0 zZO$UFSUT{IA}F5wRFrlN7mq1YTt>_r2;eZn~wv^a=&tJ~6T?yG~yf3@c9U$W4CnZ+UCGgba z{RW{9=Tk7bj{_O%va-;*0BmLZt4uuaFjNLMR@gTm8G?!&l}y_1 zwy>dDb#$%B6;vh_GMF}cwss$48Lj@u)K^#fVQuG56iVXa%<9Kv zHK-D(VT$SZ6G0B#d|(@g0-gX3#ERT=z$z9a%VtNf?k)iJo!87d8o4|g1zlvt#f^q$ z!vI@y@mw6J^iy|aFu8#DIQH?jiT-6-yVfX%3mDoa(rl)q%9o(u0rL*Lxs+tCYe9Jm zt=oqd6yZ ztTeT@o>$@bf{hhR3KRbeD0YbeV0Kf%L^$W`+PP~>l7{wpbU%Fp+CBJez;N4Sw*qpF zA0+bE*7L=_GO#6y>GyfG%OC*qe~bdamF) zH67@C6omhf@wpvLDnQltDM5{+^|sM`CgWrdD{_l)wE*;W($otgU~NpvQNL@s7=$w+ zZv1|A-7F zKx9PM0e014^X3tzpK8qV^K7rW;ipU209_?U#`c!>iJmYLEw#P;QTjW<^nT+v zj;otN^S*b&_!4{ek*P<#=1BFsZ1!v#P3H5;sdWXW=l7HXfxYO9{K-V4QV5dX!`NzF z9r?*KA^3-g4yppNg>c0K!nJ$UJGlva-J2l3+i<0_F>be)2B3B|6J;kG1WV7$=8vNw z%>hR20KmYAT%3iLr4Jh=4{3AS<&{2W0kXIFgcB?VL$Xwxr5x4>5|`Z%nL_j13*k$3JYXo4_Mpg!54Q>h820-c9U&sXJfP z8L5}3bAWY)9sKUYR@33b(~sg&ReFMc|)N!yO0t!M#5O9zp zy%UuxRisN(KtQVW5+F8|j)3$gARt|O4XBjRdkHNFp_hcv0wj>THAIxSAz|L&(oKRw}0Oi?xDgfh}YA3iNT)(@Fh8I-p|} zZI%0(QRkD5gO-!#cTJDAxfhzCeDs3PeLJY-)0SS`CO!#1$*3&`l|b2uvU3&_C}8i3 zlxbLqStIbr@`*NzLoFLP0bmRz=Tj%8`T;R2nK-cB#JWyhWP*+G^q2Wy$&liH0DP)E zosmMU>-aA;H%s}EnVw54H=qL9LBMX#S;&NHJ@A>1M8;ye7nL$<18%QGU-PpU*bGoC z^@daeo|s>JwiS?4Efe338dU(#ylf>jObtRCW_Bu5tg8}}cpR2l50(bE@Xc8XH%9#l z^DnCpRNzsDb?q}saTarrVWL?8_f_K+&5U90e*shn-L-qyIx>qIYXMO2p{46`(>L_X zN6EF~5U0jI1XL+Mq^9~{<<6vU8NXhf>_M6V1vIndx0aOA2zb=@I;8^@@Zz?69;!XTubmlX@>8osORHFr7&%vxwloL6kj>9La#+Sl?|7gbDOVkk^#e zNFJ`~Xrc)FZ0o8YJ`*Z+351yT-cu7ZUxQ+Pr+z0SUGwaYto;gjReY0tEjVVskSyUFl`iUF zaqKdWw*ZUn3)p4J<4oGwEq)8MvmIWZPMUqM9W%vC$xDRR@EoG-%v}nl@b!@xs}HNN zmnMv21faV1-XlN=!puX~RiEd<0GbeR`Afaac}}esxz<2YZzjzkpZ^DBIrlvf|U$KkEB9(nLTZpfw{Q=pP{7{Gs8t>jg3%e z5l`*rO!NE>@z~pbXj!_<7OC$q%@i`YoO)V}kAN(!@`>)2dTz_no;)P5-r;-Qe}|kk zaRX& zpI}N#Q3vm?@pLoHuA61~U3=I1A6+MflMK(n>#jk#GaM4RU^33tA;Z>~7+uNg2Q}3{_Wu;7Bry=4O zMfO>JIFw;^*m$6(k537r=?M)E1mPUaNEqkz8^QwrTMH{Thd+`IV48)1(gS+RaEm6u zQmD9I_+rJ58^7DZTd}C_W4Zjt3?=DxT5fgUB#cIPsni^2{=_96B9?BM(X_TET1H;t8D_i`~X}Hd{f(zuJsGfQ!Q0Iw*qf?=b z%6~@(0r^;9xhoDXohaPVSUeW$wfv5lF{aFz7{-#XSQ53cqb^myHG5}MJ%ysEs9o_| z3<z1ieM8}3mz9kgApaSK%tvqgk14Nc1h44g-pMac9d1zF8qL4|Vo++lmEq!>dLPgDV z{k|x!Db|VxkG)0RzVH+TDPPGc8Hp?)@7M2#?8-OdOqSIpi#_{1j)DIR4It#*iTnF< zV!M??L3YFr8y4{r8sq!-6oCd(Nw%q7T2svE_PihnB2?Cxu)q&cD^ews`wTK1-p~p_ z4TJaFci*~o2YRi>t)KfXT^GZvSPt18p;;$Ok$Z|yXY?zJIq~2v-gm6_o>Rz-bqx7I zRG%)8mzi1n@Qv%(1B`$^|AH^NJqxDqn?9K;=2py?6GBDP@`j$OUbCSuFr7O8zLf}b zLVWc=!#O>|6hccw(As8g#sUH2mJIc>sMwTpwZH~uXykCEsi%_cRr|mJtMRuL*T5vd zY|n~|tRo@;DL|}Q?fcn5 zqwtMCWFFxOi|%>tsI!ub{Hk2LIO3u31-SI|8mJTSa3sXs5;oua`lxHt5pGj$*lo3d z_URE#Oyh2S5W=j9yH&aT`d>VS`Uw#ed};&q01r?Bxkqa*m~-7K15hMW*Blgo48mu766M<&K1hCqPW zotR+!rU5b$7@`iuGg+#~(~-k0^s5fz4z1?1chU<{=%L) zmsj(_BSqPPAYA)cVrRF<@k?zKwm1L1P1*mpNTkfd1tsuYlkBUsooB?pBok-dKEUjs zJi#qP?w4nmdh>^mF?0vc*9cGS_?&`ZiMXrERcKd7!EVBDQ;v_#Y7KDM?)8YrIhRa@ zo+?lAj?lIG7?L~w&4^m)){|5wHr|{jKOU|WA|bv6#LY9iC^?q^#qI5!pq{+W{m+F? z)150ZS;AUMIJs7zzr|L0)k1duV#|O&`6%jsYbv&`JFy`Fn+WLRWfhp6lyPRHm4&Um zyy&!==y7r4MIk7h-C;~jRjzBHl;9dRxT-AX`fLYkzG&}6*vsFrWe2|c?3Ba6%EQF& zM41b;Q%}oi=NsHg(6--s)B6em?5{mn)g2g6Hv#!pR5WKUGVD>UHttozJY=_QjtGU% zAJd4Xn@*VDUhoOKXD0hvfx;r6pC?-?iKI3c0<+6J2h-Gq*Z#2gc7(ky+Zh(Vt5)N= z8gaMeVTf8r_NV?p166v$9mZ7_6;J3R!<)^mkF5Q>&8m~IuYdPBJzy`p&d~iKX{Xfm zc$ZEpwih2YH^ao2?px78ppd%1H%|5uq9~PWl?f!KFLWPR*>qs){Z>UExwbx-^R!xvc@;BQhU+T-5XZbGz`8F^|)gp$;jW45yG|sd%qrj?MY7F zjkAM#3wdw9LBvqG9Wu+`%U8@7*-*CMAAA`~+E6@} z)Tt)gBx$IY9)b)&$pz9!V>Oj#`44QH0j@%_Gcp2s4dFa5_L>4di0-PUgjLuFWepe`hE%QDN*G67_ZbL*C63yy#_DoL%S90TccwN>SN!{UnY6++SAe z;Zd62XstBn2jUHY@3UUXsGL7|uab^Z6J1?~Caa0s)y;1j!LF6= zyOo$`VjE7-($?IoC2G})Vg1)C^ao{fXig^myJBrgg950{!+bbRNiz+5B+uy(HPNZ0 zLoti(Hrr5E!!V$J8^aOMBE$$}Sb?8+>HOcBWsb4k4gw>ps1qW#qN{hCM>5AE%1Xw+ z894DySt0CuWSIWx$P4ToODR>~ycJi6^S*TxOPzmi6)T|pjAmpfu~{Lw8`s+lMeb`n zUkrcVb;^9MZn&5%zT;D>)i?Z5wpg;JL~y>MY#jd24XJ8BRDC`1mGAj{%eSSgpIbo5 zkwr?5lZ~Q;0ogvj#w2|D$mcfJcr^%x4uF68d+be8L9L-D2}0t10efT?}GAPb;qw{E`)Ur+AjEYTghsP09>=|I>NCrzt0?)<8ImgO~H8ef_(>1DqrRDOu-sfHf+ zye|cSwJ%A+?C68}2lX4C79}N>uKryS*9^jX;UFL!HPvY?muVbFDA1=VuIXhE8kg0L zm&5k!vi63=vdw{FnG@lv$vL}`kR|@yRs!woC|*=AUaieQb&RusP~GX#)4@XZS8hy; zFNp+a4KyQldlm4lC(A}n^|97SEMJ!n4@%X~$LTk)$T4-wonKoP!?GRU{WjOSCQ$o#Q!C(Npr zS%Gs@S(K*Muq<-Jd-&UM&6sbko!Hbdo&ceM(&HwOfART^kPsC(FCfiKAkTbq=c z>xFwu0-8^$^dftxqz%|-*00B@ih&y^oyTH{|j?ptW(yQX4J-0 z|3gR8QX?d&;wi_4^+Dz8_LVd;>4ANL$Kv$p z@XE-mcqXE9}h)bv~|<*MWhGyrA(n zJp@NoJzp#D#~%;%R}V@FnXD+phK5yfQGQMlijnM^-7V=#`jrkAy(oMPMdxU@i*cx7 zg=wyA~uF>Az`|RwiP- zb$L9o{vXt@{3t413vrR|4Ci)EgLg`Z$ojmPEs$66oNA`1ufRe{Zo*?zxWI51ta zsN4HPvD7fXQ}kz5o(zR~GI5UHO+7;_%qv>))A!6D9@n2JyvwK&5JEO*V@hyM*#XpQt=T6lBILFNIRmGzkTcOIEOF*m; zum92ft#ZgcFF&8y06%a+Eb8*+AilgGEqpzzw6MmBaT-_qHS+9gBpDtSpZ`HjUVD=*}Gb0$R`jNs+1QVMS*?Hs^dgZ|@< z36#$|-(X9N*!$+5;!L{Zkm1Ta(Mc!y*pYcfm9JoQQlfDj@{U**)SakV_-4cHPg(&l zwwh7h)$a-L>4FaW49@h8^=1P}Md5!}RXj+ijArxY&D`qM+VCq7RV=%r+$!lAuf@XI z?S+g7px^3KIzz%;X?_>Hq>@j@>FVU0Bzq213 zn$BNP{R>p|=F8sH{UzmlG#jUVT=7dRyl3pU%filCn~$>amK<%;1$A`}&(S4NLmg}d z>E&`tg97eK#fG*S#)--xgFiu%bMH|=S^QelXS0^EHO+` zRb>@3aK=YrussVHL@t#^Zhbt}IeQGH5O|WA0pDbOQf4y61>~Ob-yA*0K=iTEm zfxbu8kJ-C@=2kpKcb2~Js+v7R43|(R^_Woh`!$JN>-E0SlYwy@Uf5M=YzV%8u804h zj#1qn{P~Qtsd*~)daC+@=frz&rjuHRyfz{Fn`ahQ^YQ|AxOL%9e2VX)X#xsRLr}Z# zNsFc)Yz)P>O#Z+Q_0K&z!&uB5?3TU#vM`*3odeqH8#yN-oRkC!`(Qo07u_DPlUKTL z(2%};VpdHQqS~X16-Vw4bNtI_s57fG|achhl5v<6X&1a)@| ztF=VAsxouuIV7`0bQ{lHd&KmPFr?rwSVO4SW!zP8_j}g#KA(Rr#Q0Uj%s1o;-GA2J z&Hn|wj^5myheeLMy?mATk<67`x8=lwhqV2uR5fKAuiG_>-ylgUx6f*6LlaO1=2;JE zc}*-z7BaM*`?n%mN8%vii}eS0jE_3xoZCafn-6Yj$S-crv~@-8R*n7Gz_g!|8!>j{ zW}2}6ShH!ZoW<7DI4fT;;UdV!mgf?Hs^2oWZ@Q|Ks$6+!+pUnJGOkjM@4%!I&Zul& zdt@|w+mIvSiYjsj(T=FhbJ;g&T$eZBO3kZ$BB*B)Z~TYHM=?e}q)SluF*AMPqI|UC zN%hfEgEcScAp2X!qRyx$7@kuW)33wM*ze#f_*uj9j0L~Nr)!VNFObUHe}B!{&4P(k zQMjxU=jW@Jt0Ui=_{{*eocr0yd*S_Dhq@n_n(!%tFcL!$ZkgL79j(7*huK-!i_;Ce zxBvcjKsTV;X0fDte``uWK-87sP$>yvGtB9*eihmmj-9V0)N<9Q_W z0ac&s{@U5n%;B2Xr|TsNv^kJcn$$S^KRn>yrH%pR9f>Yne%XnS->;!ljA>A{yg9%% z6BRS(nTeN@M7#v|znDf{&$D-z9fv7iN)k)Km>tYEInVT1^fC<*OY)3mM@)PKi+tB# z+Ssdd+Uw^2xvz80>&BP|qIDOK+MI3Dib+b?)*@!~S8s}(J~DZLL+Y7KGHwUDiv6<| zfQBK0(|-~qf)@(%Jkz%?s`fA|yDiLCye@HEZI`#cBoO(yt*X|ad%QLZ?yr}ZNwl>9 zv0)H~(R#=xV2MHIi+Y&m+<+j8u?56*+!_TX;#TE2S0nZj&;K~bDE zL#|ut%M9R%{Rp;nhWvZ-xR;5RR)-(@Us_VX$mdt#OZE~i9o|PBb-eDcvG;iyRNLBK zP0~G`StB%dQ7LPT@Z4gy(6n&M!g>GJ1w|8#W$A0UN|7Xlxo9n{kRN)vqW5|7;5h>& zx(kb}Uc&p2yR-9sEXEEje}ml;+d-a`icoN2c}_w-hnFt)#UypQo=*t_V}z#VvK|)LvxvycR)|3bP-d`JQ;tUcDEfWPV7Gc;&+( zDER)q@boysMZDzwg7Fu^QMNquV|I;qbyY``GX^Ej2aB1;4zhf;yEX-N!ef;k_vEEL z^h-}D9M9!VMgUDd--clwRLV~l*zG?z#;;KKSAMB(O(~jhDp`+t$EKfTyp(_WL|)*a z=XBd0&i;f|eq2}>Fq5rU_?$yHh#gDDqL)N=TB-_n3YbHC=G%p@jEJhW9;|a+O3=+^ zMP!QLJrIF|-)h73cUpCer7o)WG6x#F`#%EvX$J1LWR}cypi%p`G{F@JYZj|jQ;BPx zy_%vID{wQd@{5P4DA&`N8uAl(L1Ts($Y`k|@8g357sBxdif&Q}6R#_Lq!hlb48H_QDdWzICSZ@{-ztTWN#L6J|S^iX%d5 z>$>xsB`e<>Q25%z5}Ta|voIE)0@+iVoXn(S;_$-denZ|Vs++mmO8J;2I`^QH6>J(} zvkvg#bn(h!(Ou}kMZ{@abIXk}DCZ}kfF%RLOPyldX$>3Dy8(eH!ehA%A^0P5(8_10 zzh#99#SdvaM=ms%?obN|8qhZ#>I%q4g{$exS6XrB*==e~2-D{3G_xL`fTg$P0bDoq z+*7tRO(Xz+rDMK2^P7?FprY)~#`K6YBiDfq#2ohM6w^LjPKu|u(>7~C&`Y|p-;Z=@ zi4ey?S3a49Hb+feV80#ehb1oBaDX>5abE6c3A!zNHj>$#16nb>l*X~ve1O?DxdxPhd zW3EoxJZ967;hpx=bViKfEwORe!e@@`uc5UWbI$7{zXs*SUnvg$t|QMG7cu^}-Nqgg z0T9`ev1F71HBNhei#B2s{V;0m*qHwpm|n6X$~gMJpd;LQSc1Z{a^yS#>RpnG4JnCq z3k}n08ItD~9J@DXo6V*#L|>t<-Cz2cXMm&j1sT;)dj+e>`Cz*&S=xYQ>Q=PVAHm{N zI{FjuA79+~`w>I9f?wxgm8QB9H$WlGq3;}@sk%9GcyGk+F5P@`lY@;dhELvzU{mhS zIBF?jl8|@L9_=mcc(9hyrkVPra75?|(;luhDohI^oq|30*!9$5Y~7>sm18Dw zJLhNAlJu^YJinF~kt&jPCP_hlNJLZK#I^M0m$H&oVmC($eD;C*{l&P4i%|o=TS~@- zwaQg}uyj+nBB@IsfgWQ5*eYW(|AWrpE4;YVYI`*~+wxUH9qw5$NLeaOE|$BwbFMa7 z;u|)8JTk?iATdMJwBtKSH-}Jqi5H(*ta@FZuFxCvm>#}-h!~zX&79M-UsGN478Xqok|79l2!?bx zZ$5Wd!&m<>5>Rb zDTM-)ag)+kjk)bQ*Tzi}7W-5LC*#8E8pdb^kioYg4HdlMkk7n?W66)|eRYi=y&zSW z^J!LxK)(y3v9K_C8LzFb0RL3q&w{u*w`{lEFf}Xxcc7^8R^urK>*U^5Vc*p#>Hkp_ zdx(7{Z>^!8J=?%+1^4nQlFgnkExy;A9<$Jfu0^@)tJaJvccmj&F(q|LorvQ_TT~w? zJLu?CLrkYxmD1vw*M*6YXMtR-Hi;#e6lr4?FrGpl^`Al`ELB8d_T_G6x7s5S?)VMf zGN`Xdr3PzmxKzV9{eHX7Y*_?0KLkPOMsMg{PYYIRoPLBAS@?ja77=h$$(&X5nyVZU zug*`Ow7b0CJd;?xXtrRg{nxR_k>Y+VD1paRch6 zIv?Pvcq>(9`~=cGN}vET6Ta1+Trz4w%1m3Oj6dwvwMOv>iVn(@K~gVg=M#MYQos z1iBxX%}@+1tS0Ls{zswfqKIG;{hzd+er4>y#Q6!_gB~l&?vqDZMNz4*k6ZI`5|E0= z=i{$wwm6XMZ)?hrdiS_hx2tNvCdCVZ_@Q%wZMDV&E3RJmTNilM0PuHIz!bIzTNwYOIMzy@i*j_l517pmLu=5ik5Upsj;vsYCqUWab+ zx?5*H2=v<9jji6wHxUpqM4P-j$e&GxFMp2TEpNxWt<_Ws^d|tw?`)&_ROD>WC%K4W zWLVmA&=IBvbg%U-I6Jo29f_?=vL>O}U+X%rGS*sbSbF1%8!$E1hqs{5F7wQ33&<9j z@IQOaJrQgi;+E}QpCK|Cs@^2BP|7kT<*M~9K zQwWGO0f9<5o1i4w2^MNDE2XkwZ3?t^Ff+bVhqXx&*{^Pbt<1hmn&9UALO@ONf~*wN zRsigkFpV-5An&?d1@TYJ&qGVv1!gx!o!xr_8WTL_DTX|kwh~15&bFfx+4h*z@gN6V zDk91{ZAMq++aT4dbmSoJq+?KggA#AwIoW}5u+`DewK97EH@J4%qq{+GNLwin)7s0! zt!nUZ?X%=eiPr%6&DL?E`5#o1^i0Q#= z(U@gaHOA|c)wB<}6-X-BJs)f1qhPtnB5rJn-w&9>({t{+Q6x)lfU-Dtp_3O^`JuEl z`sWq8q83%sFFHThmy`B|sh%ZthkwM*d4cN{tqbZuLVLzs*aQ`1^?Q}CoA>&u<9~EJ zK)0lYL_Y*Q_)Y&3#T|l5)RN)z__58>_^sBrLe8T=3i=T_Bkn{Dvaw0IxhjicUq-oG ztFG-oalPC@E;;6XR92Kt#=4&D=jurN+Sy4vn^_dpRP!^W3EdWYl8_S*NMtHRv?Udm zWbW(cQT1pY_C?^7rj^CuFtU@?$4eBf2*r%>^M}smu}wHa!zBZl95JinVGf!_johD6+Djw7;k8+3u+K=tiwTFA_FeeA~dU zU>eOlmH$q~<8%Lv+9Yv3T>LQ~9&+fFn0mRkcRB z5;I}L&&%DyVk-APUjz!8y7c}73y@79+R-tCWo{r7|D1mJCuRjG6twWK$-%!bvu*Cr zVMFLn+s(H2Za3FV_*nEOrVIJ25yR(azu_uc@YI?R+u5;m$!)DN)7ZdwP7Wb}i1s5~ zZa%72C5;CM-jh$3)L|jA+J?Rct~j^1b^#fB)^fJT$xTsp)BrpP0u(Ebkv$0jH>W(S zn$biii%r8<_cEIrev28$ABs3*a(n(g6@VCGV@u6Z5mwrOyhW2siu3Kp^zn1A^&YA!rEuC4_^Y-A3vZ| zO8XoFgxX+R8}%G^Tjr=|q|QZc0YULPvv&Y4y793DRi;MTmUe7=Ttl;D1eF!d5Jbw3-1ko zuAKWR|Ihw$Z%NnI=i#BHY%1VAPKxAKQ~R#ng6pNCCOS57OgdL`)Y-Hv=%UfT(|3`WA`lc{*3IoOcA>R z#96S{AnHie1KrTGdM(e*bhlZ0b>(4bw=B?vz0565xmEcgQH^9-9BGLp1m-^oKe(9k zlCEY6ni_V5UXg(JB-jb+22iH{Nr>36lf0i<+f**or8tl*RJ_T2M zjJ%^e#@jz(#&IG7|M{rwT9tZi`9J?+75MX;?f;&2`G1?V{QHYwipu`qL*f7X)g`uH z-!uK^q&txS-u(CYsQjNI1LY47Zh&C)-{WS~|25;^@%X>d_;)O*sQzy>{{J}|I=Wb( zOuYzHlcblSv9s9Es5PkkEE~Hsq+p`XnaEVC6|Jh|&PVsUDOx~OmR^os+d0EYI#vAk zW!Q!D$kao*ewc0jB>9*=Q&Gi_g1B-sWMsiun!H(5ioGom8Ij(fy97xN{5I2mg*72K z6JgOWCayJtNWJf8qFe8#vvTTswIt}aHU|<(3(hTm%AcAq724#P` z{Wqd2de%nn(w=sU<&MO!7KivIrGrc8&%z$|%YgwjwxE?wnc4!PsSz*JgRWdn3GOfP zy(TXBFt#@&Y)2PAo4>HI__b^Y0l5~zbs-{o*rBMloV`}c>PSMz77RUp9>>Z}V6rYO zlwcf<-6uXCP*lvB4VjiT*u>QD_W-#H7VI7@%ky_tDDu+*uIHXUhiFY#U0E8%qz$*WMW zA3Bqb`TVV|*47^}xu(05sb1?Lv4FwBhoR!MunT9AXlglpABNhwa|(g~T6ARS_hik@ z&2y-^Gj)`XACAtDZ;A@3v$eqYq*DjiS=31nLPZ_UXANNijPk|Tnqyr8n1sAK<#f|ySQ)eFgC;h zX!R(g2*ytAT581;gud}09nNd8_Sw|#2+RlL-bg%rBgP#j*5IOGe@pH;W;uC{IYQ?2 zTMYgXG#VHKqAmhigm}#%v+!zUMS>`?VUL)Pz)7xtLGw5IdQ0cD-R`t6C$}jpyxsAs zwOyRt+FuGPiF&s)ZsdZ8PS^Y`xI9$uNPc}5NlMz4~gR_3)O3FB=4mO-m|u zQwePP@uUYXsCw%tT0l}%O4g#-Y)WVQ(0!4b>lSwbK^0oXgBI>?r1qUZki#?M5L`21 zzvlD@7jW1ge>3oX4g!{Xv}2CW&As>YUf6{ud^e6ID3hyP*ZGkNSbA7!6Y748iCl5j z(p(VYIq50b;M0`8*GdR)Zudqph?%IL8$(qWNr)ENg~yrt9W3VL-oQ-W{tJ-VoGT>h8FIkjdk*+#LWUdG+luYH#H zBRb3Si}QnB^+a1GZZTs{_8MNH&6(hIs;d$MkDl2Z=~m)ix%aHY$(puXC(h9Z#GPb9 z-ZLAA9tAsBK1w7hDdS>e3*QcJ>GouaD4y~XFKRqQCDSBP&lBnkO%(jXCugokX_?$vfXnH5V^}H+0y~q?oTIecHoFR=oasrnnWWTt(3_lukex{_e zI6%L}F7<05byD4G7^z;2@kQTn+3jA(Ps9EEd~pzuW;4>!NoRCkwo7pfPfVc-vXW*3 zgJ|^j_azVNBe~F?&c^P~ls>5>btjfRN-D*FU*rkB(BP^)NrHPeU}xJm!GGPfrS)1fLk3*HNr z^ChPhg*SQ=6w31MhK||Iyh=os7d;)X>a~1`uP;mi{cd!x&_~`XS`Lap5HqTea7CeJ zu$gZ<+(1S8fs*YesnK3^O8N4>d7q37K0Mq^QLyD;+{_} zc-D)OcGp)|^UR40HKXOfHgx#9Hlt!fB~GKOo9opcj@=tjs%kk6jGDn?=mU(yszi;G zUf*+2-u1JIscn{@cC+&l9E?uh>v`2j(fX}*Xdg%6kzQ=nk`DK*?kHcl zlYhPRbwrM>V_PeZgsi}4Mc9Xgtr{y!8$Hb*z)yBcVsPZ`0r0d+q^gIT(xdUX9Ov%J zqKu{=qYV9OO@l@t@Zr2LwbjdzqTnioqpr>(Y5(L+4LK9t{wGH?y>>x8l`C&VXOW=S zUM(Ur_<##eA)58LSp&4T88&92JSC2w$LDSDKT8ZhMCG?oJ!Trn)v4cJQNV|h{Ul$U z?6sN-2K(zuiMGZ;OJ(?E8!IMPb;?1H8#g!S@#~t>T&5Le)_Ro;qGFa946a7}Xxmd% zUR$nma+Smka$xJCY`F;f2r|;uK@3k5hpTIoT5x6;&GtGAe~Trl-50*$FkS!G%Bq#; zUQN`np7m@M+}pvJAg13O&dV}ydiwKYsY*9_KBLJrm%&^e<1%&S+z&97OuhZQ21bpEREkFSHBTxI#h@<|6pZ37Q{gvW~gOF+- zG&wx1e_Xiko^g!TT|0NuGR_g$?bfT$xv4UY-;0bNLej_^Bh@PdW6T|GpS1D2W{+6l zJ4G~^9t=~SBzxu&QRE`DUWAfKlwLoehYk$Hhw(B`1gC1Js3LXay3kw0#wBjxjXIJH zBT@>!b8Uv|@gon;q2DWoUVaqo<%v^A8kyE{%MuxlES&WnYDN>ZWBKwzK&)Vp$*GWF zjI-Zhm;B|MAKn7$a^uJNx(Pm@agw2vVK@dx&wYoR9v^JyGph<2E8@L%0z@R1w4<-F z2Gt+4C-a+Q!yNGY7aYRqLsmNx9ap`NKmr>iZwWrZ{P|uZYqo;_(IvBkwn}-v2icn@ zeumbTg6(e_qHLBhU8I~eGg|l-Hsp7wmt|3wUwl@xcMV5L()uZ7r2-9m`V+$WTsGFP zy5EnQHry^T{ME({$|{z>uB$SPv_kzhN(~xob0_m3Tn8BeBShXR^_mKai-pAmS3PlX z^*xd^%B;)ueTksybqI=RT$~NA+uJ9JsN>tAHJ@g8Q;TB>Lr9A8m^!O#*662qMcEnz z2ckgCnkzk$zO7Bc7e{z%Bd~*|P^BN3GtH%BE!~*lMbnXlHl9=yBUiqonO?rITNNly zwsy!5_aso({)_6q{9TW) zVif6wc%ojTpX)^27jS^bGEB{Xvz`fK~Yz6VjA&fUfiyMl#E1euQ?OA)V^}6c#NV3lp9o_q9sCu#E zzf+IX(n^Ws^?bJ1l|0(Kz#q7!xBn!~+^t*}8L-GfsEWmgC!)US4gSMv+bL_W-iQq8 zwvZ1pyPrDjWo(iTR`ro^@4;G7X~I*IUBppUw-A%RLEj@52;6C2WJP9pVW*Jd5j+H@ zSSbXIq(Q=HJ)E&at%tDRG2rVj&I=`>tk~0u93GM(c_xv z>quC(EeIqzC8Zqcguum6oz*LvXS9S-2;;^}wb0Zoq!UXhCQi z{AiXkbd)?);&R`wJz}eJv^czwu{@3>F0`D|=%Zn8JZg*;5vL*d78isunv9uXMdGi6 z)KKlCsx<35k?88&{&u8!adYixW3(qMwzb32`lL$Ec+rMP{nte)|7F{k_)MwS7i|MrU8F$rdAb4 z_?>=-*@dLuByiK`OU8v0>JLd?Q#dqhz`bYTB_7@u_3MnPgEk(ea5ii;PJRt7cI9+< zcysPiP+(x2)nGpeQy?T*fXI&WHC46Dk2*XIquAVBl~}VX+Q(H*J!YwgT?^FR(+;t3 zy*4+VlQtq7T#Ds_9Hxd?)z4*}@mQa1xb0Xs3hPy~b82tFHSQ;SA&EHf36!rq(JBgS zlW4=JF@2}yz`Q&iHI0LMu|f3yf-6R<3KBx+hnY9cGG9XtMD7t%ArrtCJ!Aw7j_cN4 znqX>l3VKbepsaA0&!4ZJ+tKaUNek0eUA1T$U$FVCdQ^yyfFIU-^(Q%n2etdomgQhN zr)4f*SjPfGC2Q2Ydd6;{jh|_Rtr?OV?L}ECL=tQqI$AS&#tp_z7**?5*SNlFw0N=zA*rjec)M?s77(Yf! z3*WBXVvD|yJ#!l{tzu*NP1&7cE==k>jTW7wG5+MD{O;yqBS{RDG+A1`N19_Q=`kF; zQVee&*qdWaQ?_3)cFFENG!|tM0qwHuP|(zO-~oh1m2o)6GAD6G&3C)eA>3}-P5bP5 z&DgmsUFW6vaol5TcKo9 zzLa**(Qp-tExURpv2l?EKWIHdl{Hr5Uf*Y8N>K4#I2i6O`CKN7uc3w7a!(AgQrPGH zg}4bb_yK;2IbM8qVtB+d14Ou3UP=-ZR@BtrB*5*oMbQT#`Li+*znl0m*Wro@)%|_z zC!}HWlu7CSFL&&M{+#rm=$3p`(!7wRom=f@VOPJapo$6THHFx5VqrkQowjN=g_L^LVl1VL*ot&fb8`)`QT2WunA;l}#U*19KbSrqQ_bRs;`zt>6?y%^34Je$gLv zn@_xoBNb+-U;iVx2;g~+N_|fyb<(%u6gnK~>tRs0rN{l8hXB$Im=vI=wCDhw=xu-7 zO0A@H$-B41@?pv0_uZekZI)#!QsZVtnu&ufYUbf6WnEC;`8a*Og;Ds zWwYY=)VGP~{Io`K*=^4V1@e!v(|;}|0V|YVj0%tHHfyZ?o56Fq^@!b?U~=}?WTk4j z=-;Eh6VS={r}G4YYjz!1$7Q-(X*B!o_lZUSo#9)Vm6FjYX{&cY(5OBlB4-=@_P(JG z5^=3?f5MdWbY}a>Yo@-sp6&d7Dd#}J7$W^#5WSOr+I*4ONk#Zg-BSxAdxME&RDB>t z)M?zhWk;7FA}vYp1fQ0nFu%ou*FKu=ARgie$iA-T4qkw?d3D<9ffW*I;$u+SX~dxc zX~t|4Vr06Nve!*^b^_dfQ0!Ssp_$iFRP}7e$)IivkD4F#u}k)={ zH-~w$Mog0+gjUsQ7u8APa~B+uAK|0b4l(;!y2gW-@LsGeYQBeb9j1`^nMOE|2Wc}5 z-v}+^D%l-7sLk{0reWj~vJbBV&(PA>u5HZu^e_uv_zP&cV)Rm6uYLN!- ztw{NW3SleE{3wr#B}3VuPQyjBM*Q>oHHWHZDKy+{n`7wxhLV#JwD?sj@%%X?GkK$D zuWuR}i|R7-ZrN~|!v?M`^ULlRHFyH;Ucb8BrEoe;tM|x*&5A=ranvYFTXP!`&S%-TCjt8XL}6Zc_Ya z2AdXL^cS$$2z~Od1Ac6EmrIZzU{?MH%V%t5FFL9~f-Eo`c`#t{KZsKCVf%_}OW%ei zseM}dTH}Ek{36hdg1UU0I%8>6Q(q?hF|eL|8XEPhH1M?xY|Zc@hoUKwN!U7!QPmAP z6bzjEZgpd!;okMxveESjM#TPtmzxvb!O&!V7=IAgQ%pmk2?)I4@1pNJr(H*vP-UU2 z1aK>24^3K$QRtecB+ha; z)kpyKhT8`{fUVsNShTZE2(e--sIoov{km)Wp1iC-t``@<@3;7vZL4UElZPrTxQur4$lxd_03=Hpx3-@awC<7pb*VUq+K{F4GR*iOgi z;(V3I`5l{!XG8ymN)H0*i@a z+txpdfNB-j;QD1rLaMU*qEmx}k2w$er~$@iW;wnEcCNW0xV%5=Sc&UEor-Ak}NjqB@W zq7sII5l0wo#-hDsjs(-{qFKm6f^wEdBZE~35O7%kc^UB1bxKc`EYha5w?jeSOMITm z{WkI7KDM50NrIbA>JNn~q*OS!v}~14two#pW-MLJj}y7<_ialz&V$0{KVK!gO&tLw zsO%h)oTcgKV0MkKbPDf1QJYaD8r`Ru9K?(T@)B|3D8s7Y(L)Gh+H_){;s+#~nUZp+7 z)GipHw1f&LG!`q~1Ia0zw_UjOSLC?e2&nznt3E$Uj;e|2+6uijBsPb?xBB0a{q@hD z(*&xv2)}VupJ>edx2Z#X^S7A{tD#{_b1iFUUM+rK4NtAAG$5~H(k6_CLYL!{d78P% zHPv4&K)s;IV`e3k_?0{cwC4Q`tFF}i3Mrl<(BvP zYNyZ2!qX(a=Z`4aeyUHjaKay`lY_NWwe(>n^*R2Js#1D6xoGf(M&XxbtcM>G4trhJ zcLTr)z~7xmUvuSntEK((a_h}h!0?j;il@D*m#(hr*{CK&XzXe>Py6LodmsR-yGEAOFdHf0$@xfO$g06+E?Fc?Uo=|@05mcgsZ8mm)XuMRXQ;Ur#^cZ z5z(5{cx0(1M8QO#3rB(tma}0qd%T40)+(nY^!`@HPGLVfDrv-Fv8=x&w|XZPonb}M z5eH1-`V{YEd1IfZM7AgUJr)DeBF&E!c_l60v=3hE;J-EH=>*l=KHKdBo#=Vye^i6- z!8kXu48n|y>dV<}eLa3H(EC}Kea;ZIH%t;yH3<|m^IOR$W;~ELUIO4T47%Dg|$mxia*UX2}NCZU_p+Itj07f ziv+8ST@jg{+Is%mB8jabr%M;WXEh?xNFWUksJe5D!q%1)cy-|C(N4)yWgEbX#68Rl zJ_E-%v)Zk%$;uieg@tMjh350EE88S>Y=W$=&}-w6>W^|Xio9C^Bxv8Qh1sTtmg=H5 z4F7sjNNUme8{qXarPd#p7RkDCB=Xvn_v4hODFkwFyTlkl#$jA|>IIgD*CE<~#)0ng z-J73Ze^$O~O1m+xd*YgiSs=)Z$=CU`xELv1nJ9ROrDr zm-)-NBXs*1x|lpGO~CVC&md)t^}Z{+&eMfV7Auh=-mW$yeg zmh6lXxrN+FJo%SP)(vmnnJ?XY=Hl(oGEt;kr8*zt=4>2z>}=Qd@uroh7G^$#AR;#XA~Lbtim|%4;!UabbjD%)Ah;g?H@PLBaj=g41eGEoqB0d?(5tTbty%r z%=GNCgu~@6FZs+oIrklz?48{9$t|v0_CT9=pyVNnfK{K;oODrI_?e)+7Sh&CpyJt8Y@=)=IctC+;2 zZehyBN8-C_S!~5VTr%gGxn-4d)Zw!HP=4u=ZkD8B^u;Vw>zU%amoF#?Iz-X^K9J6C^};uO z{1Kd>%gTQ%9-X59+O39I@`xQy@E8ed9Hy2*ixD5@OxaJ(o}-OC$6`k2 zs*1(N^E8A{KTy)&iJq(-8MwV(e`+yJ;wpiT+GV|Dcz<7UlW=U~C;#5MdR-93UR-w1 z71S$OHcGTlK^gCVE_Vxy5$R7m^4;c~e$8MwhaeJ@o2W&_hKRnaduWYGIyCb%;tIQj zT!lZi^JH9uoTy|a0lIJC)YDt^h3c$RD8ui)C?HSF(*Ut-_ZSu(h2*&`koex_>gfEB z#&0TRx5a$dJ1Xe;NXOD5$i)ZBS2!A$SeB#HJiv}X1E_joNrN}EbaBm&tEWao9UNaw zNM1C*m1F8@vs`TNg3B-=)L)T$KVk31#WPa$ETTGQxK#vNW|P^BxeAFZ>hGN;EO||| z;ss(d)A?PD*stN_Cl_~KIloGHlciEt#*VPI9oUuBf#E7-g7+?W>I~NL-!AL>J=6}d zQv<-={Zl_#4=KlQJti^-Y`ql_7I)B$tX>p2oyR?rlAdcjpuNo4s%9LusHZ_`;uGn>EoNj))!w_mcZNBt{NYfRK3d6PW(vi5h8W? z{^wKkYtDXe%2aE)@@sr6){u(K(;=8Fe>Ud;ROWXApNV;c4U+b2TWR8#le5u2M8|;f z;fB!Rg1J9!h5jHwogvKGvp07>wyfARP$itdH8eD8F$|2mqeI=xCFOIRhud3U*l`I( z**@QKQ_c+9yqcrIW;FNHagPKU}P-y$9y9Mq6<9;f}{tE+Lu5-{QRzN^J%2fD=5`V zm6W$Pkw0H#R}aS=P{XBhq}4B28D_emQ(>?}uCj{G*xd7c?RhT3r}KM89wu?b8omCq zDR?Uo&4I95Dz;w)pN&adu9@AR6RV0#f`IStK8{Y8)V~x2m*Oxjq>qljd zB2cr{y0u_@#d>;0P_ZqY)BuK4-!{AvrDo4DS*t!JhPr?bOX!EE3$Sd^Nn->2%(JD% z*!jl-yJQBGybe7%D++&GbSJHB^L1)Kd13gs{!K!*ojz-YG?hz!KFO%!JO<<}QJ0Ws z_e9(|9Sz##ZQ}{s^W}$vlHS|!2qgS*xySxVq9Dq@9;PEj`Ic1oFC1d zGT#h&Fo&#NNtJN3;_;T0HJW>}58Lh0;LjF_pHKDC36;55`lW9oNm$_b)t~pL9J^?D zIGzEWB0a=7EE@z@3k&bfdrDtW><-m6~?( z3)TUX?N4(g$mH;CmBc)q;yJ?VBCb+gwm!4i!sL=CTVkQ-EW)!w5{du1dR3iMr-O0! zia^Uq)I&Gy$j`|A)?4JG4gAQcdCuRr(5UX+&j^CxyDAYqg-m?o^al&4%!QZ*kp)f> zgx<64Mx(ny+5Lv@?jE{yjjcg)&o)Quho>03%lDRfc@I2M@S?gmb>v>Zj}yx+GTL+t6&>`g2yWk*Dx zRoT|KVrd5*hPvTRt(B2l3@Utp#(oh=)Vmq|d(bSyIBt zL@IpP44i>Mm%}O7SI}zWq?4Q1Qcx38TBfgYRbAuf5|LG_YsbxR3zUjKjgrn;5F*dj zb96(Sp#|J;H){5#*bO`JkHmvVtx|aJ1Ky{J=iKl~_>_e!lLYwnNvL z2P2m~nziKIe3kob4sfg$>r+TBn=spAfdYAfiYhTt;iqy7lDL)GQzLu|@i1#o~H<%d&&Y z*VU#*-x!J-i3qBc&pU6{I9r9qub_jor$dQz1~z5)r!3|8)LbrS@8ox-pxs^F{D=?e z<54xmO5Pk!*GcX>ql4o!oWq$kpua)os$gW?o+1k`aTjl%ztvm;kIP4v;_E?>j_xqCE`6>c^qA_LPyec}s&{~n6~Hbz>eY-iBOs;)s?8qG|} ze;l}TV3|phZvXr_`l6HfP7@y0GPx2rwAXFi=Z_IS`#4#>J_%99Y(2cwwu!dWw`g$R zI@UWXd#rp%KZ>!_Yk0xP+~(a5hr*PzJL-+hHDkrS>BK97+7hdNvv-mu+yXebA-B7% zS83fXx3E2f@4TO{Zw4fO?{4zxkBEF9N8Wa%Jo}$FSlIV7LA}1R*Q-4a8^38v+! zS6wFi)?GbV&1(nLQ=DzO`XS5$b>1B48SDwzM#C2)i?pSVj7{?Di6f6n+>V^@y!*BV zIWZkJ+qsk7QVvl^+TXA*4fCp$y)LgoB6Ie)i_(k+ST%!i`DCMDg>G;0fo^(HVMaUF>iD&!Srt}VVIea(_ujn6k z6WT3KSp3{Bs3WA~>~MFwnNOYs)%QrnrT;8pDZ#x3x_(p=f_Nb+9~D84*|70=Vu z+^8v?*B5@5d79f9Un5XHg(|GP@k3+2D2;HA9Zv;;atOlY*X~*B;i{^IhPIVm56GM7@M-w4AZYN zSdh~X?{uXlmGJXAeV+FbD)#P64)aoaw08lsd4xWr@alm)_pTTVDa??VG%e0JkxA9c zY}K8=wE(~Sd4eiX?v|=+-MzBYzT30DAj)JfcOJ$#?aZ_uMNH1sO$k`MV$4r@xC$=k za09AH1^iVt`;pn3$RwfefihMW)wor8h;vXQ7<*Q z2ID)xvv?zS31p#>KCE=|UDuH7rQH%l84J#noVLN{@6@W^X4K!W|JnQ~n}h2rXd&nj z87>O|YT(+JOv;$J50azH$gY(d22ps40$2b03RI?aMW=B2wl-&$PDSSB3uPhqo-_wG znk@pS%(WdUP-?vX{W#=tV|irr5^DhJ^J;*9gQe}jtWC3@774KZF?Yb=jGkjEXniv_)ixlLB4VpEj8S?FHyj!|$4-=M?e zBU)xX8bv=;hQzyKnqmCOjF%>u)K~@oy;R6Izm^CP^C3ColHo9QKbp7!CCJU1o-ik5 zOxn^(0y9MT>g9HuM4?Wfy0FmbvPhoACVN6wvsKwYafr>9_11a%!Ken5p$>wa&2glW z*}{5GE(jN;c^U1*P3pC{5fZx@jVdz zeY?#C96y(rPeOs(dghPWlKWqkDE+VjYDTG+Bd}Nkti-h$OGVjYwM<3UrE3touO?T! zO>aM3ubfMAeA7A{#x4~$u}0EV=F%-@J$aO{wm*gt2u?fZ1i8t9#4!4nNF07ujAQC) zH_>%`xJdf2+#;Yu+FV_sA~4%K7@I$k<8XqK_rN%`*Rb$qjVN8;!usl-HQ2+V-%EC1 z^2V=Ax-~hNPq)|Re_os`y*Idfyv|**7hb~AFhls5g_`(L`zv$mCPe;mX|MlTtzOV+q-P=wl(oX&sU66% zvAgunb1Xo8vT9WyyuW`+<4Nqmkk(Ijq;2KU@Oy3zT&1*PaRx{qKU;$4&fV77Z+y8& zz}0RP@##gu&Ok1B;ZxHj<10R*;8J_ciX(B#8XJ5$eMH^_8IMfxR! zCRJ67x}?r7@4AW8GU(4gcM~!b-bIv^cK&--4aL|fTYW&RhB2JI*0y8WhuUP7BQ$eG}T1 z6F)?EljT#+GT+li0q1_NB0X8k`T&4ZQ$|Syy3Em%^w!o#eH)LWVq6BglU{cB z_Uq1^U(P5f!OYiJ>IvWv0kem&6^OBItl;RJ*H=u|sl&oS%U3~xSIkSyeRPj?Zw$$m>u=s~o)-@?uOdf(LtFT1^J>LuS|qPoVuh#J4joDB>ur#ir+ zQ8;O)tzXbGxT64om2_TI#jJE3K+(npgk84T)=l6wom+>^)YO@ zmq|q~A@QsV=_egs%KY!!g52bzly_CLp9=)ZWG86T9zA}_&>CAMkFu9I{2a#BtO`wqWfT0_@%*I$o=*vbMuZby1sSwup(I+t$0*-mFZoT3-)L&DX%(1 zU^sceMQzlP-mpHkr9qsL+b zmIfv#a;=X^zl@4og8^WCPsvR}{EpKnCF0){ZRF##rm21D`7O%#(oSuj@lZS<;8Q@;Kz@48=betIhU-^Ofm4q zgnqG>DS4B7n;GHu4U}GE@C;zx<`#Q|Bx__0#RAoa4mZI(vkIHG*Ly%RAqegXE=&8` zxU(PX=+^c^)feXIPwusx!p!~AE8dK)(g#(w5;r#VoiZo6LwEeg$LPa^Z|WfSN*vHw zVtq2s*d~j46*E$P^cX(+f&$o?`JUyY9285W?(K(orvhZ=s+6NwMumYcwZy{TrsvLDJA{4=Py|Owt1zElgNZ-2;}hx5H~Xdr_v_2 zg@kaebng8OLTR~q$76UtjdC=T9He~9fZG5#Lz)+}#OcLV%w(hEzosxM=Mkdw?FFI! z)RzmBUZPNoNM1%BSsO(bom)e#-&D_jjMl1I=~B7UsY4A?<&DmJvCE58&bSN-ru;bC z%w?lcpUfEo$hxl;As1Ny!$SzbP(Eo7U97XZ3zw!7tzozDbI|**5;%F9ijw~x7d`lR z0hnZ7^k`~1=zd*^Tm9mww_?D%TP+s9i38vbhPVE=mx*6 zPB3*_R=B$I$E<0&ZaS`=7XY4W*?Do@fC+na>P2;2nc~JKjg_6tP{P|K1F7QrpnxJ0 z>5!(TFVV*Yv^L1yA6Z`vtMiF&v0>zm#Z$;y7rzg1Jx!mGanP?!><~3bb9!{L6Ni-U z@C#}W7rS&TI^SL|F`=p2-91aKiG!vPVxW9d7Mba9vH-ZakeA+V*{(WD2eKo3`Xeq2 z(Q<0OVBv-iJf22=f zO`drCDy*RUAJ$!Q%p+5^rnnVCQKeAU%EbNd0J=higOVDw))zQS_u%Fg;ZFx-U&P#r zvVZct>4NXT2p)r`rRDV)AB9hbIu$HpJ*{otBFR!3^C@YP52-PYjW1_@JmVg~_Sw-q zqwOtb5*g0SGxM0GmK<(gGCy|$hWmLj8NU5oG&(dz=Gssn7W8BPgeb6g(UpKSmu0_= zl%d{!q-W^ul0|H#jcLxRVxTtK{s)%EZrM2LtPJfzjayEe-`+E4OBYr};0xt`* z0S%(mL^F=C08k}DIcIFxbHn{Cfnq1=Wmy)H7weCe^~D&2?7rLU5~Iy>_9S?HkK;)#^UqeFtLmi`B5v zn|XOJ_MG%knU&&!j(KXPWhmNDi3wqL2pZ{TJtFApyb@p^-y1X?;o~YA`3-bDHPxkG^PbvR zIy}ci)8Cx(u$Q-N{7@iJ8cw{J$hsL#Vr+s<+4-4oa4gh^+^f-iZb#$)g2$w2NyYch|DAa=)Yy* z;GRGFljFa#D8!*y7!%Q}<8vp<1Nc7)FG_^xY)*=ibX11Duv@!#l6gO@2LhUadw@d+ z@tAPqBW&{cQT#{4uV?3YUH4urKrg`ZoZXTOJeLMIB_&>On%72tJ4z4D`QW{gn6s84 zR6TI89uyFot@%~LIE_tOn(4*j6VB(J@GX?d4Gc?8tG1{6WgF&J9W8*W&nC);(g|p zXn<|p()6qm(YxF}@!zY*&=-Ci6iMeht*(tQ){KO2)M+I=&S2G1(VClcCT>tO!K+cZ z`8C?Ovi_N7-YOCIc*OP{J1_O}c^F{Fx$J3hc%P~IDY~z>n!GPud9_~SW#91Oh*3NM z)5?8qN`f-I=GWAVzT~Xy*RvwcC9Onlf<~SSY9Bg3rUD&UC^Ak`bISeN9A0dwheRYw ziMQkjpzr1Yz#RUoi1XW+D2jOg>9G{TEDa>^e;+yoV*l`;HT~HdB<7QXe?L8u%Py$H z00XGwf-^#Znok4jnX%j?mh8Xv79H0~k`H(;ehG%E&^q8?N5z%=nm&KAHS2pl7xBG~ zXXYeI!3ck27)N{L(ULgFaPnJd665E2DudhJFN{@O9)bNVGmX_SSuU}FM?ud=o=)aH zNM8c#QeQ&+*W)Xl85!9pBBlno@kxMQ;RsrJ5tKRVnZ}Kjl(5+s$}7Dn)0~!k>#TCP z>F?`r#Bou&e&NVDn~Z`^RNw%I$77Es72!+rKgQS*gT3bsnCcO3K%R)yqXR z54k0m-tmYj6?H@UO}zt9Le###)5Ls5W#Z$jbtmoIC~^#oXF`JxFWxwZM%RL}xK!cb z875vFmYLSuxJAABEjOTz0AE*E|34Bg${kPu7|4r)@6X+7SV7q*6F4@p!KfRyKX%TK z@Rg-@I@BAsI?7iq)@Ms~G_N_|&366nx{p;#Yc+U|0&nJ7$7TM!Qi2MJlNY}kdP0Xr9 zvaR;tgftnTBwo}f75-eH&SjS#%1aI?2a)8LKOKJsoIIk;ZB_B2hQ%|zyHxj-<$rHG z202gtPncCUwY^J)LxAp~@g;ida+>ev76AYZ4iodkIL%jXZk)ja03}Zy7J40*_iDEH zaH61vl<4SKcZEX(9tUwMvAInpkFLraNtA|>+_JF`4O|;SxKx5FaQ>{#pW-(_Z<6aD ze$o{9A2@fTLJeoNl@6R1Pn= z2vG+obMY?d z47!$X2ONbZ>WsQav#ixiA%rWgSRkw%sX_?EW1ZP5FUI1lr76V-s;vgGGA1cg>z-Zi zz1?2YdF|E=l^dpf56x3hDo3RCFumGI6Qmx58ry#@U*&D?Qgel|Rd@6vy;ezDB4Vug zv3~3|__Q1cLhyOF>d?H6>)@M6n{@>MQI^v&*xz2;b{Zls~TlPYPz;ImeY?t28hxMkRvB#$_G*v+Ns*Yg$whj^_mAilT@m;%bg z#m?(<-cw<#%1NnqR2T?ItN~R%lTv;aZK$vt2KUrcK7rivdf1X~VJC#c$4ufh4-ZV4 z;}(a&khqSF0mgm83E!1Rw1+%S?_hQxel~1p0&osM?})GZxU0lHqf%b~cqIE}#u5nn zW8eno0D1{vV}F1G{(e1vEi_2+i%$=|w>4_QTBHUzhAdNuDD~3KsrfxMy+s{UtVJYT zTYKnP(N98?V*u-M*;+C-v`U%E@s9L_LyPhDmCqVR4$y|@2{d}!O;(hmjQADRJS_Mm zj$c4`Xh~%BkmZyj=Nx&d#7o$}g>?pQsO-jF;!LltlQG64t+h-vN z4WlP^hL0|@H|v`4@+Zq=rh+?Z>+cude$Z2EHiXof?C*U%2M-0P5@tig zMdn@yvG&OMIx}S`Yh|T#PaJJB{9OHIhFdyi$^Xc;5>>HY>!|>H>)X_&z-2w?b(nk& zxmAPIK}T03Wxi$MZCpPc+TCCSpj+~6xL%E9@A0v^8nf-l`8GgRxlfEQP2c>zZuixd z0SE@MqaGt?zkxTW$8Yo+5>=zTh)r|6=_RW}pDtR?d`g$p^OrB?)967DI-kU~>`ZU$ ziRY18L!+$HTmuz;#I(=JgPFCy2n}H?!0_b7cE@9&ML9c!fqd%}br}<==jl{ME~s`h zjLJ!7KOId;3hKtj9?){RdxcuIw0$4c-L2d$<>g~AoERVZEi4)5X({%`J{{N8nx zzTB4d@xYO`J)b|2Zis!8|80s8-Sb^xUGG>7P?SktIe_vKIYYga9GfY!YFKgJ)Kps| zz&@vexZvX?c1O-TXmnH)sD*(2HH+>)yK2nLO0~%;tG7PDTD3 z$^RTXx2_V1E4Sh!kytknS3@< z^G#yRCDqAJOH`a0cPHkPV=*<@g}w>tcace90~|#iCtoFrNE}%OMUszmPHh{~AwT^X z6X@d$n#OJpP~%=akbZ7`Om=WW8n{^D#b=LL!K&}afI#9mI?7ukN`L=lS^bLJ*aTa@ zQy5e!WP3V;nr^{Re=J9R$NzG)}f8dLi^~)?r#?dWda@@S?6Y{GfCSt;{gotLho9WJ&ybqlxiBc9w)kC3})>d9kpo z@(DFv|LT65?F?4l%M)#iJ&?E(K)fU;VzKF%2;nT>DN@D#K+Sm5FH9pW>CGeL*pbPE z#1~rLdE1g{=8s4K;Fs|l3o83y91v?eN*s9z0-4h9$F6i|Mht8)*m%iIirjgoSOqN$5 z=)PFTMjlNkGB$ui5(cZ`p!{uOHJ4B{Z6Fg*f4{@~dXuz=j49}eNa`>ht!n1buEC8D zyh^>hFI%6H)_It`jxg-nF|)KTjvA6&bv53c?mLQ@ zp-BvKqaD^mcQlV6o((ljd<&FLT>_Xswp%cG&BU&aQvC3Q+(?8=Q^Kzzrb76(pH5j3 zzBk5E_^4@q;@fD_&VOct!BQw~{UUevJCOHOyiX?#NIK2if+v?!3 zy!%|}giq+x(+p#wV|Y&He!cMU{yIGXoOA5Xoz~&kD5LW`0kX@Ynr+oB8zj1GNv%P8 zrRip%{L>TOq#wcX#XY2uf8ME|zM;sl9qn|g1Tq5TY%%dJja#rny?sJ^Q0{OABgnLt znXijBj51v^8};?Wzv{0BlJDj%UJojFKbaiUEI+?`}o{g#N zVTWqsn<2+9L)Gy>s3DH}`pAxvd`KBv_honi*42M-JEU*qoy-E~y}WAh0NuK(I|1ub zQj(I8>o#*t&nQX?b!Ehom#3gG=W~R{Z~K76{o07^J{6_t9wqR=rkK7E3c{4+|!1@Fds8<^%%S<2b^|?4eam>Aucp_vZ zwWM=^NkQZbp)o_UJGWL*%+S-uZ66I()h&Y=4(?|0Z~g4O%+T3+wtxXjAp*_GD?S+? z)|1pnD8%YqsH1LIZ|Qcmp!VVOXMmZDfjAB727CJ6q~+@cfNcg%_e{Uo)Ofv?wuO6QFDr5q445M2aRU|Wx{Lu-={X&cHD{o6bh3#~#ktUqx zi{_>hNz-bME`Xkd?kHMYBb^GfGHyQDQwy{b}E0K=^8 zOkWKBZtIxJIs~q7!!|Q5KUhKD7NkVex!U=?+>+%-4VQoltt+vG^l_fa71zv9SmjL1 zZn6qaolv1uw3J+mB6GqzCN6PlRN6=yD3Y2I0qiutY76`(c;6v=!bkZj{|5!l-)Znkj2F6a;PNR0?v=Ycd2&tpzUkC*_-@Z2JAuem! z@bGQFN=VFVZ@HXe5f3lk*fK~hDtAxtwuio%k{nx3_{|@FPF-hHY$@k-9|vumLFLkM?K$fyyW)I0!yL7(P)m zm9nO(>$@7Tv$zC9qeM3lj8m6*MkMQYRDVVUs{u2ol$C=|3p&(U(L1W4hM5#D$Y69o zXWrJ;2w%+sg739eKSF#6d3)Y-7!W1}QJIK=f--roiQGFO&nANKhtWVlhj~~CBKu;C z0Eqq!Clka0Ozjfsb;4bpiMD8erWXF1_^$BM-~<#aT$VapGu`3*eZCmfd|^SW+4M#$~K0i=L`< zE31OsOW0n;V|u+foVj|*vFZJzCND(sQ|mz+^{l*$tcudJ{YKf6^QGF+qDSeQvyHcM zmJm8{43TQ8QoMe^_M%E zjZ{xeKgH?48NK)5Lg<2)?BEEVlK`b~Pr!jF(yE$LTg_6_0CaGnLLknF9SHXXYAwrG z)uUW{2!-`|dSKmXXldK$*Dr~WmNkA9~{G+B%YBFzj zo;zh!=IS19K1zCn(_Vp$M?1jI?*W*5DMma&EEood2E*j~UtC^HxyCbIE}w4JfH3cA z7z2e{X_LR%_$r<2Ow5lUcIFK_z{4^kEKI%y#=7vhfU3c`O;^ncItDBpTi;+!<>dH= zXl`g;>`7jJFH>{WI)%E?xz^F;L5PB-YaI-_b@Ix_3E3QnxPBZ3G~$RdK9v?5|6g2Vfr! zQOroHlK-Ky-O?u`P;iLiKX?Z}Kd2n(I%A;k9OVa}~t^-W;06ws}t|w)vg+jT4K4y4;wO4T*Ex&w2TsPf)d5EvR+VbNM8LsCT z?^VwjT&kixTRfB#IO6{9V)jd`U{uIT?ap9tzbDoKK>c;z70R0)hiAqd<%r@l%^OX+dGdr#MkkzEoymj(C>LlIQW?L$AxZ_oEz6yPtx`U-kIRRFFeQpN5K&Mu zeOx6FAVvVwCO~h}xuc!&val$5wpQ4{*|?hiGu@Z@OqO8WUE?6%aI-(M?>A3x5}4aO zPd&EYXh2cXh~Ly)@|62gg)X>sLBV4%65EGvx`&RU9jrDA}9rT`dN2a2}Z z_T@6b8Yr=?GW`89NlLy>`p&j|?BYkD#?aK=NFjQ0QH!yRow%$LpuPjz#(Q}uJbob` zH#$kX4AhbH>pd&V>~ouH->G~Olcs%K{!q6naZ}Wf5c(Tv@`2E4%V6Igvf2%K&9AVZ zEj~a?CcL_yfzx_LuP77S0K}(Ru_1T!4?g%zz3fNWBJ2UO8;A{n8lagXC~2#&F;v_e zf2to#k^csS+DF9<`$xdeB;*(2{5Hc^C07%YrVW8+gTfb(vEj>gK}mh@J&N%3=r%6k zX#mj=ge|mNm^O_Ds9pzx{UaWzrxEUEJ<+PhO!W#=#U2GrxK9s zD-O3)ZwMlxf--m0Zd!*Eq?mYXP>RJ!j9Npf;h{&$x&G08y?_}6N=;|X#~A(ChxT8= zg?m&%6EXrnPC(|9VoI)$@3kXj{3`ecbESUneu*Z1H4Uigf8hi2vd^VJa)o0AwB6M& zTK=WJImh_NXwaCF?Um6%nG}+!Z`qBB_n@#vh(fINeNmu=N)Cv0QpSH|NOyH!l*D@j z9eUymJ#UwsAC%IU(My98DEN0C-v9!4IgU||DHe;wG1%VIm83r^=|T64WpP9aKs+P*(vS3}GeK)5M_&Z?|qH4O|7PP^SSh%nkXI z6OBNZu|g(zkMG7M`{tC$4$kaGgNcF~f~_QUHSY7tPzAv4t&o~%O;dWg188p}eX`q~ zQEn4Mg?k4q&j*3ZAM|2XVg`Zt_^Z63kcan2c+2l6s#N@K{{jGf znUw*iwNMj|%@QJiQ~Ju$NuxHOLfRP9iUx%^P(b`D#5b@YyJ4aO-1|XD%7w8Pf#B#n z5M^`kyVo^U3{`5XFaDUs0w_xE&}v4*NplM583!SpsU9{}SZ$QD5__v;(vRdZXtVY& zl%pat@7M51lv8s&H$Yo~6t~EQ4hTR&*<+P*Ne)Dsf%@F}t{qU)>bF-dc)UG$@eS(* zlo#zKjTKb73K(%>e#PN+;cYrSXa44d{&dq#2Yy-6>p<^y4c|AwbR0)V=i-LPJeaA# z5MJFuUSXW87W>1T&yW2Bq8wta5XTYqJcfc5Kd7kb`bEIfp3K@98UQ1y%b?uGI=GE5 zigL{U*`2^tDK3s8ii$5Suuv1E0%<;ei+DLvt5|Oy5LThe*K#tY+F2p|LmSG57p2#MHtcW=Pz%llf!;;UeUUS#U|EMC*e*xMwyrj-O zdlrbta|*^3L7&39IoOB#rT(ta{ID%rW<;MI?cEFzc$r)vxd1H6gh>t(h@>YZr|u;fY;gIPyGkeFF#h*0F#)Y56Q>vc|V%iY)4o$2-MNd zMAjzzS1kN!*IifOPnw1Pd~C$T3kwC6O4!dIC#-iiafId8qetB5)4*{lo8S_Lpcq_0 z_&cg?xhfQ~`&Vgiz4L%jvtA|+3ra?`Ts5L_Jtbk2GUTlQz9u-$d(iVymZwnRy-hG} zKvjJMYuEK5@u_j3k{c34DFG#U%l^vYur7Yq8x5jcNUfa0H>ZyiThH-m8lM(y}oT8 z^Q$N@bplGPA2;*;Ih-kTTyx(Ht7J#N7KJxBW!8tRUbnV1cxPG2>)c+)7Br)}$_>-A zRqFA0hiUG~==)M@p(;=PAyAi6H);p_`qH>!K2p$UYoN>})mCB;-bwr(0RtKV(4%F9 zZEsy357H{wb|SMIGx$z6^I4^wyw5u3%<%m2{djJ~D7HAZ-m}IfHgEl2;u}U}j9~DL zbCrxg;9V*ui>5U#1Kmk)#Q;y2hu>-5e`D7IP)**i3RLfbrbjnp(cdMfZ)WpYxr@_t zljM=GO-iTH-_4i||AU=+%-=I>tf$uKBn6H`)^W6`1Nt!lgp7>BTZg}%%zDcmR6bp} z;Fd#?aYS@+dAh&8#$%np_co^KW;mi&G7A9ne*QZ{{$WaluF%~6ZlK%L>oIDty3>YB z59=vr?CLhTuA38-saWjEyq;8RN|6V2FwMHIjj;)2xKr(jRS=^Hg_N}f*%jIoo(Ius82@Ego52~=X6tDrS?kdQY5=)G^M;jCkjT+sBt|pLh8f2 z{31G-V9;{INC)Bas;(fWb-lhF%<&RHkyzEiNb6V0ZzDv@v@yjcE+&}c;T*`<@gU{#WNbaM3)N=!#wG>6$WuXQ>9Wc;2xpI5tNTOk@sDx=LVpx!X{^FZHCuU#0CvE8 zhL@6#G)@3OBnT9ZhNiK$@}UO^o5u$GuVvNv$b*TKB15NImmcMt>)Uc*Qaz`C`izdC zu5p-0PQPJ@ruN2_@5YMzp`iyrsYr1SzMhSRJJyvT3`EF<{Ac%*{|RUmRr3GgmHSIl z_`iRl^!8VQ^S^#^{}iPK`QNV>fA*)pe{Fa3|NL+NJP`T!ryI0@{_xiy{`$l375KmE53oSNW(b6#igHE( zxTOE9*YfxO|6TvTz2)z~@Yf&y`osT!{o!4x>@UGK^Q@=*6ZH3A6kH=WWjyBh>+k!& z>+#zffX4Z+ef;&0KMdlpJ^YOif0)DH`0zJA{*8}+IKi&{z+@iYsF~ZEWmc%?~N~*|I+TmxB@v8*~lmQ|cuA%2xxxaBT zy759$j0`DWqJ4dx@tN)?ZCk&hP!AXV`?e!#)i}Xc_@zwK%e|{rz{ePx7<^1`* zQhIU9AL6M0!Se_et<1%=)zQ}G{+oItDzL!EA3x!KGvWWf1cBP!XsZA3_18E5d-)iP z|Ha|I8S%e3{4WmwD~A8(!2ja#zc~D_GyK0C_+K&nuNeMU4F5kU29?BfV3qCZA9&W` zlki4ZYTi(2Cy7k>k!}@p>)9W)N-E69UHF0fhroNg4%4534~y|u6*1}h9HQ9&tJ>_2 z>%)e4wP;84-A#cZL`666QgQzK4g1VzAdqo(%m~z+(FrP@F3g+oXOt+&>(Cz3w?UgL zYfcDACg3L$Ulh1Ue#LJcSp>{%I4Uvq9b;ot^2Oz4R7!{iClLt5NldX=&u=UAw>w1grbdv_Cm_&;D`k-X1{ERh725WmAt-H-jT1nbUtEkIt9#+pvr zLUx=NTyK&B$a#BaaBtY)~DOn!h6MOu?3guWm&5r$5sM}850_-+g5VmU_(#`8Z4E+-@kwrmN+=2p{ zrOS9G!+C02*Bus-CobW6N2f>>^6&q|AE3 z^1)Qz(^6-0Y9s3oVrvNGSXPC>mUmo`sL<|E$@FHUMx8ll0=QiGdGMkcZu|Ds%!bie zN1y%em@+IdE3aEQI`!p2NzKg%kD~t^rsq4PT{6^YYD)^y+~?YJ%CJIdDKQVvYdMAc z){Z~~pPP!=7F0+nM|(HCmGJc0D)6%oT6-(TPfI(G`57XV`vFYh-0-K2oM%(2qGcA3 z7ke;V>7eHssGAGe8(xEUSICNoar6FS!%ylB_sxY`us|#6vSPSH1I5C%IMsR5$?z6e zg;6%)xwGI=o~^~L}f7ZMwfpyvnbEnl53j#U!d#GY>r3_T_Yh(kKL?-}SH_Gjf9L`Nzo+HIR zznX1!=Hsz_6^*8j>~ZF`i40Lgnh7(5_DKZxt}m`UoAx~59ZYr5AY~gMD{JTu>{mwP z>TTVmuo7KcpK+=%cPW@}wNXcVVI}OQJGDqz_D6|zQg;RiYjY)I2&Ti=2k@<%p5o!- zA6#YhZlzs%($UVJbSm}|WijbRUN3%qzbQ2qw}Kz!z@&+JLsg)+!pnOPTifbVXyCE^ zJ(#~jl~*H-ce+>CJt^wzG>t80TS3Ee&#MKA3d`r z#~%j?nSOOf3Z3~z=6j=iUU=5KvM{>j=_9Vn(9rK}`=MslD+GFit4)X&IoOXJ$1$d>!^%Y75+%o^z0Z%}z1vwP;Vn_PM@MNeIE>1AWtK{He9d!%PYxjkH@ z%-&-G6|v;L5~;jERk&&lYX6STrvIaUr<4uRnO@T85t)1qtD_DDQoD)@)z5xc3+%zy z?|C1iIK@BqBtJJ`v$h)v_I60MJDUtIcD?9(2Lp?^8#>8a7x#LAI28wr)7_|lky-LY zS9jT>F}r?|5TU*Inf_pJKU0<&WA_7^Cc}=^ooDvInf74^H;WnvL|W4k_l!h0;T-Ry z^)0e&8oH{$h4Xucs$}S9D{ruWBQ(Xgjb7xqPY|}J-VpNA&)fB(zx8s7Quwhf-{tX2 zc&=Ti2M_*iDf~mF09Gh4?mvqe}j3`_u<1X*z)g>zUo`-(`k-~Q! zb1nyV+Av7$O!iPMhr^qmH!;^PLv?0)o+;au&3fSDUup9XfA{3H*-ob{l9*>{J0swG)6hca zXw9d8E6H|G|I>VWSa8BRi6<|h#dW$qj@ow-H6NA;W*>+!8ZLJwAQ0eEYSxg)zP#+c zVXdk~4Z0vfo3sska2=hgq%sn{`LfdNHqr0MQoHQPct>+@GwrKx)zUNnew>2CEhytmXG{T-dz4RHvQS+Jo)KnsuFyq!KZ*?NIQJK@SG%x_KWg zO>Qq6YsRXqC8pt^a%yq_45{_%*nJ%CuItxjL!e(clGLkOBItGAE4Xh7d%LL80Z>Ge zCM?*Bj8#PxrSPaaQ-es4Os9~h!X1IrdWDdI8TO)CkJyvX_L9gEV5tN<#pIz#nFm$v z=IhkLLsXCuf5tPs7H>MllBF8dwd@VveqXw0Ct3o(ayxAA=rQ4P_Z$HiKu&)(1@ZbxIks3Jc@{ zk6}a>v=*erz%YHW!;P<8-uib*HcHRbpljowgjn z?E#uV$*f0HY=lE|#i=VIT6Ltb&j-|=^@7chvD#49xA_dV(gkj{wNE{*J}mADEAp-2 zS$5p8=HgTt^dJO<{>w1*x+^3?EYGkNU+dCSqoOhI7Xu8#t!)RO5VKLA$yq!zp=@_c zh$AgXq@@RL^g&K=cxlUs6h66xCd}J%I6AMkG_)`1Uom62;W})*#!Re2yFuAo-a_Zq zP{Ysgk~&5Jk|TlU6Fd-Zy>stdN_3TRe6$(~Wg}}ag3nXj zad5l%0I?3@)Md4r$78!%Q!KIXS&ekt`OFcHEaPW6d{t zY-yI(L)hjAB0a|u&(e~sG?3rulds1UdSwvjlwj_;8;Ldza!X#*hjmO)S}$AMiqg5T zlqlxkAGxx93~t-W%+(-2Mu+{k%SqJiB(M|b0oV^TJ&HP9W8ZVza3FJ2&e8Gl5kH;t zzW5T!-EJ2a`9wZwOkmWk5Pt8U+gudmiUJhLBlCRrn~yM@OdL%+ca7{VahD9`2l{ zW^$0L&E=qYqtMEwSN#7X=k(B7!;!^nMHL<;JSTGX#BXV5PN1(wyB4P zb1@#1Y7S7ONzaF}=;)4R=mPJ>NHj0_Hg#6Xs&HIo%3gG!6S3bnP(?*|Z+|CQ;gem$ zY-!8!q3dHqDYNC#a5p8}hyMmJ%;QGfqIE05TF|1E5wstbK{*As>6oJVNN+uxD%;!a z6YEC?qT1V+L>^ATZTHhDZM`n}$MpI)najPWVpzIEOmA6ZC#YPU7gi%LFA}nf8hdho zP8XIwi182y5rbl$Wju>{6ET`u*LLCgqVEmMHMySmC$8j1 zJ)zX5pz@-;T4BO>yW^$1OWIapb!9%L3^PiR)BmDUV3`HHCc@&kdzHwf|+~5@Nq=DMy9z_Ugr#9sim3jGlSDh%Nmfpl2NMES_FT6IphiKr+ZKlxC za4EW$Szg8cD)iD0S)-Ufz*DbXkwqs`w-cDWe_plxOcngWNSzmVFp>?rNp^@1x($2O z1l{GCKzPb+Z|zKmN}qeVEq%P58JU?h<^Yj$Y);xn0W?O&V;^iI#04~KohARmbwJ)2 zN;=lIp~caWQ0q3aK9>$k-mkOC{%~)(VDMp%g%&oD5?wN<`yccKf%LI}1`t18<;*AY zP;w@?CIL5kXcUUIL`TtQZTbrz&L-JBB2C5Dqs+6-cAduV(vxcw+2ewtX_0h4Tu>@Z z2!kuuvXcWTdCx|o({0lMC;>{C;ZZ7b74P3k{>5lLSwe&3;-0BFL-uT!3Bk?N=EOkA zyBEJUm&1pJMQpOQL#1a@si3`6`i1>Bdpm8Bl2;irWq^_mU z?V*h(s!OP#S>X&odq*0`Rf7r*^z%u}ZdRiz%m?gLr}Zjw!OJdCHbv%}SIUNVcqld1t>%tr+!xX>zwI~rgg{pWdN@)i8CEp7EXO!nusL8{-H2=R}! zyj@tScZ>V4K_8PFi_t)S6`KGo!%8>=-{NR-GCdCtx9>bifuD@ri%eV1o?_B~;?-Vi zwkIj+B|>J>csX=$2l=_GiuifXu%O7&Z$#y(Ph56>Lui%ygDw*w|hiAUpy^0 zbg2N5_*VDye&x%^^sX2MsLAng=NPWQZx0ars+o8q@!*Z2;U|YydbKb7SYwO>`oEpqsCYEv$4&5`QSn+$Xb6hY7`)|Ym zP+}K~WxU$#T@ur2#4B?iV$X6>LE-~bG$1_ucTLGK!E_;n;!kMlyk>RSM;@R?jXHOv zn_z__X(#!;hUz6laHMO{jrs)?bH&BmYpVzM=v0*&s>I)V5fB3V5#h^L39>khakoYU zjHKTF=NoAwT;kOmAz4MGwsnvzwUIGIQ7fv&dqoq<`FbW@;q%Snp3o5+O)?f2Cu3o8 zF|o)vOa!l`d_%OxTpNO&Dh0GO;oSs^@JQ zkXXb2b`ZA05pW4D+$h6tMkf#m0@S>|sOR$UD%jEe$@X`v**hBfl-hbDir(PSCzZ-T zVX!Q_8>c=*@_Tyi-=8#5j>bv--?IQ6CupAVDC$NghPtVqN}$lzjRcH5%!~$;rV0P! z6qo=`0cA9r+Bvk$W}cLHahae~(B&Z)|6@(_#qAZMRXETN|7K+5dv{w2G% zH8s-gu|yWsg$0BA;ivRBB(958J@3stqcoXlMXE0%Ntqx+mg?8i*ofbuUTh4>hau%2Hs~JQ0dOp;Ws8KAfcZVbhhE9m z9yRV>!~W>Zmri|;ufU5WVfx1jd7=xm@QJI!Pa1OmwxZI;SS zcjYb`UA5z}dL{x?x95?1UD=|wj6KB*W5nr;c1pSLKp=vM z(IG0 zW}%NaGwNHTL^KRUN0k3r; zPB#g)GPBBW*V3xDXTuiEJ?z_^>V55#9``&yO`9DS#i5Hw(zZF;g0n_TdyN)R(c+tp z5sTu>bx_Au=cAST&I%x0M0;{WPR~L5h5(H$*JB}cut$6e=}ytDJW97BC1vieJrHE( zBl_5=q-c&Z^&T*xMQ$>T0LQSUNzF?Ahm7CucXReGaI>eP(COr%x31BWI2VOVr$H1s zOjX$yV6K;w!30KkU$y=dofsfGchi%7*a!}4?U#(~R7)*+rPwHyD$JN{e>LU!JS@Df z$LYuBxEgPoTf)#3+#hY75#P&MJ}2Fq{Av8oPa7L_u<^rm2^#f&r)a<=fTajWaQ{I8 zCDjKKgZ2}ng&m~4t^=eE#m(UPGr*Rh$u^?cMB#Hzz= z1og(JWYkS9odx>a8rcH~u<(P8>r3$wmeYyAaZEJ9(Z|?-q#$ z%hIbC+^f)U+uX&=PX)YpX#A0gKx1z7eOHlA825wK+USA*{R3HUqQA|HF%lwfZ%#k$8GT*UVpsLRmeQTZUO;G*A*5?LHyCr~5AXC~tRtfpQ zsZxBI43`y2jKCZbe!YA;|2eB;VHs-5T<3 zBBikQLSqKtVW;ULjJoHysMI9Szlgn`++e9yXD6w6bXN}Z3o5op`?xGUlx1wnAdRBz zwMdAV?aJ5UB|cJLx4*oAykYb4T-daCHa=Ugy?(^hEilAU(@4%$y1H)qi?kyR&>0|$ zU|~*;NJ_e#*=nG>TEB`uPYHqjQ}wn7{6&rXRhJpeC?#bhnnw#8Fr||wYfshJa)U)9 z2?xf&d@sH4pc+*MuRUsW?vAwc7r{^D^M#^Un%LGI?T`Jf?awk|;j?rChQPE#5vbT} zEgmS?%iSF-x{6nrjQqsD*Z;tNAD_~`zv2&N2kvj($Ewe7O``^$G3hyg|qiduGO5_`Env;T|jBw`Kp1aU8;gn$8`p)U8)k zzhKoGK8nv1(h^TBpGCamrx<@2r0tj_jVY8+6DNIXB$|P(N~2vSnk4ruN68PmD;6^6 zU&;JVF2QwmwSst(_iD?TBj!z4u;En6ToM;e^c+Q>J)zrvxDwNAdfl7755;=nREoiP zfje^Eht3&N-```@Yv&!_sik0^5AjU$Xeg+9?h2?Wj7R^%AW+rcqw6426C!O>JT%d7 zVj^0p#)=$>U$@oP!A#&w( zGUg$21|hokyJ-uXlkM!xW80INV;P_0g|VO)UkT?T`3$0hb&PL+$)VE(I*Eo62jX>T zNHr6ybA0WgcT{d#dMh-v)UGRkCP0)M8QDE)Uy&3?9u+6XMo2}q#9GE>)EO;Me3d~F z5`AMf`jG}*LxA_0D;xDwqo)greU6M!I)2@VaI$w3?zfVfnK z_dQ47uuBCLkz~Vv>_~nMbM+;tt{n@P_j%h>L`~dbjA-+-j-z=>;F!f_Zv37B5-G0v z3mBMv!GFtY+0%M!YPGBdk!{)=TNDo?(Fx3sfb6#NAeX)HV*>m=-xCTMA1 zmsP(Qm>CY7a4p=}9Sw)V`jg3lZ5gUrT6w(YYkC5v_$R?8uQ+Y$@!`Q=3}m7aGfy*z zpPyq&e2af^;A*4F<9lA_6H2Y^J@Zg5r?ozBMu;^UdxSq^cQv@$D zEqxbJ6_Z!0853QzV1c^pI!(eQj$N9R9?Zi2^>f_6mWgbCsu)`_HCU){ z#>~?-sYH%KX!^&JyX>XAI_1R%FY@=u*zd}Bbmd-(-L~_?P7>kB-0faG8A|d9bGRXw ziv}SqOSma7f>uFcJov$;1j-1G%gW}q`!#jvubIvxAm++v1%j|z8o8gmIck@wury3JSmv*uIRk4Z{5K;@yYRt1w|Y9y%>;@U%zbgo@#lV0X5D{_YLBFlse=*TyjHZ z2Nf1<7-k~U$$#lMEY+U*t&bE;+kY^0_n17wMY!%lD?1KDk4e0)IHn-2VX``kAa1_Y zMVUUzkF}D~!=^TFFVw064#|HZm68FibwN8|$vrCHw(_5a5y5O(e#PJV%z(bxmKTaF zcEj}=tjT|V><}0(T`wl6B-;&7fjvLyX~#XU)BYV6VV3t=?BLF?{&B=yOG9)E_xcZf0V@J@jQEY$MvSZ7V1#!^LTQz)#PnTi; z_V;Z1>$KVN_(B0p7b>f+Rv>9oRsx^Bi>Req?lzdJw6k)YU_plF!V_|!T8h;byTt& zsX;YxdiUZZMvf|jS4}GhU!S!{$Yf9bxsGVL*_naBY9JA$ zC6RypU#-=5r3Kd86pl+4Gz>-8XjvYoQ?rzxDj1ETv1DP<)Z2NyBp#CM9!0^o z@m(SC75q^r!gk>%QX}Pmn#Zsjezns}X&A%$LYmM&-F0d$$QARJM{y}#hKeXEo~4rO zb-dnjQNdKSEsx6DYK7?}?}EOWg6vCBc)x6$^kDo#FU?Pl_bksG^B7)pr{0Aj8^u{# z7gVAiZZ$r&;eL9ft{&x^TjIZ1^F-I0G$e7ad!QMEr-P73o6wz9oeY=u+rhUEho4iS zrxB(4)!aMA7G&kUF_5Zr`t3Y(7`Iss9mS2z3qF0hc6>|LXsxU<*nU&IOTbPirX8Eh0$B+3#ZYuX)p=pjGLiEUy@#a&U-9j!w)>_~&JVDx55FGLhTF_B zPcYU?mPb=Azhjp+a#BW^=GnaNhK91=an5 zND+>IZEYM95_mPbiUm(o-?8IFn9>_vU)JjusXJ}Vhq!pgp;O`Kc7MQ}u%BzLwprkl z`b6kI;#=5Ws18w>s$e(H4O)vXsMhX&VUn zeffEXt~}dJW)#BoY$lF9&dp?e6dfm(Tro5!xRbP`D8`c?^Cb+<*|CH-va z(dc$cpj{#kER~OES*|orz4;UQn$0-71H4)hkF6EXpOgClC^up#MAh@+wJ)`*|NCBQ$!F zvy2p8T4_2b`!rCy@ae0Uvia|CK7hf$dj|p&9iuQ70yN zFY(N1nXI4EJWN2y368huqDuUDz-47j7_)(xIZExoZuwl5gf`{notideTo>mO z!xI!U+&CQ<=!l$QSlsLw}YoYRi5;%F}(Gy^FX6 zNNy52+g$VEcn~vUFg@5nq0LU{9FjFCuOv4Z)g3;7rr#0zz3oLl!tP>Lg8`01iRVA3 z4CC4=e%dGZ;hXU6n0*7rjoK+uJwyo$)WkNgWt*uby^R^mq=KXzs>f1AX0_Dnw zc2*-QE**4;(!AlMg?mf;&bwQY!FY>KlD^tLpOUTOKfA@A2v|lc7(HSF`S*_ib^M8M zK}sigr#x`A^-W{bXDS{@cCXuxr=@JKg%A_9nr*BH)Bqj~C1ST%2JQT+B|KG?Q+q0+ zElj0no8O^aMtQz-ovngizuV!Y-NO0jThnXb57w+HVwgd%^;KNnBn(RayP9}O-@+5u zt3g!qNC1mSj4x$>K!10fGcS64VJNMCjqU6G@KofoFiz_WfnMOAYLWmC@jJ$D10X3$ z-&m=t9CUk5T&^j)-6mKWn;e6Os7Z4EdCEhe{pu%(f9g3czMo@~h54y?wYgvC7hyS@ z%+G2Zh7mU^(3k4XQxDv}`3I8$C?i#)0eb1TB>yQ}>Yl_s=DU-tuv=Y^ub4KWb8JZN z^3oPCkBf0{3syR`Xn~6Z#+N{P5<^C-WBG?0ELE+5$<7)j6u6h=N~5`<_kvhh5rZA* zb1?-w0+LFBemv^vntw9zXr90d9>8LDpR&q7)79e@meW1O31n^*i33<)eT|omf>#27 zP^mCq`Q<=7SjbC5Q7#je_m2lRXJoi^`01!1tv`bKDartGF1&OD)dZK5z3naP7;uE= z`=3lxnt|GDKAj|O!@xnjB+2ntqPe`SQbm8_5JJl7DfPruKFsW8VCB4reD$bBoZCq> zg*G3ZIVfJoof1WfWzes+3YSNhb zLh(Pycb#*G&!E`!`{SB})Tt{mK<<-C7%#tY&eMm#Ewux$dh}HK`=kJ6_l*8toqzMT zAWWmd@NFjD-RTwsdi%4jH-_`|8bZgSRIOJH{YCbVbUnnDj25x`YH||6JlDDT68=frU^;+mWC2q(=pBKclOal7>U8ViBtmA@2Vz)eh3Lp|dU-3)T*Nz?p zm=*-qxgEZ~(e-wUTLHhT!sA#oz;b=OKs-w@E&uY3R8aGq9!o@rH(j~090t|>o&lsN z6~FaqsK)Pd9I{W#7E)@8L1q@iznrmKACW`Njb>9U^nP=vH@VWOUW!tAWJ3Em__jVuZ;(p$ zWL&d&c5PZpT)(fL<`5W)BDRMV|lCl{q@daLnyMDc4z6`DUrTER#REfBzVG1lSd@?$2>Uv}O423j>AjlkUWIw%4 zibaX{&-rszUN~{V3(e-6GY#W6rwiNBCNUbB6U>N7%1*m~{9(T$)itL5Q6*9om2E%i z#1aAi$WMG4(j=Lwl@}MTUJ3H>j87iWUB!(bv?|j*|Nbh( z2va%uk-fUp_a!6}Ma-2j;aVaSnr}s?>%*BS`QgbldrD$>YB4&iuN^O$aK6Xr;_m$& z_w0N3OEY=dQCiopZyW&9YZZGmPXG|X|g1oX^0 zKU*HljN^Vy%qNoiE&Sw&C$a-_fU0nGxnh7)vf3`@&9wO{+Q7w)=IJHU(@-9!!XQ=s zIxyz-e^Vslri?t&1arb9WyRF>-_#Ci$ZL?V#v(5A)&MV77Q5h4)kKrjtZ9YuVhb~| zP+LhcFWpp;cTBqN^>N7*@tx&1iAB`E#a{Mxp+FLxDYcoJ<%F!oONi6H8>)L$>D|@&|bWwi8UP2GxX^17tl=PN4!V%|nBk6!nWKqY0=4|ElS7!o(@_13W zQ&Gu4)W_gBUinCBrB%GjGZE;PHZ9Bqz(rRbJG6ZaSafgd(ZN=whg|+5-TD9GPbch_ ze%+4-eogOv4bPW{3>1oY47nb=l<3sZfUbm;03X_$zcJGB z^u@w1>5L6~fPTbIH={22CiZY6Lm-Ndz@gW~6Yb?79+69M_DQ+(B_{_qH?sTzi)8rg zFZ(Zt_)k~E797h3%U;w(EhCwPl$~3i1({I#s9q!{wp_{DcrO7Gp%Um5e$b1XM00@C zABhO7CGb3}!5;U1ZYCer7 zaJt<|_8;X&zkM*U2V;H3?hIGG(Z48H0b9fNPt6~6NNd#bG>R$(He7k8(XHdMA!W-o{yY%5fl|A4Ex2+B(1Zz}qNYU15&;fPZlj?mGeqI?s{F^AsK{Rp%2l3jhYv8Z1eP zFE728My)!lY^gf)9!l(rOeC~IP;I@G0?Ve=4X3R6llZxY^RAj+nxGGHNDchovjG2L zn|CAB9gJYLuOdEXObE@ng;y>+RF6M=|@bE=~LPZ#$3E>?nb@!Vic*Qs* z)tNO*!yET&wigsGN8ZEAfFGdiZv1ALj1oS<2RKDSch_9EcPZ*E1(zgxj@Pg)z##K)#CQV?kOr9#O45RJg@5=$45V@kRy&`cmv0s2cwq_yZV_CZn zzb|h%ikm*L>hTw^Yh_p81ZV=MmJfOM3?OYb39`8I(}he}PBF5XR2$Zt37c<^zo!3U z9aLkq@wEU`T}!9+{L{#j?$UZ->ZW%+{3tD$GI6pM34z{>LOMg%ad(7Wj91-D8PoTE>A#0Hoz;47%=py-Xe?b9<&wklCrQ-79!0kLs z)M{QC0t?4^UpuRyWA-lt&UQIdXHtKIE#q%;r7V)2Z9a#SQqWg(ubEW#3Wh;j(OJ8PH z@^h9_Ph(u&tMbvj4^9#VgvWzAo%Tz=d}O-8Z0wrLyKh0S?_Z8eMq)$T^pf!KB#HB| zcS)jC*vVfbx$Es3#co|KOBM%Wpu+)&EhFw7-_iet6!l!C8do^$p%O1P6Rp@fZ~*s- zHKD9uAEvy-%?e}(OyDx%&6}F!OK}#y7E9^Ild-1^FdXQ!(wCB1f8by{X{y(7R)R;&@ri8M)TmZ3qh@rmmUOryaK4 zFiV@wNUElvW>rSH9sRCApBcFMRR%~FTS#;VY>w#{AW zk81y{z#CebC}i5Jz0=e4;Ss#izeeXJEMlRSCT9yqITdvk^8 z?c=_DKMc{busgqNZPBV1!$+2i1j_s96Bw%%JS}c@>EyX_vs? zqP@|6Df(3}%hyl-cUU47C+lyyKgnG((e%=G`KnM@{vbKk45~0ohw|PEN)^ite zpGg1RqQVGZSNVKtUcOsZhUu|F6ms}AQEK}Gw%u*5Y@NfOWl2SP{eU4^5in73MB?;ZO$f6dyUhm@HC1EGONZi-GU@O)BS#?YFY%R~6 zB%aSWtmjKGU8S#!=fok#KkxV|{j6|6%DsHQ9S+QV+v;7a3|$VDwE`akd^@pAum?HA{JHC~h8n@bd@guZ4biM~{tJM3y|0@en_gSJ#@a6h<}k}X4v}yAT5+3`7|r8_ z65qn2^Ke&F+GNE=i_atzf%dd@MCqUGfqAjXD=i{&B}^|Slu(W$1=vDmpku2g!X)kc z6q%XzNkc6O42GSick4yI52Qfc&5)I8Wd@rpO} z8m|O7rsYIaifmPCXai$fe=q~Ie{r0IS<@-$&!wRby~uqj1%MZT@$vC{=!4B_P4$9( zW;W_G`h&Nu2Op)IC}}K$_KB#(6x$mqy*v=%plITnjGU$D9RgU=NS%QhWx`@B<(}(g zMt(D@Y>A78HG8_;z)gpZ>)Jxp)Zj^%U~Noc62I<=@|&RLEalES7V^wUp~bkn_IziQ6Fz_*JwI&?vg z%+*~twf|_Sj=TubtA{Hsko)!t*t+P8sLb2Ss>^s&>+iK|>3Rv=f3iyZ!U2l1_>yq> zzB*7+kRngH3zA|P^P8%>B<^;;q=v7(!nx1nRH;P{{pM7w=S@-d#5X{&O?&A@lV&~t zjP~`k$)Hxiek2`NYCN;u!f|a&$C;FWvNy+J4wzM~E^px&jI5ceOeT*3-BHE7Pm9gk z1yCsA_XP%klrWa=eJWQo>wXG`YHtxfU2X6THrniROYdPW;RfbDIREGodRd)JhI_5g zwS^diB>lbtbCYzu5MaD2x%{N4bSxaw%GAjVR`0ZOHn@BpAkQ|VQDj>Q)36r=MBCr; zYE*^@0?jC;X)|@e5ZVu8? z(J23hzV9GBA60|!HwWNkXVJYX+RN>2iPW{`%AxzV6ucgzmTw{_clFntum8X*mYQJd zz>V?X-8Rv9OON;BuP6@9;IBN(T$WhuQ9|hP>1s8X1ufKSGie)%ND9EPT>cLlIt1@} zVCw2A2Li*uE`Y8>+p$D`ueF%-@*l$!$bjKd1n{WEQi2WyGOfSNFA2=FD_JemdD&1P ztzJo%L1B0h$;9y(0zUONFN>E)4UVGA@8wb<5X9dCmnpM zgge7#mMjXI8#)f3T}+?q`h3rRle2-OvgybbJ{N&Z5Gg)YYyAbGmPmuLW^7*5-&G*( z2&Qd}(phUBp9Lr}wIDBXyX0{H1;I=eXh5#&oy1U-nJ5Ki4e;xDmF7GwX$A~=?sA#D zzfnVVL2HWo3RHdC6xz>NBL8Z!i%-sJ$Uw!=*<4h=)+Q4K(F0OVOH~{jsN--YVCeW&z#Y$Pix(QZTmtx(YrsL1eSGEh6lBpVu1x* z3_YPaTRFg)@xA3U(@~jf(EB6C3{0~|i~2cq+&4N!`ABP~nM=3ZEgwX}7RoM4IoxfX zGNhVMj=v5z*<;2|voT67AOLtoK;?7Nlljf=fA>4*JkN`I(I?#Zb#1J@ z_S(B+pz#f;1*C*X1JEAZo9#Rd8LuWstlo%mGpxS2!C|Nk zVP2qiaLIwAk?daCkCrH)>>4qC0f0%{jRIrxT20n+Ln;_dDaRUayY9J37YQxMw*e>} zg0*q+wbm5BLP>Q838j0CAqxJAAVVTk8h&psO1Bq-`$VcnQ7)FR)N`b zr9e6Gq9#bE$^6xNvj+VM03wG;Deu*tBQrT@)2oKOwe6*u1IEtR@j1ku=o0$sl!W1?WrM!YDZ-h znfp%RO?zS9#pOvH&}#&8?wDX*H+AzkC!%}+Az7ry3#gT6^A8=*5dkiSiJxueMEL^1 z_nFd?Hy0dgM(02odT*DoXarRGA&uB7f?J^SY8!EaYwot`6`R49vxcU(>Gr0Fzi07O zH8%qZ9L!1pCdC9AUf<$tR%8*qnk$v!Yg(>X(n$;N6YI$dvfIc)mLI_E{u$%h_;?Y` za<3@@YB@oEN8|)X?U+IR@j-x(`6#KohHDW&>LH+sj{?vj5LA;HjD9F0q!hNT=*9GE zcZ-MC&v*tkPx>=n>K|kuM>UM^Hu-QL0=QtrLnz^Ey@ z<#v(glitE@t{-~|Q;Zlz#osz85Siv=d&+ytK(b{QXA=CXMrO*lSM_iR;uN;PV6rym zG5$=|vmnC;MWN?$CKPn2|oZ=*kC+8sV`Jmf=D)|q7pGb;A+<|J+PWc-!TV{GCC z$YO`Am=G--j|k6Ritr*-E54VuYKOdff)7MQ_2vT6DCi7^^uEUoBwwAG+t*FOXt!4! zU#otFVJ&-&a=Di#)fIum{~VU>Z?*JO7(fA)@P>TF+e9uLxW12y&G#Ql`%7g0PbumT z01SC^1coSxds}&sM`azd0sImWj(gW_ToyIia0k+^YnSt*E#olaAB6A&!YgCDC6&Mp zDadLw&a_;kA;z;>nYIDpMV{Hi0{DuK*D6P)Dy3VpXH3M5!7YC;g=NxJ?>_FnBoAg8 z+9V70(dIJHA{?X3KI2*%y49N1{GkbDqtlFa@M_O0psl?PYM(W9-Wm4A@4td_ag-e4 z0SI{JAmt!>e?la>hlKJ-WI_ikf&FW^mCRP5IrK?|!i4U4#j*(!TwFKB$jI?~v; z!?kOiHK`SBC<#(}DdUDJxRa3j4bb5N(f?f^7QjFb?4ck2luHS{@1X7;+sn8F7)62m zTSoemuB7{OVYJ?^)3opKrmJ{Lh=|eMa{BB*2;1|x!?RdN=~u?{IAGii)m*gc`N;c# zuYv#pjMt?z&AI2>R23BhT==SY`U!yj0FKh3s>8KAl3d5hrdIyi^)KLKJX{bZyfTPh z56(2R+!KUo0b+Ie&&y8x(p^oQWt%($#%q0bi?#3kyYoB{T=O$zoz+RJUi4w4 z#&8dk)*JPrI(E_bpJv`)6ee!DA-QffJr0@N-L``G8l~$m#%%{0kVf<+$FTU&{&*>_ zn)i>#T?6RPFuc?E z!B?)GaO{RKunYJWast?UyzI{2njwytJbqQjTbH;#3woX!G!xJaJujhbjkM)T@Vr%~ zR5<(w6qB>A`^=WPOX@*%>{I3}N)=eF(|H)6)NFxiu~;5eKwp+k$B~+yflVhT1I%k=_%}JUnK}~tMwghj4L(i1%=q$ zoT;4na;vNyO?=edfH+#zTY0i5bkVx1Kk5Ed)G_0QqU;%90y02HF&H}g7M!3*&-PP) z6&YNbb(rq}ZUIUq3cM;Rxq}i>%Vfhy+%<28)tToEm&M+(687Fo5!qDdGs>4&eJToX zO0C9r%(6{G?H~DdnPXeh3RD}dw<9v}W6&v9ZGe+EnzaI|DS^l7RtPs&6F^SYLh+h9 zF}=8k(uiPB`|Trc<|Ip7q9h1 zG(aQ*7m`69Xg)$Pel(bnIZyfed=lo5Q0-qw+K1>29Mj!)&po_uqU!lETG3DnzYD`> zpq=#bd&aOiB2At1&O`<^TJ`?=!$9c038emqSyrg8-pk*;Ze-K6GxmUM8z3TD-n|`o zYWKwsv}+#$g7?IE8zpcVlCl99n{Q(rX#)WNNHChu3j;_84EDxPp9(tODK?es!4!0+ zfAvx=srlL23y^H0ivBup(er=)wKZY#83n5V^z>W?D9as`HUbm)Lo%4(_bZnEzTdxY zkE>CswR=D;^4F$l+aj>4zQ0;?UxzbFPe^xH z|2hSKb_s!dj;WUSumTEHlZ#?-zR{JJ;3q#< zL8c#Xh#tEIpJUOBOnAig6>nQw${0%SQHLYM{3B?D96q#lXMGy8PM-&&E^lq zkUzcVdH8B!o}bSk0`|M4KNzjROCG%9@z+_{SFk24JzSRA{N>+(Itp?o-YGuPxe#zK zpA8!M4CsY0H+t?k+xx8EkEib8}fl#d+e$lw0FoitvXK-5}NnQ`(zU;gj3*RxWQh5aSO5T0cZb@8Rp8Z+=8ymSjDf8n{3 zD~Z7^&(CQ$t6-vtZEehlke_txDH;v@VcOfRNr^GAd$%L+4-&3W`&~a1_|l`6qs0!q z63{+OYHJvu&f~DDaF<)PuSSt&;J~Ih74xMm5bk17H{SV6NE)~2nCaeC9URmrUYhwX*LmBfJhI@(24DPRp0I-n~sKj5ax!_bal0jVE%y2&- z-`PWwo4SZXN)|s8DhwX??n0B5V|dfz1x6*99f#t9Lv9_Syd=u4HmsF+^Kb64@IsUb_g`7VYlDJ`HE7lDUHb(4-IhPE>;9wJ3=pmW(N7DR&CY+q8juT*R01j?bSL*7UIp_>_Z0hv# zebNOQjI$=EbYCFKB4bV0kn6P1O~AnPin9XMf-9K*sTmvPlpi23*X!U^F@-3_3TWPu zhvdM3;Wt2-CH?R1}n? zy+~ZF7Sxmj*A`=co(x^@J{RUF*5@jWi7{gNi+}G@Hy;+&y42W%3ltv#&mpWhtH&mm zoWAuYw)`pX!Xm}+?)n@+!#Wr-G}cQeVm@r;yH5qVd|5gB?v(uOWLaV=xc(CO|LIpmc3wUvD){*I2pQ%RgGSY{mj{o*wM?O!u4FM|J^A zG#3Jd+Ax>LyPYKAUB8S@IR%8->wi#l66UM|$?PvdZ0EmXUdpJ*fza+5^*S)WT3UDi zG+rc*o^6A7toFk-WApZxtPViMK6^(AWX)lZC`=qPttS5?NYOQ*+1ee%>Saqn9PZ_R zNM7BLu?(f9u~B5xmf!jBtP8Bm*d;GF&D+pHox>6KTz`TZh9&h}iyc8tWwFMVMDjw` zdo?N&wR_ZZtd^hbx+yxS7(>HBkM`Q#e;mA5F>+BI5cM^I@o9Qu`tuj9(a;*0BtqNc zmW5+3ui#SdE^s}NYpJYKPx~VaLlgb?qTa|cqHsy^=6=d7 zYJ$V?l$pci=ES(z)P7|mAWCOnlUT^mLLaq&ZTq~50Z3F}mx{A?_$*Yw`!S9&{td%q zl<-ADAtq%F9KWznNRThXt}7NUQ-1nPBnK&I3)D-$qW%NiNTmrh)H42)pm>+&l&xey zZblhnxcEo8Qn?DOGit2a%(DX}If*d%!*fYoUGl4=jvm?p-<;~F{wDdd2&jvtS>!Yu z_!y!j3~E-u@9B^7mT44Nq)x44zfSLn{^Z5wu78YxS2wznIM(0DXn}kbfFplkNK5Fk zI(?#i+>pQf$LT1EIU$84q6V2W3+mqLXc`Yy8PPv0@6PSlKcO0Fhqoz@L}SokrX8Q6 zIh7gs+dL;Ta2CEy;hh)MFQ!@y*yIc5he$$#Xl{kkS5OWWA2$3m+4N4&k)(`NM9u>7 z?sv+na3Co53s+p7PAi7rLGc5vKlH?*O!MwGXXx4Ou$*Bjq=a&LPi44_aYf;mU&Ph? z!#Yex;04rIt&NkJ|8yHlJMtR>DhmRmAVmvJPUa)Ds4dD0;RQ&27UhAlaCzoai{7S=p!QaRI8kH%XqzJa-^0t{ z1&iW-`J^;$*e&DIjU6JA=!_=t4v`}(1N3Zrp>X(~vK^^v)*tvZH%Oj;T9uj$I8ArH$ z)y+4t3)#S=tCHUB1FQl#FiXI877k5v zu3Uzm$`)@ehVxiu5g{Ajvs8St z-lR;WSz_P3FDIK|Sp6f&)V*kB2 z&}7(^p+{w))&!`wp|t-Afh2lghuho_5CPU&5j7k6B3$qVKYa9&Tq~dA=(kFX`muAL z!5tODfi(Jmq^s7&4{?l>+!x4umV0sLDcm^VocjoIhGm z7S-89n+eP4GroeRW$^d}RhRr?O{FfTGZ=R+`+tXLb*6b}SGuPMX|Eg-vA(HVA3nM9 z1uPJDhEgk4#{zw|_~YziH}gc{fU6F46FVmk|3B!JYftvPMRacv$YqAvEx=Y6FhOceRC0pWM;>aAmN>$AX~jh zgN;Hf^JqITCs%zWC(#BA!!7U5>f^yw4(56pYhmyxiXZDSSW5G&;Q!7hl0T+?L>r=y zXam@vxe0k)Rp}N|(SZ9GBQRo_qT^djx0kg~UB^(v0_AXWp+1+7q+T}(O|UZN)D&8= zTV&9g=V#v3-%4C}JLI6_qJbi8$nK5-{biSD;DA7^>W^9WgsE6&7xxdb|L)KQPz-2B zIWPsd4bjjlm>Vez(TlA2Q4l8)&H#^cvH~R`KnYx8m-vTNRu~#aO9_gxb%!V;^@Ua| z(89ylYfNIsUIWIUVR-Xzkn;($uf#u+)1T~8*gg3OEee43NACO)$=!_={fD%ur+0rh zg}j1E8d&5r?3JDHyx<&}?JftWyma|(jS>*JfECw=>=NA?0VV}f>fnwZZt^G~C?R2x z891kxU8g;A6H_CDEk9jdL;;?J@8-KKU{OT^4 zY8dcX^g)5GDutoWn!&o-0N!DQX?XtuUB##F$!urRz)>VQGSs^~GWPhGG-Q$25y?x* zutkS7apZrUotILSr*M)Hfe&ati(eUMZ$cMu`)!I2Ou(=SwF0C`k%ocQrd^X~ub0Z6 zf`Hw4RX31f$W=GTMlPr_<22R*=y-U*Aymq1gGHql1e^#2)_=@`u!O>lMWPNk2v?B0 z*}AT^t0|zrs+@xpl>y!hm0_)b&Cb^Kz=!V3 z$1h=OiI$A1H1boj+nx@*^{JV*1%_b@UBZFHBVgfRQPUnEs~S<)8=e;FnGS~1ykapt z@LcLld`#d~TKeA|ynsC3~VY7f~!?Sje@5RBBljNdjP=cNVyRB{} zQ^=Y%5A@>V!QTdne+3|OA8|GGfkHfatGaU2jGn&=L;s$=YUZ>Q{^tw1y1^oI|BxkJbKO1S4jcGiR(IG5J`>9D76s-Mnw{8J`qdLhH9vWkQ;H6Y~2Qb zjgJH#h@5M<)AQTMgY|$_f&KZ;@J>kyw#1c%ZE0R}`^4UcN-WHN^?s^(AQbBKtx8^j z^_U?${u@=5gx$0woWe+_Y7gDFqX};yf)nslL`qiH#OM#k&sPBJw~Ic=y2KSS(Dz<* z;IhcCL{`D(mU>eo`8jvE66}HPe;qQlH67-J!eJtS1$mIaD|3D%80gP!s0{VFZy+uT zJM#o^Fof~91alOe+SqKqvH0-vM+Purb-gZ~XiLDB~D z6bFTzVCT5wuDc1sm?BZVz*lS$sq$x+bK|MSO}3|3A0Q{Wwc3*>)L>y>kuaAcaVx6R z4s%heL%%5r3dPram<`i=DEvpz36zLb_u}DE>NU&LGv^}bbV|iPWWMbPGpo7cZpXBS z-e!@H!S|8*q)c88K8b|&r+W;bZ!qCi7*Xoe0Uqy{{}^B5Ur{uTXC+T%H5`}Q~_8){3~ua9U!9BZN(eLR$_h< z0unJFbQ~(fQ=m&i!f=yOEzPt)1eTt4?M~j4T%MR@kmtRNa41_j2gm&j>utq}1`rHh zWSeG!pLaO{C=2E{Tri;AUJYIEtTQ_LaWu;=bJne=V*J z`FNrs;M`uOk|`dWcAfXI3n~(=_>#8zk_KLZChPIc)~{n6WRikdEVxevR_Kt{;ERa<{?p_^)&luYxDCA)l7P&r#{b4yN|&=#On>WavjaWas(+3Z>x zN4@o-z+|CwJfH13FU|syf3i8WMi1x2j_vZ8*0n0ELD60RvnZ=3XOaH^&~htzmw*7R zIb}OR#hI?~P?}jond)BYWx;4(SWvl3^3T5e*ryKMEv1N$efq3 zgvN!#o-4l=OBO|JD7EI;uO6FEoN0mCB>-p<}0&5R^Q+q^F^vSU59h-_@F>c>r?Mvoh7-EnLC z$FP8hnQij?UM#{$u5H!>gj6Z|u>;0d!fw0H`cQu5kz1XO7kqO=UWmd&wlyuAIg%yl zQ%qtT9G*@D33{b17@PyA@t!zfeuzc5lM9eG3Le#kgc0!KKKB=2LPM1l8;Z`$Z7--2<$Ao6SSjRzRx>i{%l`slp|V)zZnbg*19Cud{Pb3`SrCPCFiwoP|tjThe z3mvEwubLa52gA&TpW@?35V^SdH-~)*l)n;eQiOY-^W53>K$?FMu*UVgmg;qzBeU z+*@`H+Y~1($+D>mlv)s)v(1J7J!joOj*7x%sfA&rAQ^B7knru<)1nDFeS-kL9gV2> zZes&bwZ-*t6gmQg_oRhm?(fuf{?5AGGza~`rN0Ivg44kRnD?~jUjmv@2ARe5Nk7c# z%L4UF-Or}A(MzqwnZRb0FS>7>SbjiJc{u+Z)vTfE9i5Ls3}n0q;#WZp3%)taDXF6B z-O8m3H^xWLVu+$eM;p$9ozi$QbLZ(zZs3kC{-==Ify5~4B92=CHk~kDQzwCcM~tfq z`f`$ROj(DP!Oz72gcZ9R@|-PMKtVEt>a6o&XA2}ksb-%lg5|+Q%_R)lkI@sW5n6P3 zI1!dvpmhARq%bscn!h!q%(i>WM8}Qtt%n(T*}mILBj}Xd8U{X~B#roP95m?;)&{)t zsEs>$`J(1l@4Pk1e!yR1;jYqS$1UW~bS2Go(xlhFj|y2Ng2us$0+Vq4m(%yH)|9#7 zFjJgzg6x7YVg_uxie3f!R283N31`3?>}az@$heq=wWG9+{%$|NUHovr$+jtrZ`wUc z7HaCS5?IkCQDVsXpgcr*g@6PWig&|9OM)E=2wkWv*zD6RW#rI-OX~4JyDmCwsMg@; zrKqK=3Y)g@v7OKat?l!moggQT;&=&FhcXK+&K3`KtuXWI%|$1>@YaD;0add=ESzrf zyG^(yyA&Y9ZC2%vOV=A1`R+YzBX^&Y&jqBN`u|Rle8iSh?JGeJvM*ZUZO(l&uoXmS zA4gyaEJ`MSzxg)&zml(#gO3D6OR@f2BjNVKw4x-ufazLALv^e}0el4tNWWnOWQlPF)XG zbnl!b6Ye@e_+xK7-&`GmPDln6{CF)1A6UcY_m&G)1Y1ILgs^uT7voXsJ(r}B%OMy&&^gi|LkR5xS^G8PJ$*1nV#NuAiPC}Wfv zyz`YGY;m0!XmKqhB}uk!w#RhxLGObz1-fUsNk5d7%#2K08tEWD)qHokzXNt={3Y5# zJEZ8-A6nkOkim0Zbo_~gm8WL#K>RZx=REwY#c$*#3OPc7=?~r8*uXv2pZX*X{4}Z$ z4;i0O;M3+6J2!dwhr3HCN?pGGc5kHih^PQj3amNM(eZ)-BC8=sh#bjyoqm)^j9{{E zDAqBhQ2q!7U<%~l{!4d&MWFM+XaIsghcqf+IIl4o+AKWA6f3s8ve7N6y!P7Q&!8%E z8#}-&e;-xBO>-uMh>?Ama2w+wR-OETNlZr;Im)NB(v;zCxHNOEWdAzzHg;gI{xLGf z&jSl|N5q=m=Gr;fg(5}|3WnQQCW9Uok(p8ftsuwwe!>_h4JW`mnT3bL|Ik`C8AsZ) zgZ$A?F6@E2FOC6=r)|Y$S06O0qp^_aAE}XGry<3JuN-jLcrU=l^xFWVoJ02U~j%5z_d}ob@W&J_Jk@9WcrF zoYHh|PRYsdC_joyeTAn(j@^9PHxsaCn#jUOY6yS-3o{BX5J3G+p3my*ne&`H z>ud!~gEC%chV40z8N2L6z!|NK^eF3> zmj(8A3$(J(@yjGXqm|vGZK0?vI5{MV>|vMx&tBj zS_9<&zI5Gm(TT{*X@2bba4(FG`jzddX$UOe07e`WYTk3&TM=V+bXLK9CMR0@2;#p% zpWF1))X%NU>&nUR&3Ud=oeSU2wby@<3WA;cEw-|Qnfcp3WxQqleh@rl1}rXZ8KK#C zF{w;Bm{}oi@(RSDM zjn7rR^A91@^*y)ox-D_>OS7=HmHMpO<7X1D_HTfif;^tO)tKg9&%<%SrhkCaf`&bM znld1C?B+1-TSevdk8KBME&OaA0okNi{8H&;7MQ7Deu1u?OMixzruVz+#h5MTe)hZ3 z+o~gV>*=qSVY>QBLT`1~_ajG7Q``R$f1Mlw{SL{6&2fFg4;U90{1POh9ZgS0NfZtC$v8)7+W-yXobjYQ)jv)FrZ3R6L_dx5KSX zo1bguNBziaNkrVAD(?N=tF^eFUsjT{@DpO>YdgOMS8f-_XfMSEpt)N|Y9OP;(f;oVE*4D$&h??R9omd;r2UzQ8XKKF z%^&eWRG|H2zJL_8q`qTu%a!BRDxVa_Ow1Seyu{$G(jG@oV5F*InWiFFzofqMwAe<| z;`(>HK5V2Mwez~vX3ApT9f=zB1klg(D+C0wafUr~_efofRna|%LSeO(IzTWqaiZ<; zbYvs!Y>-bVHB*^$tKr^c)JOKS7^X`IzSa?95ZkjE(^o2d@S!(ln8;cY0s%&4hV|IF zN&(|`{(4p$BTWu9A3aU>=LEam)RAGqrc%{QkU&|sRKQh8VIQ~u1a5mT=GugabEPkw za4n&YZRQ6U7&)|ClNI<2ttzQP4^GXhoy%G>CBMs`3=D?!k#f-P^i5D|Hi&F2{SVd2 z`%-L#c7(i;_f)80rlwmPy^i$`aDY3YTF^sVCDIjNiCs{-n#m*~i$OabLY?LFj$i?m z;qkez!OHpQrPm&{6-ac^K07ot+E?a;EDzXtAN5)8radb)YfW< z0~tlL_)_^rY+wTmRvW$Y%b-J>YCSchD;aXEilmC$Rt`VtIh|HzaoAO+ee0i0|7tuw zty*p}-i3D!)$rGu2&A{l zgNy{gG{&`VPEpC8o31fa41522EDut|i>PKH#Y6OW-pk=N}`c*scYhYlqa|Nv+M4oxrt_}b4-ah^0T-Z z8>!%JC4Uf-#2|uGayv8{i636ot)o|7wiGq~Lbj`&LV0RQ(KUk;XSHn@>RtacvEE6r z>~4_iZjkIv4>`nEa{XmUeK8EKB1&}+O8onSu&C&ql1x2u9%Wcf@nY-qmOurcsN!sr zS__7JJ+jy*;5D~rFSvfqsPSJHW4^xR#jZUO#gIL90`LiJc&9%rj`6{Xo~ zx1SH+Pt}9i^jNE7wWJp#Mn{LSnKF}LQ={hG=^G#f6J)~Zq*iS8nu}_9`*893vwgp> zS~r~tTyerc{`R!C$1t+yERC~IeO=eDM`%))R+9)YDaP2V*~If zDSmUJpGV5(B~Q&STrhY*k1=9Rhlw&`_p{A^zU&55mR+^8>V1T>T*TDP};jhBB{~TCOrMhHduQ*uhCYD3j7?=b9V)Eo-Zj74jQ*f={v8XO% zr2GO$cdqR`M~J52WS?6FR0S{vN`6K_34@h>rc~*j3#SeX4V~-Plp(cp^m3nd+g^@{{q-Yh=^V;CjuzV2rJ11v_P~&(0C5 zPA}!~b$Pp-rmuf_R8bkg4BR>)+CWppYcG8sT)Mw7qjFIobUb~`)|{O=%~cpb#nE3M zTqwwQG$5b_7ZvNx|Ff%6BlwOW(^vc}tn~CE35QqvMUN}JmX_(|7qXLd(sZ5@P;6X!VWy(-;xzs#&?j2Gc}gnDI50*GApi7$gSA^Pi)kVP*C zP}8Dx5FmvWTV!+_*(H?=6{PRpQ`kq$TE?l(&`hompVVY$=?-4ERSvWoD#Fp$-Dtf@ z1~fA^;u}beyBtz#hpRU39MK+_KS0_RWU>-vrhXr9PZ5|1 zS+~F0sBoxFZ+O@m&OMw}Z59o+oH&boe>RivAAs_kAfPW*1?M&p%jTKaK*ScL$I)+R zLH+DG!0x%~vu*@hzWLE~kbYiD1xV3<>y5`Wmq^j^yS>)whDQ-aEm&9dnq4QB;O-#> zRvT4`#ML0VE+1(gZfL%3+{`tldk_)2%RbI`dbbQ1u4tH)jUCqG%HUDi`aZB{0E6?K z&&C7^5-=I6E!lW;yo6@5(Uoe@t#DaxN4sAAA2wE+cfbf1i(NFB+I{s`Kee$5U9e>C zjy#?*YEnc!pygm&TnVMxP))Z}B4nD>tly@eH*J$RKc48{|7ii#tn}FH1o36+x#9_f zX}van%GJfwgMAA`XActrj$GN3`5Rl%VTf1 zCj#fu`N{1fTTi* zE=8Zf4+HlbD4ZajH7?>hQAa^rqN|KvD?br=j?;Z3IV`=nz7~2@M5Cc7KKB9&1Rlyd z#lFzDxU{||J1wWgRAnRfn(zG>qZWKb6(e-j>el5!f>Uh~N69n5OP+QAN@dZ?h69y5 zv7Wb-;=QGEe;PHD?_)^WA7QDSsS>h^M5Gj1ZFzL)il0|4El2k~P2OOpz2R&*jkMAn z&7b^0Md6Ffg6M|JPZnbL_FTXpKS4t5F>1UC?q6#emaLQP6J$E}-xR~;5I_i{6VZS~{= z+u?4FPS{q16?`kJz&Bk$Bj9C0&6t@S_75W9RF&Q94VloxIbx>*mQ*(0uQg|~w*xgL z@A=V4Hz{wIs8ksW&Qw4UABU!*Y64i>75WC__So@BgWn8QZ7e(VjekzI%K{~W3~&IBH31<^gldaa>=IMG+=kA_Y5mXy*L;li} z^o`@+6u`@Lxl_^1exJ5NwLf#uGQpb!kYeHB0?|DnhTY1Zqo@u&R(5voxqH$>B$Q7%b#jT5L!lakMhSLldC@My@|{*K-GG~@uELdhv&c= z#l}EEQFQunQG(f^Sr!z_BwG_zNBASOnC(|m{drP>?~i&l4wZVmnC!GDeJhFY83ZHS zumosGP z+rF>(j?By_EUDq(_PCp+QD3Vx?d^1K-kqiHlHk48$HiaCtKWgi;l6rezgXv98|6wK z53vTaBD6R=-Vg<56XR!VFGpLA?2e8!r+#Mmz?P#xz#pQ7h})b8nXpprRF<`rbfmw$ zB=F{$MYmW(cf3*5a`swbG6dg64gN%%`3hvy?>F+_7UdQwtH{;sU;~GVcZOG=4Ej&Q zmL9JqmzeKG=^u^xFunN@BLoOTs`Lqho~tgVcXpp<*j3#e7eMW(R!>m8%)XLoJI|Ue zEmG6rI3c4G%tmk8f9!{UYBEUmgvHG7raSWPrrZzg)E$KE*25ez zmt76AawmYt3>?93<-`D0fbh9Kmb1{s8us!aKalgC#*?dbcN1)_m0$RZzFO#TmbhD& z4w#Xv^`CT^|E=mPaI2lm1&Ry-PaCfD_PZ0yUra+t|Pb+gTw$BH9Bs z0h_-cZ`JWa9z^<;1(S`3Rn`t1^xH*nwuJic%nm_bG zTqQv;;8G><8l(h0ia){Nza{}C?`C!NsCW~_&o72-47Ny5MgGZZmqF2qNGgupp!*6| z20zEDyr~TfX8WPbMxR2jAE6)U(%NURwvd zf7|j2^%6moU?-wKw;g@t>y&5(32=x{+-aEbM_GPxuV`O=+*ssr6M|VOO}G3LSnbc} zq7N7OF)cY3-_G3G#eqUdJ#$_14i>>;siWu<*4kfu;Fr^omIWesAQ+bO^sV#={*?R< ze~b}h-y090<{;>XEfdX}Tu71U0W#KcdfzUTyCc^xZg>37E3ocfB*1ru$PvtC@G&2X zeVjwWU_Qx0p@?-mk+X~MA4?=zNR)M+W#%8EEH=&bSTXA}c)KAKWF2vmWs&G)dI`BK zvqxyG=(h7_t`L`_IeX#fyMF0BL>vdJ_D_NE{j@*L*}x%h!v`1P!ncuz5}Fc#N?SVy zo@eJ?#?kv_T%heiv4h@-eNn8)I1i|u(G(FI>_Z4n8s}+RVm>pbCWjHiQt@IYw$!*K zJxP9@rv55dbu0`Q^}TCr1H@%!A)ZfxyJh!9LH7VI$C2QB)hsdVdgND;c)MHfEYQuF zx7|u$Wqzs8f~$K~99ioIh1@mB=TJ&LI<^_mxegz)-<% z*wl9N9->l>R|C*1K0}f~cuF9}^cjngl3J_=P9z)<9R!(&6&J9~%D7#GkqnK;0})#K zjLv@hu87lMUCr61m;k`dO!_!spZIss*X7+Cu#A{=^QE36+ z-v3kU!DDsZZoYS|w}@OM#12guEF4CU;|U*G=ek%hp$3YxMWn$}p4<&|PQErw!T0G} zn1g(`&mVM`5^AC}yz=TP5v=`YM23oW6blgTH@w_pJ$OG*dT!}NNU0W+l_>);SXj-I zX;x<-In3+C!xu)^Q7Wt(9t0mBTlm_UB-t&{qX^ey%cgeHw-p^TxsfhM*L&sqvtA<0 zGW+q*W!tw6=WFX03x;~yUG;IM60DSNs?#2-D&4s#;4x^Jlh{R4qsf0tN^kR8CZMv^K3Ayujh9>B zJwN5~su_ss$wnA8ZTsV|dCT5o+HRsdVkK`)m|bakw@JvdZH=mbADLl<1Jlc{L1Xg8 zPc#17pqtYK+epb2ZYi_D_`%l?a0e zZt2vZMzmEs%e-v(OHFF+2~l{YxAGP2T59pj{XCwk2*_d{T66G)`NR^Q6>FHs)Cl(V z>(W2Dep6c(DX$u8I4#Bfy5F?sYL!`VC@67}q`YWiqKd-+QU~&L(=Czi4;IluNoyed z=5%s_*ZETS;MKY0YV=EXOUsQa@ePARZ)P@u^6=aEM3&>@{yRv100wZ>d*RJ~!(Sj+Chd1NDzcdpL$PQ=0g z6OmUt)~7Tzm(r5*kpSs)t+2G&5HeQT?2LerI?eir%aYutn@WtOme$<<-8DO*Xsf*) zxY0FWKhzL8PCUw)w6t@Y;iP|KeBtvp)9k`QE)@Z*#4uRWtN z9|vqtM#`gZ$Gr*c{T4x{9DiT&)MOV(Wf$lR*IQ!K13veK>S05eX!{YI%bOLF?%r`G zZ660V02bPGlAxALYTkXi(oq|gR-tT`t6ew|4Fp)K-Kt?#60rGCa3e1qDiE^8h#CrL z%z2FF-(`nF)BSMRKapAZQ_ew-UrJBAo{5W!o_(g%LY@}Vt*hWV=|lXWlvJNLI8uN> zc^@GKEEnk4sLB0agBK>*k-e zx7{|IiH*Prjc?Uw^|eOWf~0r4*0#5k;n1+!>$KMFQA=m-itSg_%eMrPJW8Cu6dP|| zNZIbL8OM^CP?l5n<% zhb6o!9atEePL9u0OAX2bdVw~M%)0@Ush2WXqxuGB0?@gkn>-I(tvoDUacw34bm7|! zWjnbXFp@r$og=1o5RLira-PbOaOmDN&U@Ch|E@+P^I}y&H+dZR{JtzQ?P4>^Iky#U z#__VpS4u+}Bh#JGcpF!MV8l$l-L1~q7~w(!)iz@r5uu!bNjR8#+)uzP`j<;6P*`b&I%!t|$rAnZKK(_U^$LF1!ePJ?RRSjnZexlFH$vM4wDd zhAmm*$CJObw4vsB>-!ayl_6W@A5>&k3N*5wcXov2JuCFAj5jo$=QfPX)dKwB0HSP9 z!-2C}f!1&h(C~P95$E1#VC=oHEL%~*`G;MGXv@c@0P5V$OGw~0fy?Rung z?n^Rrjjv$nm+ws31&*<6FV0mdufRzQLGMZaontZ2P(KU~Yoh~yZ(gr&*-7Jh{+~pM zlY&VU78;{I{itOoa@kS~Hibliya&QxFG1CL(P1MPNQ%hk zLBm9q`nTXcfTD4`2X$LBE|Zc=y4|gxxjkPGRjyz{80_C{V=r)$NJcD;6p?y$=j`)QmWkYA2G0sp9|TZV-K~8Z-ZD5h^Iv3 z>miT_aq2s;;8UHR_?3LEXmU6?l%stmi&#CcK$)-JSfv4uWo;*xx6T1IQVSF)&q-*~Wv4G6&yqtkobAq;RssJ~Z{#&8btyIyFIQH5DKk zve0%qFfgP|b#<7Jua^#zI4;YPj0^BcchaWIBn04ka;0#!V~8*_*=QsNkn(Zsd1}yP zurrgGzde7`qc-iq=Kc=xnQloMEak4^R!P-^D0>Bz++0W&>?Z%+hC3>jGb-V7P+riJl8l%oT zlb1N^8_OB3M5ArZ`gNz$=&ySg;_EU^qrJk(>ZQi1UYn;Oo~`hUP0<^ctzCqkjQR8M zl&C7$C*i)8E;PRXZVFfqyu|GXt_$IxhI(Nv{&Zboc0bMy;JeBQ4E!z0y&A&Z5#zk3wo%WTwjtF~Utv#;NO;$P4B zMuKb8IE@7;J0NVV&IXWvhHsZji^E^SQ?38usAhBWK&qMFxyd-7dv83VB$aaGyJnbx zxBv~(;rfbrar-2$U)h|IR3M0|#Zzi+Rj8DLZFM#|xs?dUd0OP+g$9TXmZ!j;iprrF zD{ZIwI0e&Og#DaG%uW`$P4w4Tfjy@QlYM2aX*Z3L`XmE{_4JV}O5KXZD^jjuX?H^A zS$Bizx>{?W6w9UH%IQ{oJ37(Q*_J3)YlPQ?jLv4pUs{R$YPP!;WaX1zdWzUEOQ$Tz zgc4Nb^`a?Z)p;a*+?MOKc8ABgHGWC*0u!?q6R=;_GWHFu@b!kvOvU!3bY>QT&{v8p z9zWGZ0a7rNl@+|tJP>*7w+%G*enmb#ZZ4V^7>buX7hNDz&9Q!Uyaok{cJLmr{A|ede5}uFFq|5o8jgDvuKiT3a-W3VWU&C2S@c6C zRFe`fxmiVH6Y)vS>wA4qD1av_>$M(V=m6DOKa_!&dT?JV@DX^t*qJX%m*lg0L-=^t z5fD+<<50}he9-W)D|j%wP&0U5L-q1YV>L@3ilQnnyJy*=RxrHb+^^r;b9&Oj5#AMt zaYKrl^-N!}s1U*7lazwDeHy&_d*@a0@#AYFB~2SZ)TGURjbyvw@jHPy;6wex&bCmh z6}6zZrU=S0-qPTlq9%k=Yc(p!o2B)uN)wvgs@9{ErMt`{k3t%L5V9Plwy7jac4?KM z#V`LNDpZiw^f7#m97ff0)oTE}emLb7bk1CDq>ZEQpRA8)!4NI#LO3j%ahB8Egb>W|OUiui? zWOPoIjP*CjsUpB;XZt)c9kSus^vMDdk(!K;L#DIY>n0Z|H}|YA`=)RCs**lYt?oVP z`u3#rg6P`kVUJeZOQ^(5$^ezQ)jOZkEY}-w-ut1LD&Efa%j>Fwr_VS^TIMz)J{vIUjS+Os@wRDR&7tU#@Nv+zb~dVaWkBW+T-5 zHdn&>d}$zsk3~;t?IgVuFDosw-{CO#HOiwXLTJAI0fW;!rAq9(D1A`n(6fw%7d5mL zmAE=%4cl_IV-!O~uN1j6tyN!(RxeZw37cR3Qh4j{)cr>rwOJx*>6~hGSu^4Hl8!)< zJ7QW|*Kfb`wo z^=Cz?Vq&$KM>^NWZ9xmxkGGyD!r4K)z%n$9E%?*Pb^D#9I#<{h$l5jlZ}Dz7jehEK z?pY4L5D-q;<)Ll=fpOYH^(ST9iBWG%Vt;>k-V7yp@?#4uNU;hu_UZD5 zgwdFcq1@F6s&|+7l!8x>Zj` zQsk73ml3O8jy62MmDV%WAmo`Uj!AdCl-B8yZ9K_F#xqz)RNI2ZE z_!LX0%g=Fk^k8Fu*p+<8PGF=~mCj>&?{k=YzmT*MOcO@V#OK8v!o4}OF<4*s?j|hF z+`)U_tkI4e2ftisVv%t6vmcbI;jkJ#6{IQZ2a}Dqx06(F;gVES`RK*mV_WoY+B52C zM*<(NRo(a^e^@r*ttxc@3lBrn{(B+Nomk>bI`f=iEPo7Ic)ew)0`BZDSfN)Uj0RM$uz9ue`o zR}wkLjgl|hZVCU>(71*pO?_p0C_J&o)@rl>?$(?&)O~Oh`j_k!+Pslm|3GCl5-;U(n`u{M!~5s8RO3ANXLZk$ z{(0-tfs)RGd#~Te&P4_!YnGr;0^n1x47?q`7WYqlpjwM2i$4A7y`ZAIQbXkXp4fs4 zabUq9KI@6G-+_VtJ5v-kTo45!%jj&RXY|m?z;G+;dr{*aW4e+*tD)#;r&FW7{cj>7 zUsP}5JtqRAD@!an{m<(AxX#|fZekJr>32?R?3=e#MULegr*Nn1GB+uF?HD}z8PR7- zd-z;(uft2+ui2apD3&v;;kgt9;eM2r8SwOyni(%!+k0>420`@9pC8hXLm|+teepeG zZ*g=G0n`uPxR!=Pac?x)rpesxUPK?{eFf}h|H?skS+Z*{-Nr;t9j=B{EFRhDQh0pZ zT%k^Lu4Uasa>VH@(Q^=uZUfiB!o@Q8s|b-&F(%G*KdH*f2O|_CsNdu0%ZG^L!zD+* zMe0OK8=`Y@jJI|-Db_>%{OZF1XBitS>u{63K4`LZy+No2&K!Km4JH!WwvY(@OhjY!9_BQ&t zPg`fK5ldY7^4 zabGc2sHURu`JVanQx52DTYQ|}niZtt>M9($z^-1xVIs(m?SH;&88K81GfdW`$tUZ^>`|2ZFtI8c!sM=m(`++=j$pHN(z?4EBxsCn#x=Uj*L{etiFOj@K_x8*(up| zgdJW)bk!fL;3hV*ZTC~o{^UR31NB`uBjdno{k+Y_s29l$Pd!7@fs?B$eN`gAzjoKoRRs?n@`nGerS|CtJK{>I`J; z#Rk3W${N)#OmMA9Tvz!eCK0OI9D*qjM_Za7BJ2tn%`rd86#S@bhbF!oExh1Ig-NX# zbOVQb`HL*!CT_#OF0nb;h|Y>$yM!69&@C;_nlO^>Qj#BfhOtk6#AMRaJD1cQ7Zlar zoo@VM2Pp%b$|O0@Lh)^Da-S^LcQ<)nw$0_;^zW1vaDM(Sb(n9{g)BR6oDNG+m20$r z?}QZ6_fdpwkrYBFz`bM)9T=ng6kvzGw-)+BhXN*FxOYe|^}3+V%I*wggHBHO(v~4^ z*S!-kyZrDYF-u{>eXoCes=l+3$E3`0liLyW6mF-BoQD*H7|ED~ER2ztFmECNp>_fc zCvP`{i*Fmo!3YF#IRs$_9gV28tw%W7e>| zOJXp=6b(WYlaqJK+8a`_0AsL#Kpi>Rw_SPiBJS-DQb^ z-bM=VXUxdoGwUK7HStndBmNp+=$s$YD-%vS7y)?pmct9cK9_6Ika30s%DRf9>Mx%0 zwPyM7Yhd119(000fyLl_lUNC^<0+jssHlP6rK8@dff8Ik+5WYitZakcZdkJC^PT6w zUtb@R_p03?^XSBTW*@n01C?u+!-hSAm7q5`OW+gR{aj4t9)`^Xg|KuuZ#rouH_5uO z3+rBY{LFqA4-@F6D1v`MQdvo#4TpQ@X56A_UjVwFlg;vYuJJ7R@}YRP=elkQ_1f{sz^D5A@1n$>`2RMWrL2+Ml^%8+Bux9A%XZKU=rw0llo z=x5(^CjmbS8GrtTXNQY*uQzxm^u^oj437J=_WhU;ULmZFt{H_FpAf__jH*K_wl5PK zPDV0>`b+s82ft~9^Hfm@=%^8(jND-$WE~rV)@%wMW&*=c%!u{hf5tWNOj2AX^c7n0ac zXm?y_Pze6%aX(Y^YB=rvMawujjM3!%g>axELYK=x3L(rp0b9Y6o$!DYEu9b}%traXslZM#gqoD;GeHpZG2ATC|f9)f)XO;KVZ6w zLGMACPr{)(hMzmi^797sbB4q?hPgO~o}Yx&IEJ_&yiSug41N-N!gwQoeKRY`A{k3ct%+6J- zu8lC=eSTpxN*dyON-e$!Cjm{|>(1|fh-LJNWGHf4shYtzAaL9`He*Wb@c6xD&~R{m z@bb}HE|lmj`SaSHRQ~YmRZC>R!vgLNGC3n@>bL2qK9KXS6|M}Oo@H%nwda>lG0`mh z8zc0g3*7GQ2dUz<87K!;;Ng&QuvM1N9<;$GWH zy#nFK5WbZQTe{>MqEBIOEajo_;w4rHm;#>l|Ha44_AEdc2On1R(J2@Zk}Fkx~3utL$Zt_3aSrXq3^c}9liin z)1f;+(+#?I`2M0F!~R~0MJDcS7Gj_D~!wFz@G2eN+dHf z0L$|s)n3{-gLLo|4&=u%aHmF6aD@y3qRK&|Wa4(MPpj5rRj<)66PvzQ%!ao1DlXRu zM*ZZ(_HvJvvQL7|6wvvQU?llE2of%M%c%Bcb9eg_O#r|*>kev6CPut$=cdN?493|s zNZNeuaH`PcW{Zn2*6*auuKk?ortPfmc=pnBKoK;skRhF|8{>sGjG!FdKlL+8SQmqz z&7RLQ1y(17I@>f92e6Jft@+k`VPAWEX*AjUg=3-&$oubkD29)!Ayet|{rm5EW68hT z&@gzpMvB!dYMADye@wF!Rc)crtNcL)++t^AJCZ7>jp$;>b31SX$vCvG``p6jsVq>2 z1T(2oX71-{(MiDErIV)WCHOiOrnwxQ0};-#$lY;>m;>nN)?Q{H!Ib`4(15m!PcJ4r zR4G*tU)DDnYc#oTE|7>qjJ#v0->reNeL=!WNRIP)?E8~gwDf5SU-c4=l|-ZRrLJvgf$m0Du5F~yB1P1OVk1EZI_4{p`=IITU$t9jfv4eo z4vRMdpUlkU*6{2X7b%HC@TZg|lbpS!O>G`Ewmx~?r<@9<%l1E z+Ml695aq+(2VM$g(<6xL#gM{f!nqY1P9=%e8ze>RK8@pwHY854_NuEYKa3^FZSlfiIp8FHU_(<=#4;K;&UU>gn``2B!aG|i4c-1 z*QlqYpnPuDqwi6tJPJ4JWv411mMX7bp(?I8(_P*Gj2HT6;gETxeC40Bx=L;}{^05fN$~piuUI8h;MJ8hLQO#P$E^ z&la|fap6_53vxvVGxXQjar*xCb$Uc7^Xbd(!Dg0Tn%ajo#K@0mbo7WH9HkHH{u&mN z$$y6R*Vr&Ix#aZ6LTHBijsKK0oS08x@QUBchU2(~rA56Yfdb=*iG1-_pa1h?lF?O+ zLofl2ngU~2IY-gK#4Jw&tV^iXOA_$D)&Fa?B#}BiU*w(;L2chhv{&@0T*6wCA{k=( zc@kjyLjSXje@_rt2GfQ{gi-VR7}K)q!3CT<6J;{aoRVxLeu_LJm+@|Dk5w3KCa^_F z69Di3GdDT8zaXwHejzP>s6nF4qqf6_I(c_t)S|(KVlRhWh9QaP%jAV$@}Zf54CBXKBY*aS^praOcfG+w6O!mmG(caXA6 z@}p2vs$x8M`~O;zio}~&&wFoV$NAG*hCxbi&zu&P_O($iKAHUMqJvc9idRp6N(co1 z&f&lq7rDej0E#{||IXg{uvVzzZ4nXBY9mkk75tCqk!TEc=@{bcQn>k*&ycX~=vFmpuX9cuv=#-REjNB3b(>+Q`Q11cD zQPpnkme32>p2xS`1Rt#?ooo%{qL25RH+~8wuMYmHtg7eYTa?s=)eE+PXBLV ziZYw|otQ|KbP<9vET`Q71oQM+QCvCdk**LUK*{=UBP?fP?USU`CD5nYgLhKMlsOyv z=l=WuJEV`s<+57g0tru+<8@>+Xg&6ZK|e9+Y(lG{4N3^h2WF!)GS`rHaR|~QB68sW zDHikJJ|;mee*9HMg`7pT{%QV^T_!J%pcWcOF5MP^24iP8v3sPW~ERmR!R0~`7s9Mly_ft{k?DYI&J#*Z4)~``ze>Lf} zJg{rZ5ag;DejBCU_b{Bg3Nl=uBm&ezN3PKSJqlArz{TJoNyD!F2c3fyLakhok4d9A ze~Tf9Y#U@`1a0xZ=W>v1lKidV%KG6e1X{G70sN1*wuBY7Cd1|X(R%@Mb*B*#v`zoM zhQNr?X6h1^LMX_tML{}knr?`<`~%vtI{IfbMqq1+<}Z23|EEisT)OCQrAq4DL(kcz zun3^2TsSla*{5}XbO{4H#zl$wt^ zfg^us2S0) ztAHHSUTG@E|L9U>XHn9h@^*&EW{H4Z5F*}!=cpQ{y;%^an6(YF2~iOq|c+&N6^g+`#0jVj#B+oM{7AyDSS)%0V>I? zq{Se?xraf%Hu779Le%;cKMQymo(mzpboNx6)8} zE-86cO+`sr`|sfmIuCsUo4I@y%&wL8jOY43r2`5$A5EmA;Iz*2uI!8HqM8d*OM=GM z0EisQjQ^!bXC=8DR0yEv|J@?>Vp@w{-RW;i(XMW*_U!n|7O8~__ri@ILDgdz>;uFE zV9m|`z2=~VQEUIl2iKqb*qUpVHHH+@DnuUz5|Y<`&XzIFyXBX>EN9|}cB9tDz#M<~ zSN`+=9O@)mt1gG~CEIA^Ld+G%_Ve=i9&C*vi3xsa!qTh za2)n`^kjRX1=K_MpYjvo_-;{pF{=qC2P10W@lZ@ieC#VlUbq-SXVIwyG@?eV(#MA> zSOuUf#D3r1)lGfC1p56u-jP}cVe0ILQpb4=*+=pwwH5yue8r*&Y@w**eG6~qFGcv# zKLVsqeK9e|Ps4Hl5ftov1(nxN$#pQF%9<%jq7JydRZm=c5w$k5OKwfvJh63ioIF*Cp z@2dds^8ZBn+3uKvO3XL4nM zkBAC1p?(wEGZ9q8j27N6QU(8|`ozo-G=eX2)1ZaDf`}nG>?` z56KR^VVm6|rilow0zGxdpZ#`PDKWp6%yIt;38I7%bC3brjBiWdZRE@bLiA$w<`3jX z;XIf_nIx4RAA@VlQDiaH<^_N%Tg=PCi$0IQE}S;(D@RD&ZAw5E_7}-l4Q1oEFkT65l5izd`j-;mi6M5@M;M5QVV}GyAdnlJ61IP zd_VrbEh=44(vC#`5t`P{10j476by$l3>UymRs+bUA5Re^^jZ9kqWzJMZ zM*_Ug3H8tF-*3(N9?&kD_lAWIe$aZC22AyTThZ`4Xge^=sjn;=$D2P=MMJZD^L`L$ zP+a=@->*D>%D(vPmI>N36s{eZ35;k1Bx>koUtaw~=)t+)&k^CEY)SHm4@XvA8{)FE z?j`?-5itiN|B^3ucAa|}TY~qz&TmBLjQ;T?x4)nC5y#p%Ns5C^{=d@rG`j5TGwAeX zH^{#$?Ug?hRz7oSTq38DFy{}Z$?U zKw`6S%*ZCsQhACidF}e%xPb~wqmOII`jkTbIEi%pW!V1=nm<-P988nzY;85>WJx+B zvN2Th6XE7BivN!N`Evmy_*pYaGzRu~@6tcgFr%t6+3;TVi`^VuOvKwsx&va zAb=0NJWV~1r}o&FoN8j^s?a!JQzky@xOEm)fBN6BbKI@>EBIX{ImHr=`4>ZZ+4A3N z_n&d?VK9?`;{pEBsCu5S_(%KrclZABHF1=GW(eQ{M7HPCOa9UR|Gn9*#xVq@9eOd6 zWY|zdTp~uy)GF%q+9mf_K5!PK6>X8G`e!7QDJMNqE!0=^?n5Q1QA6_@$5}K4tF>Dy2c#RlXGi?iKqs5 zF9oP*s{Gg+peE63S?j(HD%?0ODWdKQR_~D>LO@enMW0za=lm*=-fx^+o};0jwqiCP z_&Wi45SFLdtZd`1s*G0D@@v$NCE{8qz0VrqVjJ9f#mKwd?5_rIRhTVl3rGg2iDenR zKIl7lEw1bPXDk@X*wzF&wxBo^p&2&74ZrKET*EKY#Qls+_+E~tYG1Kb=;Z6?Z9AoQ zM=ul<1>AN*^b*IL82^}XSKQjDAo0FHpI?zZIYeOed$o^*=(tmo9z{X3vap>Vux&;p z<*3`At>}x?an+Fck*r8=K4V9|;$dfC#_xM^d~f1X7zhsf&gsU5$>H*V;%aDt!^!u& zoGGR!RL2c1jq~{t__G+<=8SZb{^24WVt5pbi0LK&e9N?#I9J0W98T?x_MSTKMOu*f ze4zMr;A8@Fq;RveM=%#kOfn`(c?X_V+*EuPSz{h{syd#=k>^Kw{yLBNyYwSgj4WCT z?qy;J!9X|{&9iInwx%cgEn?a{Fg1-Iv`)V2?6sTdLShh>avuAyt6z6>@d`cR3&b`B z>8MMwmAuSyBX2$EyA2{rG=3spP};cU#z?27U{?zSE6Af9-aRGgpa22Z`n8G-#i6L% zFj#K*xr@hUk-rfi%AD#6*3>Ro&ENo(9zXd-5G6bcDenZvT_FsA60ssnotgW=^`VAZYq#9m8#y4Mk_t~7Ma`;#;CJ4io{py z1I`as_h}mDL&}xWV=-BDy)P@_66%v|9A0kuYW&lcspb_lL`xul0h&1*w`Ks%_Zx=? zs>GnM@EPa^|5pLxUi(2v%!bg|&1d*4nKI-WwNFsg9}HaAI@LwCD&Ta4;V56?X50?` zDOj*fLsVb6zx)BCTu-aIa?KedfG6(eUb(-em{+;&Vm)E^+LPq?UIcsP_9?g$$y~{l zmEXoeuykf}%fo~1y2q(5`TirJn~$p^pU`C=B}9>Cy2)MlK4huLV$*&Ol#!zh=3Dsp z5lSzz=SvyV!-9V2AcJ`^zNvGNNB)8ou$D^MceTaJs~uE4w@8Ey)|w4;Ka}W^39*Z| zIP!D}_RZlaCA(faC2HV*YXK@R9I6rV?0rdlx)el6pD32^SID#sI9S>Q0^l{F+}s;! z!V053*7_Ne79Jj-(rz_Q`mrsIw#PZCuQtDG#|#psh6N?wkuEml^vwHgL+85Pyi|X4 zG-TqVNy?lx%+?Q+Fm$x_Fsfi^2s_Og9(bw``{rPfg5CHy1wP=tSbz7vuwVn0D8TR(TKnts#nwEWm@W@PP;_V&(MR?uZ*Z;n=#p?u`fGQLRXtlGA3^I@yoA$+K# zEjb}&G2LcYK#dFAr1=m2LSp|9Ar|I#G6}Ysxp#mTU=*3jotqQo;QZ4Sud#Nijdvh` zYleWX{{7CBF!*h6lA#17E2~OZha{r+8Qmg3URUc-V7aUAM`D(+<)!c8G-Dmhc%Sey zhZg89MMgGljJ7K|&Erf@R*T7IMB>g}+)5{wIu;{Q3eZgLaDTK(S&_=GWg`I*aXPDJ zJ@O~G*HHNtRh*L4Ugqe|Xed*y%XnmxW^X*Yi&KDZp~Fw=8Xg!a#P{Z45LFTT2_CiA-wh%PqD_p7`HYL^Gpd&A%QjI3xt3X77xPYsY?R;!H`} zw#3YO5QN4+8$L2cC3-KT9p(Sr(IfR%DqKUI((%WHjfhRcBw{j|8RRVY#p&#dy^P9t zLm9=Xe9AW+%A&w8S)C=anFVee`M9s16K4h;2Vz2oeb$%$A=VrJv|UpHMG22hP+!t` zJeFlSo+5e2w}Szr#P|x?3T3p8ZHrdaB`;=2mcV;7&+$$V!JP$myvRYno=<^?&6z4V zwVQxfsLW7lsg2(}-t7CC7F;xsZ^Nk^{>|hx-06Hi9}2O*v(#m4N=L6qKS9-hfX;dG z`;v@^HZc{21HQz*k=#^;X51P|Zi7Dgr>Y2|EJ;T&xj!um!w?`=QrPz5CmsLv51oV_ zx?^}GWRpk%@6&K{1d%kKL1&TtN4=7VU#D+3i+Lz|$xgU?h8XU$Eu||?VlFO}J7B8{ z8{RFEu!0Zh)kg;M6`RWs*9E!7`!3}u4&7y*hijn{6oW_ z)v(*0-;Q!_I>!*-9+#doYT*ZjEq|?22 z=GE#IbmPO$X?NpUq%`~W9dr%0s_F~JE$PZ}c7vNu%C>u56!5BQg&A~pp2~em!s>p0 zZ6H=HL2GVK;&XECm=+U%de3OM_ta60hxZz18&X?F~dQZ`&@HykHf zB=BEbi{ICGA4XF!F75g@#QrB@d(8It3db5xa&98>*xi;-5&ClEF|dv)1?iUcdTocO z#BR9iSSDU)0Nz-=<@~HSE|igUJQFUiy>`AbDCToP`bnq_@5LwF^w7KMcnZUYI8DFC zh+VXBMsB2@Vvid<`B|s$^(z)UR!x!E4&}yA43TkRjNI=%iFj`=k*Kd+kGbVG$ z$>{D#IAdD@gh0GG5GsbtQN162ytgIScB~NDA z8x+y8(&os|W4%na#`u*(r*{h|_V8h5 zE!StS8d{e~f}7siYC>Xrn{7B-55|^|NjJ5C4R(Ju(@-&FN+<}Ad)Joxp;rt0LG{+Q zcwc+cm(W}>5s_%gukHzF-r9dpP{C;24|D8p9V zzlRL8B(hr##hL2qJTBenU>N*@OVlLgp2mAIVHWe#?P*pSXZ6H=rWY2nxx)8+Sp6sQ zh|7I#R?n{e>d(<641!&Q&P&gHYih-IFd1WWGZht3{otio9a`>4KjOQ>p*LFTw9pk3 z9q)&y%44LKMM*3kJrM(CullD%OQSeM4DYAk>twR?s`q@W*K9-MaeGUy(VLpZiWY?yZ1;hI~KnyLyLeZ)BSf(N+U zU#+SSg!7%dR;#^POx-ghw_8jpv!C`~XS@iZqXakra**n@9w;_84(9oFFb6v;SO2nCt8Bm212y@lLm zb;>nn_<~s$hEoC@`Q(U8>YqHiwEc5=VzAsDSw#)I-@gGazP(!NN+y#rNQhYteH2H4 zl>HYmoMKz+;srA{ktg(pd3YR}`!oSQ!&)eF%aQs0$1PRLOhzkGAFjCzi1;H`N3c>w z`g>7h4%C;w+3HH}X5xY?s4+>7?rW#XzOD88@A=Y%oi2G2-#qHf{6UX`B7W#3l=jAe zS{eY71IB-G?~twmB9PoJ(Q3riMY0Xr?Z)2#BYbWuB1U6DJA8#j)Qb0xu0!U&Bpzn1 zG}Wr!KwR4_LhXm&t&Uwyd;bc_o=Sam6VPe!by6S2O%|i=92o_eo5f>wmZ%*TYAb6Qp%}H?53rEw9Y|9Dcj-I4bjEYl(|h zv(Bn^ltKgRzGrFk09`@l{flD933y{SSI2L#hDBi;B6|DFSj_1_A>S2Cm`set8EZCE z+Tuh^+Pde?mtVHbrhm`NN#nh5y@(6*C1!@E@vr(-Yi3;3M1sL}Q_NE(9B`wmL z5*N*=@n*mgAHjiaC+DSE%m{7|#~+u%$V{241~0d}3XW2{KVz+Wli%G&qklGGC+5IS zD1Y4>&X*3Vq=%z^UAIsw6F!u(nAQEj0)2So13qs=dP z-*EAetl&WkRGS7BJ`up8Cu7j&nfjb*}te9-u%Sx7iToj41KcksW^ z8Q;X!ANsC1(MGTB=6Kwx8uYI#kYOPk>f%G)#Rw`A zmM7`R>!X2duB!65WsxH<5rU+3L~Jr!Q?=3l7waP}!d-QmBnJmS{VL$rAgg5#VYTG> zP@{REWf_}3CuLtH)5djm1k^(>DDU2D|{h zUxB^4!ag@wv;}Be-}fb7bLOh3C=mPkk{mzOSK2uV@-Lwh-z$pO*wvP5K+J0{eR+OBK!{qIVbuI#2)vf0B$w2n75j9$X#iy)5?@bsqfG zN$2_9=AsQ=Q#eA1twoK_a-c9nt7)PIFKaQq|L859Hi8T!T6>b{`_84y251PysO0a3-~9DrHq{#-#lL5@l7-^g3n zrHwmdK^8moib@Stwt~~5{G!CDGz>F+U!G;}iO9cTe7uX>P#^1aI) zp=?D%7Jf&<{FyP5idb@?s$zftlMVimyU)5aef3t?ye~_i8!ltNfE45(Iru6&7cN9p zHL2{6;7)Uf@kYBzwm+G{x#WhZXkC`G=wzvepePKWOF_tpD(bly*i4pHbxg<8_( z7Vv^#xt0ZuP{Zbja8Mu{erd+_!S(78cepGsb# zl0BK@=Vv^?@q#Xw`%-~35Vy3qrTDALi0r+dw-&wlp zw%HO_4c2nA<-wUZ*>Qbh1y$Gyyj6($YP*L+lZ?likpWp-?_#6N5Kd=rRh7;X;O*}| z|C!$Y9VelE`X0)(Om))nawb>H-%_OIGXU2PDx{TPyck&^KzA(+jBNEBIs{lK*+a#< zJk7)Sz*JWn<|iiVc{dLoZrwYpJ~v(e7ZA@Gyz0=UusneEs-K9(&4-TZnAGHeaM zm~P2RPk!8)Zp5(nBeeRKJDAumBPCD0qlj%1Mg8HI4@3B2QcSPT%V)Z6Hsv(%su9IozEL9)}&kSH4*t3B?$BlAGS_+_g8_R?)_5 zH%Jjq=^aCxTM^b2i6Nho{t7m%{neVn&0uo2CwGp5ib(D@+htU&vqkR)mRN#vQr!~> z^cSA>YowiHOv8I+VY@4(otgowNBYMJ+`+JcT_mEO4^P;__5q&%m%fdPXtF;4(?vr1yT~DF5rG8^|s{ zQrvA<_8azp|2q3Yp3iZ&HLxxzv?z&F&u7L95xTxU@cMT(?&CatY+6*jAIJF=J7F1} zsjHp`4fE|`cwzMV^iw=hDqV!Q;f!z;d6spnO&@@NabWe4x|lMQh)`pOnwDe*v<1sm zG#yVzom4PvB)@a^e=2H<+?ALPtU8ZEo*9wW^@^8aZsQ@>ffFY*@?88atc|eKnFw*@ z`%Y*}IM#}m_bR+IE|j7k7yJ5N>9p<$7f4Ii69w~L%SODKuCNjbGxS7wS-c$t&|*p? zD52PKWyd4*(?XWQ>cAY)meSRUpP91Jk9`BBd`?G7rwYl_)m1=C_ASiTe(wf1wrT0m z;FlP!q~=*J)qwlxSf8~!KE5kkkWA@@>5MT&|5F-vcHnaC_`8oE24gZ607S-4Hk zbo)cOj*8P-<|Qei$ord$s>?CufQHzMR$bSP3D&KOxh#do)Nc=b;|Ub<^{ph@y3IP% zj%!L)L5IJWGm3VaaB-x#Ke_FeSL8E8#W!DgYE9aEH-wIGnlzhcSCo)R>RQh{HGtTw zRQNmTr!Te40=k<&!c|PM5Al3vNIky0^xwL_<-&#z+I0CsC2X~{)n=f6@^!d!0OsT* z?4ow+utdVWE{Rc94ZAbtqVznJyW%v}wa_vKv9~0r^3mxfhm;Cl#E^e{6ckzdwE2MUAcQ!4^mOdCJ?4@2!rXu7{BAjeVvJAvvRy_v^!_B z4FJZ7?^eI*axV2$)=z&$O2VKwCvLd5m=j|7&)nO^Ztw3BVfr#rd8|I2gtfm63=COa zD=bbwftj~aUqmmzXQH-ua>zGOcRJJ4sdo8MK>l4j9%ZPXtbzu(r|ug>8q#^F*~a2iCp?MEHe!ZZCt2d@!o zH~Q)bDe7CW5CV(PK34QmlFpLI@bGBp#+s?kMt0uIp#?!&WA7G_olmQ?*I~HraB}4G)wezTEV$%;U&m>k_;w}l2QL0jL0i03RZz5U(5qpR!f0~3s0B}>+Per*0{JsLCpMX zoy8aI2JwiJHVA#C{oghhmg7P(NgHoG@xxZz-rFigiy?RVetHK{KjO~ak}l6LIYbUi z$)z&eLIgm)lzEo@BBvV%wmi+O?oI#y*z&s6?TtYoslm($;PrTPGpXxt`BX&K2f{^1 z@+6N4!0m^8jo5VIvBj&*t3t$^#+x_vTXzb6TSd@`Ug65!0tFEoBQa^t&#w_Q9X=E; zYkmOYO}BH8H%z)@&{0q!aK-C0F|is{pIR#4*E@%*L9i+q`7Ym{!5IG;6<<+f-XYm% z|2{t7a#6V&t!4-72O;X7lCxRj<*V<)tE0y+spD`Y8c?n}CM71g+uHxKavV#obEd|p zuzDsUZ?yrn|1cJnO$?vCc3nJwEHzFm9v^OOrz1grA<#6HznN+yHYW|C?-2JW+-;!A z=%?Y~!FxMVXGAW!@M7gsYXRGxbNrl>-yor&C)s58boWcEVJ($+%6vTRp&y8k8FUD#a4NpeW>c<8 z%j?q`Ky<94?Z0{%)i~m2Hfy=oME3u&_m)vrbzKi6C|#{F@}{ddQ>>xaVGoW0jxYp%KGeCG4)T|PF{NmPLJ zy=Oq>;A46#A%NXm%FYJe`Xn?s#n@3de9>yHPxz!Mw4Tx8z(FFPLCYjb3Z0rV5g}PI z$+*c2?umR=!BaQM=r6d@LCm=sg-ka{uli6*A3IBld6GU10B9gZ_m)Z?%{PC2s zP7f@BC35#m+7zFgBvrSU)Y#V@OFJgI_PTG2It@Qh=V>+VK%HYFL}IM2KK|lFq}biG z29RuNny?PvTf4W-^H&*~W^+N2$%(|qcX?-r*PpX)gyrgJd^GF7IdD4G)^cuPR@0Sl zTZJKFcSh06LB+^Zq#}V97CTVew9Q7R=+pPk^O5qvnOn=&?)BH=)LD&Bzkh`jP+0o( zPDO;ol29&E0}8P(&XX#pHXz9GPS<|w=`JMe{W%TVIc`b(g>EBU`Or+zg3)Ixr z`9tzn?WWAldKwkD_3)6etzF93S2qXjJ^`CkwBNt+SX@Ll6@qUce=pg!)k-XM%dUFx zC$idBZEO7z^!ZwYXM<0$ET!gMokws-yUJ9B3=&_Jg;-$$7S`M+he#T>m-K0;0y1Su z!u5F$_QlsC$G#tZN4jmcF)&|pHuK!RGHj=D4h+?jKduEY)REEE+sK|n_ z$M(&C!qVEsTPyNQ^Oc0#5?e}EoL$>f4Lc8#ImS0TdskMm#E{^2>7Z_HDf-t{}M4+ zVI^Guk_}C;VqIoJ(wW8xQGBHm3&g#H33e0rQ*iJeyUlvt*Ky9ve%O$R=k{(N8&Hzm z-QXK4#f$yaejdLSdK4j0fV}R9_zj+rKWj!q^krt$jPM%TZgbS?-N3Lj#?xi_teFP< zroIyO6>Z=j2THWH?Ki*ZnAK>n*mt8o@S?QFXjKemCtOP(3W;7Y z<=Tq@5XEv#(qDU0W-B` z3rDb~iR=neZd#o(r9F9?99C1w0Ylnu&c>dFDHwQT))LM4gkm?D)-JF2FRqMg`*_B`);! zjPpER)X{sV7c!V_n2P}}?!IJ|a%geyojQ}FvM0Qa(mos$I)7@d7T%!4Wnbs!wKQgrVdVvDWeqIqk)pX42CIj;z(>GQ0qBa&PdD?7eXObP zgJU!xAGJA@gE-Oof7dt24QddMj=C$LD*EmSTl0YH2v4z)EBtZ#IPjSzS-LyF!5#&5!dNsTU z^nX(FULL?*>rH_9w2lRA>j}E@Q@p%3j9DJxTVwuAquVs?saokYVVqCaW>W_^v)MkM ztZ2qYsg`s#s|b^5+9^?(X4f#WOUe8V_Yu>J$Qkiy_{QI{!UfixUYdz~Obfm=cow-v z&L+Rcv9mcs0-XM`-^ zmpBse*kGLiV&XfZH_1MHRv7RL?=?3Of$vR_75wM7QE=0cHWCzZ@dGI2G)q0~=d#o> zXBC((0xx|@d#*(e;*MiYYvpqw#QLYX`hgOnE0uOxSkNsysC~4r8<*)(v%(4EI^awG zj^*+`=<9UWjngkQ%HoxhO{g3$Mv?diNEEy6MBMRIaTL^Z2oStm<;EP^H!+@dJ4b0xYQ6^WEhrXJer$NlJHw*OjIa3gr3>c4_S?Q&{n{AT zZviykMlySA4!lUF|Kl1~X+FdN+VT(pUg%uxD69;w=DrcU1_Sx^2g`ewk*73gO>G~x6@POvf)xw96ZROnUh}TK8Cr^ws!kb6 zGqR5E@@23EUq$b=|&)Ze*I+hMJi#%?>lR>kSQyY|saJRez3<5KNry%_ehTf&rwdI_5g=1h0hO&po|^*L52QnXsAtptipbHCbzu43 z=+Zb;g1BGL%xn0(^(&lVO()x9F7?z6m)D4|Ajga%&lm0MT%R_{LL{G>L?b+Zy+DbS zcJWdn3-N%skuZ%F03f$ZF9Cly2T=pt@nX)73bnSh+Ujp4I_Y*R%TAh+l89aP9v}y) zcUDj8zfaTh^GPGh<73;RNfnlh;yQu;2}qxN>-%# z-yX@>Yr;L$M@XB0RNP)KL?IR}U#tSo>#z3vcjMz*%lBe1%ihiW3UXD;XzK(olXgbZ zgjb>vn6mYyGN;KecoQhqxCC9TDVL;NSEkVVF37J4)r?@aR)SvDpN4y@+4hC{<9iNx z6>y^Nc?nP3MEqS$L=Ve3ov(;0q1x@F@+p%!is~tBpWwQh;SC%ul`yn=pU~r&fe1p? zb*ExFz=An8ztl`IUR6lPr8Os)N<^+ImakMzr2qE#5(>Ctw6%>+jGw;inJ*F6H2#dj z_qs{VWV_F;GePkZngG%Hb zkf)KScA_H=JC59lkx#l2`VL163XL;Wn$GsaM3i~Hq{&tip}#jq#!aGe)SvltA9{(&76`$~{m);CA`T+NJ3H2ft?C7>7&9noA z;o~z65Ra}%%Sz@gq^(OT%8WX=sH;E&Tsz2ct??X$o4&s%v-aQu0l}DgwcxyA4r!e> ztarsPo<5x2yXIsAQz39y!C+UYb2#Yp;*Cb;uyV)4ZXWhId|hvk_pj?8d)t-9Jrc4BTQ=T&kZ%^Y_AyW~#!?X56r|>xcIO zRA({t6fe;C;YocNp$zK2GhNmUlB*!kEqmMQqI(p%{kf@4ZFt~LD3ZpnW-9mvRDTR- z@1F6-h3pDYt6j!;Qll*Kzc^jpk(1(zoFuT>FXd5FJn3Fq<#XbV?OAzBD@|IDzK_re z`L}pdl|xZ*ixoi_pjmVb(P)OuB)$)7rTQz>GxCf@4zQxbLXGiAPMb-;-|89-`;oJdpAZCU=AhEn$vw~fCo`)6 zaAwBVmji}$AdosKL{U2p{q?b{!W(|pZM1a?iSqHTB7B40iN1|5lqN!Li-_aBn6tpf4d_W6{T&~oMR>u*rlUhea+1Ii<|*?IafN)g3AY3#)zQj_?8UlVakiTY-fT2`-lfA#?#Ah%hzA+J5K?lgUz|n5bJ=Ff@Zm{6&qIiK|pb|Q*ujyU@rwGlg zPEL85XrCrq%hQ4I=EiH#bNPFBe?~b;rP1M?_;@~`_m`vKRZ}s^1x)CB@XYV$ku+=L zB@QgOYH|kT79Ykp&QS^##M!K#!>dLZ-HRj2;{M$!T*DvCKq8aG#Q>#l(LHU3{)g`m z@#2hmtLWCLX(E+cH)TZ~1ILrO$YQ+bTwmz79DaTpNIDgB?INR^4?SFNf(r9~psS~? z1*!NNoqhEaR5d5&KFiDv=j+f3Lp}_+_`P6tdy+>j3B^gV;eqc3O>rOt1S*80z$9eC<|ZMupGEf{u{ZPuB|V9KICGt@Ahzqm&!hQFiTG z_UPD!N&1)TYFs!MoiG`5O6E>TkT zOB_JmO}?AO!$LmH(J*;Pe$*%&ajrxe($(onmk`mOz%Y5qWTAN}K|6P|Bq5J2VDG}= z#G^_ZKM|(U->^-s=_@S8w9uec?KE17Xq+5=xU;->DKdXs@Em!X9~q?Ed8?N-uQ)Ug z)Rgl)nccXS#%AQfBz0f&q(@8(&y=rGj!qE4+w9N1Q+{6-{%aPUz zLvEbZEjpT$E*&L(9@D744mku$DQ zMLKhsOQ!Z!e!lNaZaHIZ&x6N+Myf06%;GRTp47Me0P7`eIhEGkhMxLXkwFrycf9^w z%*whAlD7vvH*e)?kK-06p2CadfljjRsB)^ha2Ji{0==V{5nImi*03G4$I~Et7fOY; zD|(5S@_GrMAA%%GK$a7S)TRMHZr+-(U!!5Yn()g`j(;Lg5xvUF1SRC5Z%2IZ{^Wes zfe%YfhQv~{?z8l_1?!sRDGl2ZX-M4ojgU4X=9t{h6}_G0Ae z_we&So3|*Yb>}f9EC>pV;e38M2RLk8%=OU%Kj%Hd^V-J-BhixOkr)_ExjDI0D_&?Y zff%Z2q|@jT(^xc27QIGier@bCqJoD_kQOI^87hTYIi2cdkmK!BJ`AUm6K*h%mspDr zCZD(n)Stb=%o>6;a}7wMm3%cJzxZ%}E_yK0s-X#X>@b$yWSwn+!taMCoc&yMZ;Q;qmh1%+d_L7&nln-?}bj)sB@b)1nFCs1O;9k(tf=@ctkjpl6d)0}c?+0Cyp|dv0jO1`i(_B*;ml%mBWc|A-;1JNJ0ZT7EZ7jWFTpD z(+pL>V!P{3*lyC)K24)hIk~f8=hu}{9Mf7Ac?7@|z3Yf3bAD=lt$N_s4Vo2%-7`Mf zwAbqxTF{}VrezB2jk%^0z4IEPSJMMq0ARm~E|j*$%QQWZX=En|$Djqa`PJ^WWY zMDhd87&CKN^aL2fZhP>h8S2m;8w8p1*hU%3)L>h4%U z{m-@PT%@q!jxM2WCzWKE0{bJM&mMjr5s!1Wpv1||1>g;RNQ}Nq5+dMTPQxQ8!b{y5 zz~6m<4!jczpkllBV;$I!3b8U!(xh#b7A;$R1o^VJ_Z#o*)?}9tJFum3S?(PKAWnP5 zSVx1u18Kto5p|C&x619sHT6I|0=Vp0mA+OS_|>k2_4G-!UYBPM-^tYu(^e5DZTOz@ zFgz++uH-#wjkD1?%GrCjY(}&^37}gh=jHbv@`b=#l_*T)Cd(dJJoY4BxU$&>`s7m%^<(6B_qI*dLw< znL8h)#;jS`T;T!C==8=M7t=n4a>IU5+p-ke3B-4@5S2$Ce-taCNLBM7pzc%r=)Euy zXIy&fxuOoD)@Nf;ZyF}r?vztnpMqDAJ~Y|ZaZ={{bM0DJ^3Qp-fVa#UZb%dItiVVQ zNJiv_Np^h!Gua5u@IfyDr+*&OkdO5)igwU>-yg6fBja$*rhn6!OSs9jVWBN0IYRe9M%a^O8NyCx;jEaY zyblcs?qqB-T|nvaEE>~Xa`j{dJvd}T+MT!kNG}1&%5(Z!@Lr5x#JLQqH7&bt!cqq~ z$LOdq4dj9JJSrdz4Z-oOx}L<|qzm_vDWakaw)&>&q^l>rT)~jTDe>iyE-fxPR1`n- zaCrSv-Fy_DKiSSJxc2O3#+=G1Ts^!T=#QtjmME%6eRQe2-Vgj>+>QLDgLQQDT&|E# zLA=859g{*kGOub^Tijl=mq2SomW@;B9{iXZf@M@;%@y1Kt}O%`l}fJfKC6ny|!*`%>N?bO>T4dAh+{r8->r zpShp|4g+TE`TMIXSoxcijBNglSAY{v^?|ltws2M&&smU_;A$BN>5NnG6u@2+sbw>N z@OmmQ|Kkl_2BdIcq3yB+M$AQ%YdRk|VEQbZ?dnhaC2G`8&Am^;wu)CDD3Icw_wX!- zSnrKPdfy~d7#gk@zEkKdCob}!{&2~XlfL?!cs);1UAhXh5)JOLSq9np;vK?!C#(on zhq(r$%MOR6-(v-JcHeF?Hi0Tba{E-Qhw`b@K>hQLH$wCyquP%p95xKkd8d$8U0mTJq9#L)&c!5nkXL5;a_7pkU7E>pabDg<^9{hai?}|k zf+Sd$<(_W|2_pcZBbWSlAhJlX%8*rlhh9iAG<^l6y==#~tX~ePRBH4u{LQ^#URw}- z%}GyFnr7hA*VGxc$H=UN2ikAlNyTr-9ACP>A~OU29!SarS0sTDMrl&Y^C$-0X}Gr5 z;>(x}1C#uxfku}{YO)E!R>F_W9+c!Txjo*z3O%D?q#7yjwXx;Y5Y-^wJso%QEzq=GAM?A z0h{ysf;yG^1vR0wZBzl#4%pplG#o+4i}TpK=OVHyzdSXnv)b1zUNVs)7dQ(#?6Jl9 z(QEi+ycIN+#((9#iE^~IL+Y4p5r7FZHgp&YswOFPx@+$t4vE6&dkx5-44J{G?)0{& zVXPho=w>A3g)?(J*DJTBV8YrOZbbfaKJoXT{}DH49<>Oj9ZMw&`brq?yqhqPrA+W zzOjBgnaA)$3?AQuse$_2pR~x8p&)_e;K-o}DoC>K%`1liUkY>#xb*t=HINB7F;&9Q z>#x$!fk?BjnVsMYNT!T}GuE4B<&Tb9(dT%yTg$^W(bOP7U+*x3JZT`wWwn7|?0rcqUy3EP{+}hIAE~89mtifPPG20H768lT>(S zitwO1T3hPFS4BmqWU250TIZJE%*WT-n@w=};}#dKmCpRWh@$O#3Kt;j$rk7J7PHIJ zZRgEk0nC5#jss>aVSjq9{u74s9g*e6D~lkYQZgqN0jl6nmn+~I2YYV$bB+yilQM(5 zc`>XC;#8Q`svph}c7ORpGY-)40nVzVrUD*Azgc?2$f5ppq#^VlnK2;E2+Riwyca3X z=wN}w&Up7|2huB4vQ{<%MtPT8dCd8}4HTIO?r~AbIWYK(d`wW(_JFnmW?1{K-yKS- zYJLnW+tLahHlNx^h z{}5@dWOh>k&>@#yd}%uKdMVeLB5%5?P}#eXN6mnT#Il5mwUzo<8s8f7l1c8adtC6W z0BJ&~azQ+Vbr%#1&cf9W!^&hSOV>I$ZIUk6f-Sr-AIgN0b1;DD3fR#7pa`UPQg?od z_pA1!w(8(c-KmvviC4J$(K4jtDEPAJOvDUmkYOITe&yrY5#m|rD=re4k^oOexa@Rr z-ly|3g2DOFAQ1YO3$Q|HQYfxi8V6~)G)Dmyo3Ue+U;busoGIOB;hc5^&;LXN=GXT@ zu+JQX&HDU-WZ}zjpW5r%SM_@V1Ddt&qq{gfpZCq*q+EZT1SCJ6xoeKe@YbQOiytPF zsmbvc=p}GZgO$tH)0#7~Ck$UsckEsFfS{V^Hk^Obe8F7zh7-s4Ne{Jl^>R(mhUM%o zZW$#;-7l%8`rmvZ_jf-UVVyU$an{ZUdSHYf{f?yi{R}G8Y4oMR_r!|;vpACO=vM+U zb0G76^XE`Qg6ko_0nhKbVi{=9is6RdG67K0jS+Xh83m9*54@h0aU)cpY9W&2p?2B6 z2+F0MdgZXT^r-2SKI9joaTV_m`xhT;$|n2PL0u@8?edz=xMwB7UXM|S!4cR+6b#`$N@PPd*p0RkhaL;HJ`*w@G z47Yhl7|n2vtCztQp&J85z*YR{&eh%HFkNEQeYIrz^6mWHt#oq%;IiZH&Ym4cs%5(@ zx15FutFQl_*|I2VhH^k23h^C7*bOk2k&_k3Co`~dv-%!{3EVO5olsBA@!Odz@Z`CN zw(U~hTp%hmDXZPIGWWPk`hkIeal`-3b{hTB?K8K^k(;rh5zYzQx&E{8&JR`Wf_222 zo?a0268i#zH_Ej6Y&X!g7LAgwj@7IRTetEf+WzVAi6c;11cYx@G% zYO`zb6Wj+QI*h0Y6ayv$n9@ZCL0fJ5n!Znna14p<-Lq`Yk+gGBWOGr~h1ts&B_8Yp zx0$quyF60`*^SpHcLP@3(l=X54$1OcS3Ir8Rkp42$nxpbcb?Rmy_%><_1bja$0)K2>smG=)ABP1M?`el?z!;C@T?UBel-m%tN_MR~;clBkw78g-zzej)2 zttE%Yul}%NHN-}f?Q-H%GhH*o9!(l@R{TkjUl(6FXhsbanob{inCFVmk@XOpo}3Zs ztEHSbEqjSDLmrxp3mmPtLs6WzhIe_$)EuiNjwE4Sqey*K_UZ3q^j6df`HU|o<;t1z z;k9O2FvgDb8$ZfFNpUa775j3FiX0qH?vShD+-D;&^?4IrS*1oX7oNDg@)9hJ>N}m8 z>{;wPS#s2*-#R&%Um6%{UF63{5M4=?+ESYgv_22B+zxVUVD-#7=55qRuhpI#a7KMh z8|)&#Qy+o0w4gY}{BwlJYHW_2x|Yop2bKHUj|j_ds$SU9Lh$k7j+_xm-f2=RpNRNH z^!~2Y2>e-Z?aepIX}S-a904hpHqu=0(b6nfKk$awVxMc}v3+#I-RV&fNQDI5!w-z?=H}|FIg>j9lRv&u(j&vmS%4#+u zX>^|+&s>2{Sor&z#WM3g(`qW2*}X)Q=5R?QO6M1-QYGq+_#Ia%btkF)#vbOe|YiCrtkwqiB ztgHUj5Qn?hR)YJ-y;$;{%a*s?Hqy1hip!7KU3hW=Tjok9B^(@Wr=!gAU4Qp1g@oKF zYRr13|Fr*rey891CQvW>wuM=j`?UBj*fGwTto~cJ$id#kESBSsx}>Y1GATk8m)OMW z-{zh>PENlqBmzC>9lCm4o4$}IbBq?`5*Pip+8A_~c^EN`f{K|gz4pnL!!xtvjvt31 zD;LROKGeK;FIjOW1y^<_PCuS;uKb*M#BFPw+C8Fp?y(j%SN_@aF4Sl1fWBbpBx^#t z%53Grtu*gzmw5K3uj}PPv)G8@-8Hj2X~`>I^(JMCP5k@y$$+ zS}CsSnjHF!Ej03P31>KAjpwY)%IDP&Taj&O8)=MAe9HWu{> z!G$stCpNgqd6UUe+t;eA`Hd0$w=|}g@w<+nRDw3cqONP`TlM!Q*Ncxe1lNrde_~2H zSoHSgwK2Oin(Y3%P3G_@s}T8W(WuMsvpO!FkxT!+uw~&WI?G59&+|?Che6ql$~-YT z%b(1T2=7z_Q(USv!!)miDR@h9Mwsn)kNSyOncoqOZSTY-s1dSOE944FFk0_?&$M(s zzLUbLn3_vB!;wTKmd;aQn3`9QP;A%t=MohZNj$p@ck>`z`AB9Yk{SHQqS`)sC0fUf zqM$x#YUaE(lecsjRh<4Vm3RDjG4dH$dqyG|yNhx14E7sd;ay4je!M%=SGftLmu{L; zBsinJ`E}1N$ylqkt`5h38>l??oGtXv-@;+lT$o&4{#jw?N1`l++04bb1zMyfF+XC;9;L=6?FJ zSfrSM)FA5Tc2nc3lhIn+Tr;E0;nmRD&ixTura=9$w_3?sw#(n^XG63S3q_lXtMz+G*RO>Il;BFbpI zyA#N9I_XDsykZsNkMUK9$%jA8bo@$H>mD>Wh&FZufH`0RlZ?Y@nj$j zpK~c|(gMCiJ|+Fs{o~w_^9ib$10(r+Oe8X8xj?=geB#yhjq* z?108gwoHM+!CgBsAjQgaj;_K#zs%NDeC%=@y_xg+m`PI6^TLiW$)!RVLr_-pW?t37 zy1&@uQCBspCfBo>An?}GWd{RV3Ikfgrdsh_v>KD1P~_c(m`E3RWV3kxv|&Q4>Cy5} z8jWu?iFZl3amMvm4rSG?`Tg8*CTm&MBZa3XEo8RPYE3SMG^D_b>r=Aq0@dx0oCVY` z-c*|^%Z+{S#~B9Wyq*6hnPXP2lI~3kIk$^ftQ<3mrpJPYYUv7V(~Aqk#%<&GuUuE5 z`1WU(cJoct)fp>5^t0O`ZQT0lpI8+=;ZKtT8Y)Z&YP+N$@?xGlq zwzEK^RjQ)feLqK>1iHxSsUV@4RO{uTPBQ`Fu>cq>;C6T{8yWL0-wje%`7Yh1n46s1 zOY~e+&m8oI;80*m5W1uR1u^Tx%;C*OMq+7P4cX8c?))CZPUcLAkT0-~{Thj36Pj!~ zzNtxxdY~#J5A7FRF0nM(lK?PQHIoNp!4b3M?oy5WsN2aw799`9jC&}@w|@-8Tey3b zkXLPBOLfNa&H?gd#ujWah-z3O#1rvxuO^)3aD%T?$O78HZI1p@i z=ab~!y!eYX{S9GXJC02*I;*U2>EZF>%k#*$elcY^Fd0aJN8S5C{{pvf@G*-6W6p_4 zqDL)SX||BMXi!)-P8IoZ4;_9tVh@33)0^z&_98VmB=HvP{fzvbwcZ~$Yxy||hi#te z(<#2!HHMST?4?3C;|}D;9eCVW6QdJ|Saz}6+gAIO6fr8Ekv93MThR;>(uBA0XBK@0 z`hrqH)8oe^xYGSuFbTvVCT45}N0sFXaN55=RK-qm#;Lk{Z4Xmpp4BoWOCqrHzEIPc z@zN?@5`M8c9=*x@XejJGiwj9XIdge} z1`dkg?#VOfIDB;K*pfw$_jP@;BB`yv6yLna6Jx44UN(X^n*{J(OkWbie%;p5M%f}mhsIRJ~Qg@4s$<4u5ANzEh z0o5Zhr)0%fU~F~8HW|>xl`HB}V$qU&`LhqHfvIYiF-@UNp&!5B7{&p$>Dwzz2dvPA zkeLPVT)y6DD6TD`pyQYf9ial9W%2xdD&MHbxo3MM)~SJ7ikL9ChwMR%yaN8g_Xcq( z32I`&tei*z8mjGGK+{@+liyZ=e61z*@@GN5;ZZf=lllsnl)VhfMgywEs&AT4iu(>e z2JBEy?@>%^sQu!=fQm?s~eZB|~2ZPqNIN!WHPbPn|CsT?$!ul-*nUY)iP^=_L zlLh}+YupZh9YC1>^atJI@uPo!`uCq-K>&LEuX#(u(f;=v1maE#p4k0gTg3pSKnT?! zLz7{T^8ot)4z*DUjlw{@k&r*dO3Sjnjn(=474PcLieMn9XmD*~2-j!dqf-6vJAByy zlZ2#oJSXfj?7?JG`oB4(<`#pl_H)7qPvPI78JyKy>=oz{AAI%M#?+*onxlppor)iL z{O6x0WBSnlyr&c2O6om^XJ-BTWTFfIyCmyqEdj)vsrn4_+lX3!Hf&VwWwnrqY@-%; zVc6a8iW6>W;2{<2#r~cSq5%7F!~OP4^uu}8jW5B-jwB!jfEb|U@XAjA8Pzd%Jv%uO#}Kb-g9=3O29FbAym zduxvMHL{0He-A*)1pc|3$gv4Y`^x`)s4WwzXU$^u*?5$&ePBlLN-!Y9KzGiUZ zw8;9J^ohsn_O@R5FaEm_0w0(q_c%giXi#HgEa4XWd(;B{W=ZYO6a)^KlC!adUq{sN zxW}?8Mby5D+tmNhFibEXwlO_FFtpT9C1=gd%CUmxklt&|)uii9%bC5+vtUv=JpNxN zWZ*5z;lViA=0ldK{`cwhi^}Eyo$=w*BCP)hw)VfTLsB2^`oDJhU~&JoHgaF=|9*o& zcpi-FzxMye%>VoL|9@#P7XSZ%gF*QJkeT_of+Tm!0CzlRXaaAMiLBFJ`_%a4gpttA zH4_Pb8R=iIXjV)eF-3g#TSC3V&TxoR+hl_H%Sw6{Mv0tZ+qEIy`1$@i-YlE^bQAIx zr^C5LcoWqWJfzL6bC=XR!0>~awe-%sW+xI{QtYh@S4!*_9*3>LSB+Q%-hUTQwSv85 zwHmx7ax_j=98K4T^ZV!mnCV)bysVUE7qTB$6`N*XMBPc zG}6lZ1XHxNNiJOx{#Cf&XRA!#mwFC~va({CslWW^+-)4StM5-IPNyq2XH&9Mb84xe z2!#q*Wi2lPoaVOj#mi}wr^PvtU?HQuz;T$c1(2YkNtxW7Bf|R)cu|;G511S-BL{yH zXU#+Vx395_iSuuIPVVD4_7Tqf{0ldN!m#;R*}}3l=oHSI+<9Iv81*5xouJT7nS2C$ zdfHlCPGNiT*9w|@#NDvrEDjENycedWdWQd=%{krIJpX5W1&Y^*4T>NV?#5xw<5lUt z8Wx`Ef|3#g)sU>r%;E~dFw{rWoShM_oUdG=^rvQ9Is(kd!nYH5l-zfdNdz;6PA+`H zz>|%Be16oF5qaDoj~m4Ss%9o1%k#2*4)T!5l-K25u*9oQA2uNw?J$Y##WK>IeRKDA zREm*u623F%@lk)Y{bf6wBW?GOn)3SV#Z$$|Z3V`-;|p3dxxCj-GkJyFzZYlj_uXoC z54}F}dmU|Hh#CIYJoKsd29agJx(hW_q??-zP;H z1T3WJiK&j!MGg5WGZ=4IMwA`D)*4}A&%?LEog=ls_720$dN!eFK_i4y(if7`q()n*)^|xH<`zzb6a64Ut>v$ds>T|F!Fe#JP=l;R-$vX zaixi$_-bgM9y~JUIZE91XenwzD`x@kP2zfjbo5L#fl6pmP4VH4LURZRM{Er#aI2=q zBG0*vt!hNcrOpOy2C0+~Ak|nQYS&w>Txrstmw5g#^j=;e!Zb@YwSvZh%y@WxG1bcd zY=%^Z^H$@X@u9)$!qsXnE-Cr!?{dCiM3D>HSxNAUTTc;7{*D^PWEhT`3Fi>TMHHSg@kHLc@1V;n6LYjw-i@l9~Ox>2b<>hXm0mP8X9$>_Zl#7rk~swBg~FpUI}{RaoFW3A35{y z6Xp*D(1KY%wHMeLb|`m&RmmkK5huPrGha=hTue-LAZCa3mL$hf9ZbO%WxHgqG$z3+oi= zh{)GqJ;pR-!Q>5=Hi)+(Ehfv<(la`@<(!t|@vVPP1(_~AdG%r_SIlteh-;_Mc(YL9 znG7e0j96aJu$~SE@kmP6YP{uLbCGL#Iw>!0Df34D&i6H>NGS|T8SB)a65IdnBK^s~ z=W4r-9%8?4A9+8JVE02KxTL}42?3!T8Msx##2>q6=;m~)<2&h9w*JRBT#zD-w;0oR zBDMLs)>`}frm6wtGwOq}@j1En97W|vN*fhPBu~=HXKQlZh!RFioBO=XrF+g!GgHHr z%l`&-q2JHAxLw@&?~g4@4)woCCyASy)yQo0d+)w7k%i}cjB)LBxRj%QUPX=fR*|BC z!-c1K#A`n*g{$S|%!n!igsS5VB{a0g)S^l;O7_qel4j(2dcxRzG__Yq**M>Qf!xIc5NGIUBQfy zl%HR@b?K`HkZ3kGt9sq`LA9|f>I@dT-*_B_TTjw9E*QqsT!VCHx13Pg>V@dBZO@+| zzb$?JgyZrwskD49Dbsq{Bl6(h=P>#01^lNuE&UBQ2BgC)VeeQc}6RqS!tFzt)9xH!sf`c_*x^5L;7 z;!vMVL8_Oy3}>l4Rq_k(x?%~=M@yA87jpR8M$0EeEw@7pSf7o@hnOzi z^nOZlHq&CM;oR{d>47NPjR<1&W1;P=6W56;TS`$p zb+&m|Y_UA%lUaE^P?|J(6)BNi@F!I&o0c5JJk7RFo``L6C;t65Ij8W=G|^1d>?Jqmv-q1Tdpvc z2-!(JMze^9mXyA?%hAniWG=cZ`7EcZj?-h?kCU`P{--}}RD7cu0x3Mnli%(6Jv1W? zd$5B`h}_*95EOy^r)fz{C`wDqHI}?^k?sBA-_ZDVzWF9YDtS-wEl!Dz|Jm5Yv+0}r zE9~YC99PV6cmg#1kv`zkCS-1AD=rhxRgXfk4cBB!$Gk^ZfaG*7S5yg1T)&d{Ci+*&c!Y zOP%e?*48_{Z7^{!A)-S33L>rGeb{E!h?Ll<6l0i^F+OjWJUs%@h!Q8h+ovxZ{=Lzt zCu$0xw?w505-0q}iW=rSgFn%3AeZDAA=_$5*R1bM%BX4I97NpR#7Y;a*g`cQvh0Ga zO6Kflw*bs1m&nuIdcwk)WT9a-iuD!OJBMMr=)CTs%SRy|Ohd8cU)7)UFWI=&h9!%d z8F0~)_WikYC2IX&VZ=u$mA(?4GH&J{ii6T#=d0Laq2Myn3ic_8PMipHs6xEab6!iQ zaM6yvc>+<&H!p3>vs5P^NRX#eZMeUKDp0U!DTfdyu3w)XYUJWORrgoKcxtCgN1x{2 zug7`*YQw!4`g^(TZnt1{A@!hHn!Ej!I_#16l!0T7sGXf;OOIPhdSv9= z{72!UY9FGNs+bLURPTOrVsX@*6aU+s<(iOLhHhY2Nh8Sy-G>RMM0zlNofR;?(XhVIt2p|kdO}PuA!S5 zP(->Jh7d-YVF-yK27&L4-uM5%@2sT@moul&-p_vaa}M9n*Q6-p$Vm@ZyW(oQ(d4&!WEv-o8HW(2D{AJibKrxRX*u0^^YAq}VV%bvl7M$BECq zKHCF0y1_L9b9rYb7j;${R;EW$b@*peq8>=c*a&REDr6B>$Bx~HN;!)0D!F}$1d=O0 zachUk(V|`Oq z9|B03O3%wa;chk?O6%}+A&8!%)9fD)mM3e2n5K!d>hTmyEws8DszGf?HtxGZtO8T~ z%W0CDIh5)*IJ1%OG1T1^MllZ?w$QE_P~A*K86&t0%sLX5e*L)G^gf#qk_~;Kc%4F2 zQysOm)Ylq?vSEPGe8TwBWc4`)u$h9_Vem!r-M*+a^Q^|B<#u-)p*gO}QnEFT78^%j zWT!aW5jql;F3?z# z@IRjv>okx{4v1-VRz^-WoyE<5-?B5?Jz#z6aZ{ZkZMHANGM1f4o5@3^0{1{6bdQ-x(v8clEH+qchT8!UT0Nr9m@QccTp90SlRE!{b8 z^2>|%5D$6HS{dW|F4VEr%;ba;yp*57@%Eo)7R8TLLo-G8qGJC?T$>RRhXiN7_Io$< z!r#gOYSbMo+DpNSm3Pi_&heuu*(nc@VyWGt3(HQh` zYX0lB;hUHrFAIk#E)^HSs$T`xxo1IRqFL>l`uqvbL}B`-Db3nN`}EkyxBf0$aYVou zb@;CUWJHKZNi+iD7^c4i;9YS;LsIPdY_~T?xf1RB*osj;$$q_so)d>rHK|lSs|IK! zJJaPuG@9#ldvvh+HX*5Q9QhL`80)JSL5K@W(ktVchne}0VG8RMFp;T-2Pd1a*QujlX8;NaGfoipkbRdz*vcw|Y*9-)caW8wc6h(`{-@Utbm;ZWdNJ8)3wk26noy!ou{OHNp zb7WAf4AM#Ym_~xvbb{#O=PP=#W)LhxCej&IU7f`XB+xKZ<<-5df4aAt&iB{p{rFm| zuObK#=6A8K-gV#&?Bqfj1J~!?`K{67 z0*1q7IO-q1^)tIjP!JG$p8aX-+AzBPV6JFLatL|cq(3pg-n4BrRS;*Z-7K8F2beF{ z^FEui6EM-ZGD8HCV)Xlbipvi~q2Q0n3hC}uej!DCw2CjkI*ncf&cRWY&jO8eH0aN4 zbo8$^xbuZg>xvowG%dAm5V!W^=Xps5q--~y&kzHlo8eId#`3~1Y_Yl{@_c|h-ZP)2 zU(pJ)rpEp9Z$t;3?~*!1n~KZ%oMP#5d$ulPWv=W0I{kM{INsq6E+dE*RWenR#dZ!t z>f)$di75#5l)o!p7h-eepH3>dE@Dy;5!}a1D!p@In~rrw)oODpzUO#6%`=kUetag@ z;>WH2ZsYI3gX<$fjXxt~NDS$9bewfm2s%r=h2ofy`v+TDB>n7`oh?g#xFOgB1wplu zuRNrr02dDl9-yUxvobVAmdy`+P-@1vysnC#-Tp@fHI=??j zYVGN>vGs9%t8%BzLi=y49WzvV`1!6Jh$~9B$irbLi|SaLvU6?Ga&XxoiALSL0^Clh zm^))$N%Py5*-rTPR%nsz&A}c{mW=8?7}gVpn`)oW89Y-Su74Y}>ZFi$Hg;XCDyS6R zMd0ZHZ@QZ{MQ89!Y>i>9QhR9WklIm}$qHS{xnde~wCz+O#s9Y#l1o43pFqrHNPKa+ zTVYrRVFt~3{eW$Z;P>wbxZ_yyCw^hk%l;dB3-^&&hBR)gV&>Zu%T75F6o{d8)7dBL5o3)=iF0F0Z{qF9E7_{{qFB@X})Prml#ZMcCoShvKT=QH>_QJcH45xGv=urEZ zL1BtIb1YeKt_1l#%t3E1ayq)K_1s?RhohJY z6zt&so}{W)*4eSk*#<3Ni)h09{n>pa!eUHi-6yBDkAfi4S_HcN8(mB+b3xBG zbj#Kg1@C3kA%sZ!g6JMZ4TSZ4Yvff%)S=|WGaG3Ak$EvH@+ivW3-AsfAU(|S*umP@ z6?6Mcr+XQ~rJBmZ3XhmMZ zjZ`UF02|pl_w#S$>8}J_xyhB9%EgvZ53nHwa;`@pODj0Io|HcPh&*7$QQzNRL2%y3 zq{5k+I`qQw0sfHxR3O{{S#`6mYv~R12sfo?ofkt>^JXtx6+R<0PcqqbynMUj%7z2C z@&RPd^KOHyW;mM<7Dcd4XMz<6#uTty`P)Gr8nrhZgIFdqGX^&{t|jvq!I<-Dq4tQL zZ!;1CgpXu<(d@N? z>$LmG60TUCp?bchZxdv4{oEwVQ?FKxgSsOjWuwgtAIJ0oG{~;pwdJx&7#bM`SkKg% zQ{Q<`n3er!CA%hv&d5-iZ2d)t*EBQDG2Xfti;MdL-3PnxWQ3OoRkD45OrMa%XVx;A zHYV%6hM|}Qs%!!pWdJpms+IG+YKcuGsT3+`*c$$+u~ReeoJ1_xpGgJCA-lgL7MGru z*W(>&`{{hF!r|Ur@oF4%AbNH!FbWuD0}}bUIr$K&l|ZPy%JRh6=L!{d{AB#P<77$* zITo<)_N*BxF|_D}uRYByk>yD*)uS+3AKCTIVCdaQtGJGGkIqop=;;l?Z|<^pjHGY}_!FsEA+F#B$z+K%|MU7|SctQST8e^(R{M&m_`;UUfLg00{Ln{ed*fa7tfi zWKpYH`lzr$r<$#8WZCH%QC229yWOju2V{M#eY2cbA&%;0+9S5O9fb1e6YAl|^WO&I zgfHonhOQobTJTeTGBZDb@zF4^)!p+>$_9G1YB@nXc?GF|hKKG+kzG0<>32tbwtS6FQJ>3brSzAS zi7##Y#1Hav6-G!^gb`WhWYFgMNu(4d7oK?-4?Nm%*Q}fz=1pJmiKLC%F)ds!e~Ba>h))C-b?^hTRl5XW>PI1AMHB5jxe}_&)gD z!~1J(>QKhK1)Azgmrk`fxRLacpqSI}p zsq$Q*>#!-i>hcqjvHOa`K#< zLR&NZxgdh5^!6=&sOr`yIyX}D^yY0aY{@Nr+?rsWKT#fZ(A@7m6TMMZE7-F?b=ydh zWvJkQ%2Yf@%LXmbT6;q#@KBM(!{w=FULPd;P~a++hoe(|xe%w#GuMwAfDXR=G@oVsLL%j zhEijTPZ&cPg`fuqC4_a=IBAdw_*B<3B}ATH# zPq)~uUWJ?c%+%Q{u&5s1VRGS)c1BNC6BLZ!#$tzA?>z2(rIe_U^mQSQ37o8r-_4H) z2bjK@0u4o3JS#f+j_pBKD}&ZLGd;_a%`=7_KRtp@1Zr@;!%`9ANDR&&D5UI5p$Bp{ z@h;J%{d>(<_9bn~UMPB4gEaYvt_bVl@b}Ktp)A9^rE0e~Kw}vq$O6D_625CNLMAvH z5)(ShYlt%>EY+M+K!Oo$Hc1Dx&a&9^2I)U3@F(}0h zwc8(`lTVu^4|LV+ zG>{E*k9=d3RC?kU-81Vp!1q`69b6g11;@m8-GCKg?YBsj@tMhDx<5iN(mp;Mh%*?4{qAU9l#4r#oO8mit@MWuwOjNezsP4S(zv?`DR~PiVqQ9dFrvf3oeB9sS3@YPD$+!yk~buzZ7Nifyetl$wqWJ2nW|zp4K&V;C}ifZ7Vw?&Yjv@E>p{E^j$COWn=wU z_J)fVSwYheVdQlP#<=?6qShN_?v=3uI|?e>6!t$nD4nlxXtw137F_b?J&oMY!8g)! zZ(bG)F~atf)E^g#D~`%XJ0I2borc9mmGk&V z*$ijG)=rxrniR4H=BKu&mud!8r)H}mpksi01h2u zb}zNC(s`Ds-s0rF(*86=+R*<6Jw3G;+_Aog)ZtAPF=sOr zG<1FF9I<%q5)en5J>F}sx)<>B9dyb=!Ffw)no%~>vMB}|VvKRZkNEH}|& z1Ug~#e2inVVh$kQrJ&!ST@jVpGVAn^zVXN13*rTF~Lp9TuE%`>7)?xzyw;dJ& zdMc&MhQzckG8iI-kE8@@5R~mMDG~FYA;&rd*yOn%#p@7;Keabhqs3At;!g%?IQK4L2z(cFsW~w#JMbXi9 zDj97Dw1WyO#L#>5yd_kq5$)Z3NGvultb26@iw{vijJk$<H1H=neIqoPTX%8)5N z>UdsW%+KqJDTIa|Z_b1J6BN2Z+Tqd`NChof_WD-jZTjq; z^}QpDUh98g`*$n={QUdJLOqVhqzS*ueK3+aI!ZaH)V)?8{otK`lnOb!NxSR66@r*J%&`uqwsTF`e?AjQarsth3iu$1C$49vLbj9jMKAVnvq3`llas(U`dhA8WSu2@*Gm*qu|zAxh4u~Na0dc`zKae* zd@%5dlteDmJ<{G{?xvqv`odXHh)~IJ?~4y#88sP>SFjH9@2w0%iDgt9ta}N)$VJpWRR#_NrRHQGkU*!}!tP4qSN+mmOcL8iM8FOY>kW ztg&RH%Y?C~aM?ekh!-5D=VU4YdVwerm5s1lF%GBSDPi8lc#k8&v{3L z^Z4xp}0@A7Hr=bDn;U7M|Wm_oEAqQ&ZeRdEwhZQ1Q^UQ(@8+#U}q z6hJR*)`S#;y0RZrL@mUE8Rqwb|`pAwkgZhC5E>72Z+39~;0K>sQ2i5FT#NFumnZx|ok9{Qrb3O*hORu~? zxAseiXUvqpm2IRkgHJW&_)H}2oc2)}3q_k^;{Nt6Q(b-JYkZF73T1O{IzEC3F6b68 zI%{m0^K(UZ5>wCfGPu_6;b58mN@z| zpr!DWgm~3?uu`CKT%sW4Ith9Xj}VMY751FQC*@uwCLmj7c%l4NbS74dKm z2d~(`_z3{YJe09wGZNDnWF0S1VV`6_BJ}s{Pw2=zi&UIb!>3h)Usx&lxnoRVH78YH z!JBEgs)cn|%8s?zE`RYwH6JS40t+%#@i5(R;pVqt4|h&cQDE>ql&* zEL;k=hNPGZ-6USM8}0Bh6gTXMP%-_R4x4rK!74ztxIx&=!!&-!#OT+bAcp zU#1CLJN2_WdT(;Ncy23fti4!WR0Je`2=>3X(th5_wAcRRF6|bmsV|ssFR0K1mTDl~ zr!GH=Hq4e(|FiWpRG^#zc={ZW=Itn$-phxqt!kP)Cq!iig5N3@x1(s<8mKm2qS58g zBP5Gz!DvyG{XJ_e1EP*4gcR-cPQu;WozIc*&K z3$9DgJ}Ofta=y*yigu1=VMO0bT}2l~n{HV+>xDj9xDB%4n7bZuI5jXafQ; zgnsJ>dzUgVy`onPF)CJ|Ads{UpvHYY_M~BBu`%{<`BBcLYEp4OPdZpqg>;Qy+}JlP z!m`LMO(C&N4{Q-V;@r`=23HARm7c|Ny}I%(5tY(b5t$A$fKg%*4TsK+lPzGojZ6`D zRr&eZkVom9t6BLK%3r=L=4R}c195O1kYE24(B86D4z@*&tNjmqjlRg9eNyFCb+K5( z0@bKCIig7V#c#C#C{6EbKl1Y%^~@liPCjoobYA!n4Ig0ga#K60i3uq&b3k3u{aebz2% z0f4+g=zWO*a^wEJ+B#onjV(^|47wro&)ttk$s)^&;nw~H-Y+$-bS%aleVs8~US(4w zZGKzE6}VKqJm0XncDaIu=#bl4)Z0*KYE6azkb??nrJXBm#Q)0RU<<` zOF9#7*^ma@9!e z19F=|iUDkK4TJkf=pV6N%}(wHoS*zDq5pz+mEPpFSlCWpIP0JAQu%xyfe3knWkmShDQZyDMB~0*=*wjv7fx8GC`;w-P%T z2=1!dO-so0YQX1fHx0mT8#_^2U49G_RijhgQy@b1xxPjMdJAs(?%oV22bs@t`-4QI_rS0-vhH&q+%-nx-q*s^| zt)l{t2m})O##vdnZIVY*yZj0y_(YpSzb`+JqLOP_x^Lwj3Xf2uqJWt+n!fywIn*$59!d`8f(Y&WUhA2Ug4XswIY7TuZI|Hig*BPSBN zE2?=p%->_#PWR_!88C?5>H5czFH9A2CX)ejT&g5?zE3N@XlQunBhja5Y@biQ0|5v4 zwaYwyxR(n3{uUHFCmY^ZS6bQ}fl&etrAXU-)l$!7bM3qdk>osqd*H0nAF`xROsDE_ z7-;0&)o6Aq5mJxE=+Q8^>Ijo1u2I)N2J6isYs##26Vk){eEH#_B51wC;-9Fe5d!@E zw??iZ2K-wv3}@0NpO^Q56YPlgSUE>Z6sB7ZnhiA0DN9UY$@3d;Ag< z57w*h>MeYj-1$LnH@w`Lq@bzI_6MB=%h-%ce2RIm3|qpMVI5ud%O+QC*9u@KiT&6Z zlsI(wVmx?HrZJR42gM^&pn7mFH|!|v+w0jrvzyZJLKaK(fNS(+v;CXW%fUBVF*)jI zU(1qoCrTEl(4P-)=2K>~LENpWGw;067vjoy3m&fk%XhA4Q?>2kKKDm(A_@E7nSS*o z$$Fh%@CXxh-uIB1EXQ4(>U#Q2L$%D(IP;c7ToN)n4FpC_oI}^ft&&H9dTWMwaZq2l^8015fkQ#vLtgD*jbhgjHHP+ zi4)B|@)RophP87e3iy(w*QQi3L6%4N7pA_2^a3 zv~;I4oFNi@^xCra{=$u{G?M8;6F2Eb3w1?RdXX(|}z^CK{e9?AvmkaliOKmGdYw5#x%GCA_j_2(Iw-t#FwirnHoy=|) z+X5MixBvF&sR+YlXwQ3`w0*^ORZPL4?1c5ofu0NXgMMItB*P2aaF?%gz6cdb7`%hm z<%3O18o4*rA*A3b48>k*5yzV{~X?paQ) zZxce8faj}OJ6bp0d0Jqss;b@G62gz1`p~`U0f~H%IZ5kH;EylyWQMRIEN!uGphO3I z%jO}E-S{o2q4U#l#q``I+*uBl<3LV40KBA@Nuvc+KP>nrzkm}8%42JF@u+qS<=U3n z2X7ARm^)|SjQRx;4r`-EK|hmzfK51e0tb>32!v)%)_)r@%zW#S&C_HfDgmRpA0Ao^ zJI#jjwM~);;L{v<*Y4D%NK^gAxEqLE5`&aNM(xRgMLJu84h1ZU95TriY3q zZ-J!$*mTX!EW0-NLA0ygH+ikL`Q#jPmYkaQM;AzdePvwSt&AELuFjAN_8U;ym+v}* zWwv&wxop8BjF03XRURCDMZ2o>pGP04UTxJ6`f2wfMjYWIcuY!NL$PTdW`4}`yk7+Z z`R9ib!>8ldOP-YA?qvzj>dQvE$4f8%^ru)ilE+S+&3^_KBs`J{Y)k_Cl^aYGmsQ8k zEs7%G#-q46TYJ+S#d9MYKtKgE?^OThq4)t_j~z;TmFHJFqKUu2(ILgV_R`1l|EZHv zzWM`&Qy||I&d<%%Ch?F;*p^iFnCCz%$MDvQ4u_gGn6pumL^9m)L7}9-*P6d)@e~l~ zfXd#ccTSW3;VD66X$217O*&;FgZ2x#DlC?1Mdl!UA$dJ#a}Rh2>vi}5@tpAQJJxd} zmvn&jq!|p?P|U`5_jC678U=v~N}%SO{4-S?j9+k4T-n`6$`}yBcnnT9=p(o3<8$WEJ-9q)bD<*JQ+ zQ91)JZHzJfBlA+oOIq4Onq&LvD(jbxZ#igMNhK}xVmSeIFlicPTuJ24e$5cTiQ(g3 zVto603Y5+xUyp`8>W{l(M9X#Ct8{hC75hBJ2J`9p1*eI_lt@4KtRMP^dRjcv#kc_w zLGxYuWW|pUSxF_3k>a@pmnwQ4tKSOI)^@S|T_=w4E^67dt-Q_IiO{ZQ3~aejfvqh& z)-{fR>%jnY&5G?`d(n~D>3~f#&K>fFVT}Wyd*S5 z*IqDpIJ!;E=f=UMJZ9y zKZG7mn#&oEf=eFR=#;K=;rh)1*1wbo0$orP<&A&n9|o3a9cG@mcJDIpUIppYYy&)D zTAgF)q5L~xGOTF1ZvyRB>nBYuLn=!YK|d3}gGd?I!e}sOP*d&AEE5ElubFfWj>#aY z_v-KSRj3}$7f8_fzHw1>)^EBGMrl^qHVu#{C?o%F{CPSfI7D#eyN9hGY`ff(kwT9) zb)?c$+^sjZOVzQO7$-R_-6GidVo9aE57?KgD=7fQ02-DmDscjls>7tAlk?Byv0g24 zSJ!A4i1;`j|6yL$jv8cS>p2pL>x#NK)~(q@FKw~* zj+D67fG8GHRd=^g7X$eDYXdxDoFEnM2o-VzL26N#1+#I`S#T0(RzmNv2+(?v{WqRW z4iCrdDN4KH9E-4f{YTpPn^;Md??xE`aZlGEzmt zO6NsR-2A4M)qJ<*z}ODdo2}9WFA2(+FH|p*cXgUBJ6BVPR(Vu-d^0E(JU|w{RdU4M^ok=+DvYwRE zNehoa`NjNh3N$i9W5C0sX#(o1>^h1pYP>Dn*@m&J1{X_OH7<7FF`k{T9kC^{B3qay z7&~JZpBN_DKg!_bnz}9lQPdTua`KP^cj`2l0nKW07Y_KCI?vgkLX45MUvKM*G>~pw zcP)6)ou(aCB{TIB+t46}Q$tGEe6)4+(e8hCrt9!d{K;>N6|vV)mmg#P}RuRW?D{@AVC*1fDbcf#!>T6k;yd&CZ)L*~hsL($Y^o9QZ2RPjI&jYE>%w zr7}R!f^>Er7eQ4Sq)+no^O4d&O`DWB>%Km>-_s;|hYC_^6(9z_u%rF<8%>fJz)8B zYzUM79yVf?AgWmzhpEOS9KH>?xyw=Jyfy1m;fc2&fK1ra-}CegkZU|VQ|p&5*&q5g z6N-p zh$6W76N2mHkj_45g(8g&4>i0#%5y7(yIDqf&QxKzT?uW9J7!^^AOXS2rg>mQ(17#s@2 z&O>F%1-X9MkMIR-eIzZDNSK_L5;Tt#`tPYE$;(yCn86BF%y^)8Y4?zchjGtKPs{Oa z0oiUqTGuOxXK=oRHecZso|(nsblY{}tY!-*E9C4tH{QQK{*@9@Fzw21Vb4Q?Ce-!b zh~JqlorkXbX2rbVFmA0^4kO|Psa{@%E0Wp+N`m$dY>d=!kku8ZLVUB5QkmAtAs?Hv zi^Ovo3k#D5$;1%7WpIOKb+8EW!>HIN#vWJ0Y1;XKbC0XGEX3KzPj&5qpLe%qP1H0h z%=x2|owSvPx7B1nR_McRa&OH)t78XA&&$K99bIU05dKiA~ZuTkp2yFC~uD?-2l^^~zEFCZn&Q$|9Ycr9fo;K1{@I z1Z9qxo})V1M6P&42DnUtPpQT8GWwazics4=9CjkdDO6xKET{=wMfEo*FsFmdA=wsi zE?<*h-8-4KJy~H{f*>b_ljePM_+DApFfT9pY)0`m{yHG!aXhQ3tKD?bEl*UX4raRH z<&FcYfJ@mVubsYK$9JaYGNiPJM-&9GMDs`n1$Kw0AYq_581j}f&g!n{=dUNZw-sFj zvBX_@iQePkFF0T)6#bq%mP>uB$8bPo1a}o}>d|D$6*mhN{p%X?@L?QVBG<)vHKQt= zBm<2kw_@PMt-g)MX9beK#8uL!U&YSO9epONi5(I>@RL1V!i6*xkqbQj{R_l8CqGXM zHRd;qzGkswLRO4cN%SOJUXFbA3>4d2wjwS4Vv+n|c4Pa)mHEatLCQy;@t}u;3B~Ji zAlE3`xaX*Y;^lif^@OW3sPsqac!5>6n9T6RcECgCTytS3ouahS0X zmsVG4m6lO)URU+FzV-e`pN^A4O=dBiR+S42oa^kkSH7UeNEP^evt6E#W?#%uS?%3e zYZMr>X||Z^iodqmCie56tMV!Dzzq^p7gXNM5ce(86F=?!XU^dtwVQb$U~lzK{f(i!h4CWEs!gZC8wZRVmo9&wdGT#v{E0?yy)1sl#x9|w7Lu2hUj*RK)g5tJl z=I1YCtA1-&IYm*((Rlqt`pOp+=GE!FPy1GeZ><|8a225OlB-~up=2P6kzLu_+-X#_ zR_u=U+PKt=6%x_gOepHRv;!xh=kOXpMRGm)p$8>O6`m_) z$<(V*dg%A*=y|A(jm1o@f8zJ=aT+0CJ}7JsdZW)b*-j{ar(N#ynoBhhbghI z?_!JXy_D9>%FD9jxcExCiC;cB-?h!3uqTRb%?MT`i&wVhVu_-y`4V$0o~Z5IFJzzn zmEgSOg;k@yZQz>OG1mVYX!Dg0Uxw#5uk}TWt(u4ADRG zQCqL@4)4>Ak8m$*yX>i);g3J^pA}ipJL<8q!Sn9$7*&uI)QO7bJt>m!R;cLn_mZ&( z%H-e|yxZTfX9IpPf#&u_G5@_lzxyc7u2K-(%$W(57>2n{61ChL8=8t$I@z-Zi5&2z z2P(GkbIQ5jqVSomgJwm)%w^U@`m@f)Xw0whkN126q-0fX9F6Z#Hfv0ey(L2b(S<)M8 z|I-3^t;gqa#qGH75<`j~YmSAkH~E!+EQF;z%qZ3gE7CsX6w_Zg|>HeY5rh(Z}fW^G$}E=)=~q6+b4CdO3TiT)Cc0#nPbx zo>RVo`D+BmCjgy!6!v$ydWn~hujIe}Z1@l<=%~hwAD$7Pop}$ku%}6U;_N5TW!27X zz7?PLP8R3?EhQFf%$!^W#-}G0+IO7-7HhG(S(_V3O~X;|wqzG>A2I7U-k*$?L3**K zR`H9Pj0By(l=BwnV?(Z(e=(}qjKRcTSe8Li^H90t0aVGt?%VU7M%DEl_$#dfw9 z4En=5FT)I!*4s;T-zwObXDRkty$9i=wuJe2c(@&<0&MNXMUUtW4b|#4aV9&s9BGQuevYc-g@r5;~T)q6~zl_DdT!unid)cz8nW@Su+FE9D!{df9`Z^Pe<$=+=OB z8WFkOh<#fooG>Ij19L6>`bHdEQuH8K;xr?p1)VnJeom5Wu4pL8gqWn8l=gpkg1f|R z%Sg)VL~><5`N$Q2^);BOg1G3Q=nRFJTwgEm=1m`{fktLc){%|Jhh!3#0D|?Wn=!ZD zsQnr?e4fGH)2AiZl*!5m1Tncg`2uWPGOMkC-V2r~S)Ua)Z~(Ho_br=0WL)oMaIj!) zEr*dnPItqA!J(*CEH~x?XEWz!8S`;1z&s^1$C);cCW8Z9xG3*aw43N!X>svSKS!Q6 z+OJVmP#L>pS9Q89lR)~0-PEc4Hccqw*3^VsVLEUSsl#WB0KS9@Kvlp~W2K$%s0Z`= z`HRUVVd?%Oi&wR|3n&5e(bnu)X_6?a_v)6@?5_z11+-xa`|=0^0ELM+H?DFD$jV~3 zqm65#`ep}1NmN<-<-zIB7{&n?L0NBJq<_m=*KQz+buGlBd;+>tC}=kzZ&&;}9Z2I366{h9pjCRZ!@j~WEr z?W;6(kB*VOx=qA@2iX`D5x$3Pd0BN^5>(eOB*270YuHZagSFnO-6=pfg#md$K)6~y-!@sv)Qz(j( zw5Jp{RosGE=HXh{Xkp;BqWR-J>z4gDx9476$R(B;-UU}Kk6?i?okMM}@oDaSprJui z1$l+Q52Et+Xjxn@nLXhZbm(zjN9{!ckep?Cg33HbS?j+3<+*NeFZhm4EoZ2i;7>%WpYufo@VHQy0PWH+L{bc&PJg;Yl|dis2RW>}c+$Z3qtGj5|4$J}5qL>nm)RGP8VELMS^rdQ(Xnhdz-H?8 z1XM05=Kpi|l@LKEB}=HAuos(QK?F^wR%v$C1# zp@2>k$vj^QE4mz{d@0zPf~hl(L}W@ry!RQTgPO53zM!vCI*@u#hD88$UE(oKU5XdG zYI>%=YO5t^kHcB@o)Q{vy!7T!^w;tG7c7z5rNvJY=vBSN_)0-8nYLb)UJ1S4`~7;= zG5lc8{~e($kC5&yi6X&wBbSF+=uO9Xd3b>=s>WardONf61@=;nR$8K%~<&6z{5KY zR#%?>w3&U8jm7?(dX3NkW!D}AxzVkwr}Jp)h)$k|)6~M?Hbl}^SS!HOA?)?TS6a@K zn>(N2=`+O-2;Ks(3#s=Sjiw}XQ3~RJ4YRR9YpEYN1v;)0i+wg0*!iQ{!hYjsnuV`3 z9})`4HFS;tQuutYzaPtXE1x8aVwq1b*jiXyL)h?yY=ErD_SWF#j^A#M_{)R0r*$_c zie8xHe{s{;mihiRANIi|eY(6-$%Gks>z4^JI2qp`&x`{3;u+?Ea&V=j9A(ySC#j;c`En3ZJKHNu^Ikke38OjeS83NM(| zqy=BeTeOjn%W1P^cWSCpHYG&D?e0*3snl}_FvT6Us$e`DImTD(2Wz3Q{V%u0;I4je zO3PfMmoT^BRk~THJvW{8GMd&~YL?IqBC7a58P~%F|LNYv+6D!w1sbaxx5LhI&2J$0 zJ!dnD4u(;LiE&!0nxzY>DP6fd$_mD&qBdOuY?C$|}ho z4*A);C2@rs%=F@)5LE46&rMHOpHM_Z`IZVNzB>4oDX%<~Kpv%+mhu>Vpl9-6NhV4) zk&ioN6#vnnpxGybR(&9aFPRY$`W-<|dT+9iQm16OPB#ZwL2zDS+@#Xs4-FS$S-W=; zX0|z*=H<;RhcC`xc$>sOj<`3v4|PJ;WTq%EtD-;W9VS(g$OAdHpVLlVO>+pTzTO_l zaEr=kx*|N^9f2$>o(l9NznL2GLdkj`s<7gBZcIpaGqpxZx+{*QGvPj?CUbZE(l5$e z9V_3rr5-;dkd5W@ z3Rf@%pFokk@XD-^?GeQ7iAKM+Z29IgZ}TrNAqlTj;^E#}C(e1R8Nnu55M+a0*yKDP zpCH{DKAvongtRjYPGxs(3=#{)HRs}QD9|VcJ3nW7T7`nUMz6Gp<<0QAJX;v^7Hag-s|cd2IZvfG=mf#a2e-S}+m+DNoo4<@A)4!shvjUhFZG_^b`rQILtj3x zbL=$|SGjkEn<23y@!f@ChzHd~Hx0S(eDHOQ zj6&y09i!*zqcLT`-L|%7fg!d!a7P-+EtW$+;pa>+(YLka@b$TT4@+3udh`PT$(^}P zk7}LPQS`a}DUc8H*bVTDE1h%3`+&@-L=iI{9xs!s*U#;zqKX5i<7Z}T`d67bDP$46 zq>w-*0TNjw6#HShXxS*O8OWS+vey#F+Pdd*%nV(#y$){p%^^SBW@x>=oY`3m2vp3| zYqb8rkOD+J)bio%-xkmA(N{m;j3B}CCHX02cxFRi(AK+K2pWV^?w>^R-5C^)}p0v0N@ky;N^sPWRb z#+=bN(_@+QTu|@gR{6;*5SQ10;={AWA0d4f6aN9Gaj=Du7cbWp}zsn z8%de8Pc*`2J3c2Rv9RW0%9iNm3smx%y zkysopDHolzjHN3+^+eAEY7Em=?R|KPy9VJV9sO8ve7Wa6k6YkT{K_XuDNR{*FxyuB zg3-H&5Wz|vLXa&T!VL%*>wqiFLylSfkwq1=t%fY@OC0Vzld*VSye+QFEoBeEBAy$4 zI9HaeVHyY=%@Fkp@6CwRp{LnWAAHNAmGR_*?V9G-Z=PI98k?2K<1tb-6#(P8uZgO2 z490Aw7zFl%WRBYB-zRSPdj&7-hhwd`bZSi6$ZKKdGXr5DwG% zB97u^Al)F|q0dd+pY$(&D}3jl0bZ38XOs_G*@ot63M8 zM7C+Qo56AZGaS%WsMA~Zj7MiB6Q!rT-D{7q9;*p0rD`TV=Kd0-&p?z}8=Yo_FcPEJ z`z3-0AnDUYB^kQ6Bx_fgoPKYtcE*6{JwBZ~Jf;bp1v`ryh8@*S4?T^GvdzRMhC#&yDK-vRm#RCz?K7 z9CK&7NBD%;Sb9WISUOYt+rFb#+^qy9;{l*fW51WAvlRwMM(`y`NqGf2Q9>|Uy&~5L z29*bFldl0@OS=vADy3sfJ)M??xRT~E`vj7E!{GVtV-_b!$+o=#KRrUSUI_QC4@`$g zs_6cVo&@DJ-bN8{bX}J#MNIhbcNSmP73%bC{5^PWF-etfN4@0U=EYQBoa4Jrpr;Mi z2ltEtEr+Of9k?S9K9}wZoL2)eG?^UNiIVAM60}4X?}bv|G@Q`?e0imuZ>T|ItrM>_ z>4Gc{(xe$q(@PhR5W2LN?Y-$0~qBfFtD}j<)a5n5|4)yIxQ0S}h55 z9w0oniVY2U>H7mMKV}oGDNI+b-slaWB(5Wpli#`uvE$QoIc#4h2Xnn3Q>K{`Oa{Tk zEuY|%igJx#9vue*Wrq<7RUSw0UDek0I~a#Cjp${MGG#h*uJ0D&LsT`iZg+6&C0n?R zOdkq<-i$jk>KhYnBgR#a6Rt$|36S73vZT+3BMoa>0Jf#TxMT8N-s|%|JyN@=@$o(1 zVM9JbkQn#r8UHWjc4mBGQCg|G#`43j*RBpGWiRrH#b1Z$OENE++oY4bGE816cJ`Eh zSh^i0i<=a!&`>baUvsnm^cGn$x|@r{Wsu`8uI1Uq&$9R)m*>Pfqdz^3HjR_yXbw6` zrIvvg5zPbV1Q;?VgG+WXeIb_;R_s}~qZtmpkd-q-5{A*^=9i3sjcgdq`L4U_CG=^) zK@2?x8z#M9<|G{_)F{JVlop@%++p-;{P&I8N1B5aU_^0(QwvrkA>@=qw9JQ2~^GhaD zT$vsFDm4uhq9w&jKqk~m6G?3K-%r9*n;pGtOk*FFQhil3-ji2bAV!BTPhs2}y{^E3 zJN>bgn6I$OZM* zw2T&3lQQCeaQlx1g9#-jr_yqNDLCc?NiJ%46Wf1@>`MarH&(k*&MdjX^itX_gzn#c z)d4)>!K;+?Jc!rbk#^r-Y&@m2CHUy7AHiB#;p=9T zIdLpr^kOk2b9Wi{d)$UDvs!;g#jTX?v|dW-WUz;3RC?*naBP+9-eP*VbXzRhvR#Dm z_p3oa7YKVq$C_!|nfXHzQWr+r^oNgJmSzI2{t}?JycMsmUog3r(GX{`UM_wdJz4JI zsX3*5eBeF;kgNz(*tT1#e_V4Z@=(IgK@pb2q;-&PDNx9sHFtl67)97**!3l^H2jb- zbN$p+rRXR=hZ(Mbc7Imlu00g_x{=AOJG~7%^*lBPF09CAA@1RuM@VRNf53+Z(mwNf z;J3KHhwjw2lcv4Jvnau1=XmEb)g!jUm^SIso+vfFY(+@BVhTMUj%M8x1<}(rVu{1t zWKG!Zq&Z&35DoPj=EXHqs(ACO27#>tX{Q;RWEiKC+1(_NFc@5SH`8=}drT%Qre!SQ z8{c!Z#Uk!fS+tS2Sz{x*(Hm2SEu?*+b@l=(botM(76+t`R9*#_tek#*gf`VkaiegV zOK;px7MbBa3!PtdDypalVzewEETtb;=cK$*X9Ebw7uZ(!kgA73L@Q-{VNy`bNEsE~ zW*9>Qz=l`!EePU6fh_8#ntYKPk9dZCe=_n|G2n7lFoE|PM4b(r zw+>vjps}L9|80tDS+g3JMcXU+&=Slj0yiO2zRHSLN|1CFv7#x znZtXSMWN_mqpCzeH{{h_q9_KjYMoHh3>^~_j}F(<7MMj(laRRX*;E7Nir{i8;&tD3 z?9U~mdS$$^@w|K&D(kE6?BuWAoNLiwa4HcQvM(+Wxr2ml$KoVcR5wDP7 zyhn1kwgGswSjR)~Pm7Ec*|_-aX@^C*BI<^F@Ab{>PhaKA(-z3Bv6&UF8wRr(KO`?K zB|-N#Q`q%^>4zY&BbwG}%qpCG6?e88lz6rU>3<$|%OB3+7|uN|!=cPmh8;kQ#ghCx zQIN!rdws59ZOe;>eaBPdSMS=VB?w7ne6xsVwTwux9KHdP8ubmR%V3936+5ckfpWr;)H~cS>7!^-5h-9ky_|K6ACGoMb{8K&?b5qRuT;8<8nkbl8B!};o3Md_rIy0|4-i_}aWrw5-$`_i{11T@x40~Pn4#TJW;MI~TOZNcN) zXUr`RXA1Lh&ShkrmWib99v^HDk;BckT;fO~U@f2|{s$`I9%oTg!CcOb7Cn8r8$K|d zUJ=l84v)%6F(~K{?0+a{e7$4lHqq%!oul@YiKl!hSr#f&>RMROegZyq^Mz(y+NgbM zruN{2i}S9vU-_mpF3O}^eSlJmvef;Lxe3wcvM-RiIMDJw`x?J+w#PFwN3FL|L&Got zoWpEW{NjS2$7BKu6!7O^Z1w7@&3^2XyO!|t`_)b8LM=NxMeG>jjfWHCXf(rI&Qgqg z;x~Xj()Q#i8Fmr)MyD`_{9gPest7*fa|iPH^cPSHK?|h#B?-GcS;*dQ3D8!Fe0iFw zBVeNL$9#YJo{H+aaNJ-`?p4&Mmi)H`;qAHbS5+-XTa4-!<8z4Z&X}O1ogKZ4+j?>2 zpdup#LZS7U#hDswNCEHk*%9Ww!&_X=3wvgwI<5S?&r&(XA-RG!uoO?J`RB3Kx~Zu{ z_I5`piNDFmYZrTP7AvkV{Uhz2R9{~ruOOV0O;!n!JL5N&f(kg_Zs%+=mEK(^(j*jv6d2Vhog6=!t^byHvg~ly3lB zvK=M=n`B5aMTjC*pxngds(WW-5fzDnq@W0_GjzBV=JtjHUudPgmT`13V*ak}uzrrJ zS^6BGeWQLG<>aK5`*xhX7cj=YsX)&!OqAS^N|DdG6o2k;dzT4@oVshdD^w61w1SVf zD31iY2``L7_v{^2FokJqB?!meD2gh5)f;4ops>qJ%D=BvuKgdy=HnOl5=jke;G5OF z`srCc1t71(D&p=P%#bjp)J4ugx79_LY~!;$FO!-!wHO!I9deVNsf+V#rAFEN1pmLv zRO-y!^wqkj1PXClpW2U43N`r)#+Rxm0D4ceyR`xN2pUP`fgUheCnCX(O)TgXb0!x* zu(fzAFTp}Sb1(DOTtVIpnA6FLbRwaid$981J^=tUFSz}GhXJgUd#yeU9)a_ot##|E z{Ic|u?^n9iY`Jd-SZ^?saC4LM@vltKkXUcOee$s6(?$CTAJ_AxZ*GS!O+E=+#>O@r zC71Q*(o)UkYGqD_79q*Vthw@$2zpfGQ`v$6BZ{2Q>^;}bhFNJ={a6DL_>`T0r}~S& z>cPX>IxG{rthSndYanGukE@~Wx=8?4^h3h=l^D$;5$MpvY46>a2eB2J3I>s%2V$p z6LR)oGc5${&O&(khHu%=ZW_X0%U3^f;y}dG{>lZSboGalc#8dKpRrPbl0huLuF+F1 zTyXi$M(WA8xhX3Ip9uUII$xmnmyD9%srBTZ*{n8a?(QdVs6#TZx2g#3*tcHX#>tgz zZ=Tj-ynhok_3L@Q1xoF&;DE6DY(58+JDL9L`1KXY-(N2_K3;fZ_1yhlJ&syadn6uf zI_jd#xab~Q-k85E$J4)VLJ}?X;!0Cwy2KRRLEIRb3(3Cz|Hi&yTZPIH8!z`=FnN=X zkhdAG<4R%&F^9)h;+-`(#*D>r)UW)(tAJE+>r*6#tO;4xP_lKbjx2iYh%lZ?8k{j8 zB!sN}LBZh1$@RPL0(>@H)ccLs)mWj{k%xsWpZjUSF1?el7~tR8~~K?=u6NY zVQP)AKmqNYbE{HY$6jk@qP;}sBoe+8X#xm}h#8IV4}AD`5T$*_x|q0Mp)7eE6tj`8 z$*rj_LY24<&Xd?_W?sywcVv`sFBkXxDG*hXd0djPkGofgT&)mdk|u>=s1Ku6-m7n3 z%CRW%3F>h)&`{g|V{^rP2w!>+-vVQ^^W>nFx~a*<;{bQoO=Doe%0*4xcOA1y0zgju zTXL&?y(E8=|B4h^?djLoSzUEwk~-S3rhoJe_S|ymI6QNGV=%>oB+K5o3j;Ct`hQak zNc<^&A7FOXj`!-QE`d&$xZJl%NU}nMU=`3gNZ);GOm<&1v8ojD(wvsxX#W4O0NHY< zL9h%7d2PL{7d?>SherVLIGB zv$MOB*pKbM!niDS?1K^Vow6!GBhutfO+sjjQ0YGU*$4GqeZ%C%aD^B$iDwl3(-eaX zWPySqzNSRObN}j)f%8y4JYg*5SJ&l;mB|aIRU#0#dBceZQ{$T*0ba+bL|Qpi`lOFv z0Tn|~g#Wv9Asn|l@v4@2Mzaj!g@25N&H2a7LHBqB10ZeugBSwefBXqg-Uop@lNB`| zRK!j7oBh0#&WAoKX>H;|yoM58gT&uG|M=%o5SN%`HARsY_^g{UdH}3gF{c>qSdW5} z2CB(hN-TU=9rPf4lj?y!bj%*|d5f z*+G!C0yrnLXO!Q%`nhj-;d*wlwSwX~@EyDS&+0ah9_S&x->6{vMD?1KA?-x}jrsL= z-vTbsnLfGi3%^tO!&O>7X;026!^R-6>k$!bpZ|SOyRm$TV$z@AA5Z_kReGBM!0@02 zR{y_!_fSL+4S?mKaWtzJfEmTN$7R`he-ha*xC^HL94V08ii&GKzE zd0pMYv5-ICv5SwHB*v&=Rfg1TJ>9i4=`w~98#~>kScMXmJ>8|``2UufgYWg>HuIkw z9nL7PD>HdkyfE$>O_RRawJsW36A5NbR?c$z4Px8fnY!AlYaQ~}`K7Jh%QQ?VLtcZ5T zsR@gv5cEJpZ4O5x7r%|v(rM&Jyd?hbt?1J#-2c3MAk99mko^Fa7<$+9jZ#!(O3*^< z62m;orPSf@zZK~Nx8k1x#((C5=?O~}By0JGh7~{9n2c0d?N2OV`>$W7e}4F(%!pE2&NA6o4oKJ7z&?tqg z(AWm{Mmd8v$(Wn}jffhY5-bYplXh6OC|*pThUJw${%Is}h@tYpN-_FBEBYNv0Vl=x zgs4VsEEXQ4StHpeZgXxoyy_1}N2Qop!9L-SEWW9WgN;N~*&h)DjGAwZ7v1jw!4;Kh zvxi>X#fj)T@{iuw)qhfc2HE}any)mU>Vc8ef9lWEQ=nYwtcZh}bW8GnKRrobPu1ZF zdQ1XT!Y_UXhaRS5XIGN<;4vT=49WKJdb4^%Kk6Z$9phRbTJ zHEXUH(n)M7 z9O_w!a&9F#qd%)p*WpJAJ_0R*x#>%g(Iwq47}vmGZ#g+^1_L37hU6p?O>3C$_Wh%6 z2X)D9&J@o098UaK5SVupY<|Dy!VeZmJWF`uW4YACu>HLp4n&;2I%Y_XESgpWHB0e+ zL*oDTj52ekwydmt?8LXv8b-4bQFPO#NTi4Xjq$`?i~P^zl8=`k$qyvsXWu+yz(`>+ zb2{gS*1Y)NjG7s7yFYqs{V6+AdmY_2%LxA z$^pa6JJYRsiGO->%H+y=!Dhuy{l3a`MUzASe762K+6gZUvP=IHRDEw3=CVWXH!`V7 zc#_(W7rMSMwyGdNDfWyEbH?q5X9_+{*S%CPi~unQus2Wtf8X18uWe|*2jem7zI%%* z;3b2-5%XHVtMceF{Z#K=89eVO1O@V2IEXEV7fXJAkaXSrvsUf6C7*CUmfLD8EAJ^u zEwY;q$O?p|()hg3N*40RsF4@=FP0h=j}c@a0SlnkarPq(%~&IMw#Xr1ROFQ{(nevnk_+ zsU+ldg{AlIL;Nv=z@gW9)HO3qw8UK;qkrzsb?x(m|IF07J|&Z>Rv{;cCh+{ryUyM3 znaW!6&op!Q@Obh+Spz(h9W=n2=ScEQGW!RWK60*5L4)n|p0%%ga69eNUV=Yi+~#r% zj>MfmnPx`T_cm`Pn zrpiKVPjVO^)PfZIU+1ZO)%~1SG!k#9buAOmBVOs4Wue^sHyaqFstr0jRbYlJ_;Eq> z=`-uU&oJo{G#O0fE2GBe$)eEPH+ncti12@n2gF)%eZ8rCQo0SD`;uyH-?%1N1;pJq z;Qj}B88nO)W+52-=OD$TQT#LCZ;vN#zrSA+@Td&gQG3Q|WYb}mpBG}OFY@R5Q9rzC zXf78KQ|Cy_!)fXI1VHQ7RQ^q&0!*xi%xf4GzD0PJcb6`-PQfZ-^w(QmvlGJ#=}Uy^ zP$4BTADjodGhoPNF_=E3*;ibh@|>XbPrupj_G@#Dc=P8@Yy=v(ahTztcq2vQ`)AJsℜI5&# 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≪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

    BYl2Y+bz?I$}Yhi}V+_`YmoQ4%?Ek#rD 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%0A6;pMGnD6T&ItlRx9T+8m`rhp#jR{ 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

    y zdU!@pH2PGbFmo8T3XoMvJ+&K>V-t}D%~g{zJF?!u&me{lA^Tij*3T`;bWOrOpy#yh zKI!XO0!rbhabl8%t)Ui4X0waOsh>NEfJ z?7d8`*4R!xDNdy}>}nLfc?3zMm)$dy4& z`6%V9nUuSigeLrl6LJ0$G5N?wk>U8}$Bn1Z+x0EE2WL?&V?&p1&$qXzxFK(FM*coo z@^z((i*@cX9N&%EUU{NW>vEWiv`v3)XkSCK|Mq~S`pVANj<2iMQjO6GZZnHKh;pR8 zVGc^|x5wvBS}Y3h8iRo~zUbS?M;MK}=W5N?m?`Lw(h*A^p&0~5Ofsk(qX!o~DNhEH z*ZYngczU~?p;1K!tQ(UV34Aq}EP14s>GKO1>I#j0J^ellbIs~#2Lh(AQ&rxdd{;w{ z8hMCB()_mQ-Abs5;K?8nc3XtQn*JJWF6m?rO?vW;4=$XN6)3ST9?+?cO1kx*Ma>ZB zIeZ8~&6%paCisJcD~2SF^=Z5GUw=B?B+Z2@j@5t&bNV%kb>eb}E8bKxiBr;rl>5<| zw~TZwFH*;dOuQ$iLg`aUm+4x~UKmTNgU$-R&e;-Mb*5KC<_$@Mqu>|MbnLfHo(6~Z z%EPDU=4|D~R2~r8rk^3)F`o=5Wvz;=akWu3a_1!)yK2(B3b9XaU^*)jo=nY9Ke(+Rh5#;jA1vQ6 z<~XSP9a1T)Qq_0O(MXSN_|9w{tUFpCQkh6;Sp}guSeOg$ZPe^&6Vio+`!&PfKLkwT z!$xnNj5ILj>fVSocLj8ks3Sx^5_P#re=o(?a-w7|i|CkCC$EBl&9KQ+ZHluinQACJ z-D`(>ewsuB*RmR!#)m{w!kFQZzr_&#{~iG=?5F7|{A?+$2CR$_25DkjL91}f$N&lu zEma*Bl6aF*oKziF5OJ3+8q2%9U_&c0iZN8jvw#4xa-pIHSv|`MQxmPj10IU>H!>9`Ylh%H6~bm4K$2clMo?F zV$B8UD5YTZ273YlktMV9mru*h`PN@lt^8NcHL)7E8%{b;E}4lo0`Elb^@DP?4S!O- z`HSF_%N#JtY8KM9@oif=Zwv9xE03Fail?8W7udwZMz<- zXlnEt#0UW&I4aZ*<#ComT>K)IW*~K9xuXhdkqWl_3ZB?6ceAv^xVZq`QTFfMV+E!E z!>C4kxumg{xitSC01Z_DPD6w>7M}~ejznOe__7=}R*EFQaU`oO%574O)mk_%m2-ny zI7^d_P6_9CJXUjtrWil|+F6&Y^eL&-sA4nrax)9D&Hdl8GGnmBx&+P%3SJLnVlRv&u z56dMm%8`(5L-R-E^_G5YPVbObbD~``+i2ZVp`v0SAfCr?U>%kML-s^cY`VZCO*J~btDxo91GOI(M1BN;VLp-GnXM`LQ7mrBF_3mQ|!z8 z_-XWc6iq*|6?7%-bK|VuUU*|;gYn?^wR9}%f0yz9UGjuVd z!o6Xq%dST1X~=~iW#|fqiLJZ)e#>k^$CkUmggi@#oa1z!+>fR^*FMl{yFDW2rp zoC7bzJ5JtC>W1}!X!?x^mKF*E1iXImu?vfiZMrKpr<|FHty5%?jb8i*-P}?EK7==U zpZ*#?+g3PwcSFb=5Gh8TMX+;HDF)}s{e^$X>VHsg4H~OB+CF6e5n83ig}1vH8_d0J zq5!|U7#I=?;G-a9w|nulNlLx(Se9M-j|O>N?yv=g>%Unm7+wu!$Y8zsi4!pCy$fN} ze8v!!=;|9PG*vuhh8m>?;VsAM4yKVerh}YTQI;EF?=!wRB-G2u>G`*PT8j7&sH^{v zxX8zf52jc~`kCIBX07zDb{E-*n383$s7kLdW=+=`J~igX_Cl7R4=h&~$QqJo!`sQ! zu;1fSKOeBvaAL*#?p49O@alq}C=E-cO0Fcc*E)FKFV1YK3PLubAw*E}?&6)ya-1q_ zm!`D6Q6aDh-Cj9r9Gfluz$>%GrkT1KSdn$~!8m@26;uMs{Hrrhf_8D<{fLEjp+sZ5 z-Z7&d&eYN}*wO=;zMHTWZ6#U2SgoLXYsQ0070F5^pti&n3~vq7YgIc&%V^l@1pfZ8 zXmJCeAfVaN{I*uO!;AF3;AqeXO__^vxZj_lW(b)xqM%58uMfNW}&}om$8?_FZH{yP;gFiiE+WMsWA@hi4iaF{pjx{V=D{}TFd_FHy zd|#j%`RmDVJkVPc5U0WLbz2ZAE( z-~V5JdCXxbgukkfVM#qbQ+HH-tT(kpO(4ElIWy%up$ zpOQ|?@k{YIN1$6`uIW;F00ev62Qt9dW6$yfKFu6QX1=j0&JJVEWFJ&Q0kW6#e|D6iWifg_b@r%qk_;?)-lt8^^NumS4-$FYH_rv9ms8R6inLXlC--RHC zLKTUVzU#V#I40&^ipAT4L{Lr9<=jvvk$%?ARO2_5r9LGI6q(?k;KGN7IcL$MSGkZG z7hA$RdhC2SX}v~*9pruKM+Q)jyhIQ{{DOF2|2J6Rp%~W{pH~0^r^=aciaAWIl({F}s3gP9Pg#yZmmK`dyn+^r3S8V3Wa708G=@?am0ZwkWwfAn- zY=cRylzsImEbYS}{y-v#y+++?_BX5}YhA)@Ty5ATzJiw*sn2{dp}d$dBA=DSmuL9a ze-2S9i23`+FN95$jnDDcZCJii)>^S08}O(kh;>=w;z z0}GMxM#@!z6@I~p>Qs?j-#;ep=Nhd^6E{Chjub>!;JG=`+gD40hwr_=D&vevU#r#zg=<4d&NA$sW2&MwYZaFxu!?%C?`Ll_BA2Y5#XDvZL zNPjl{08bW#Qh%hoj|L|M1=21S4OQfLrWgLxBAE2-=E2GVLeP+OF5Iv%!(mUlYueDuJXV|p4ft{{}Z(I4t2UhhGAwKKYapztilxU^hxN)C+FaB(A)nz40 zAH#aPNVH{6Cx=S52xcG?<7GaHu_Ekm&r?Hve?>A!IlVgyW3Kw!G4>FMomQY=DUQDc zFP#`~+oxySUh~cQEUJ_BU#2l4{a+nUh>Kefu&3T<)Ob%kWj#%Uh13nn!VdcNE}CQ` z;*Bl}7iMq}sZ@AZpupQO1(Y4!qmcQY$IR)DnQ;X*Oa<%WY{IE-Jh8I{o?uc`ht_nN z%(>TvD#GDrb5VtVqzY519OjDyA}>G;13X_rtavmdZ|K5lk{PskqCe$A?mg3*^3e7S zlA0v=eci1I00;EfLO;fBY~y8WCDV&fUhlfwEgckHkHmP+NnrMFWbi+zwlq!rh*@1W zC$LeXwHK zQ8z~NT)XobgOzFSScVc-p)Q?cUYZQU6Vx-8* zdC;?A9VP^qSiDWYHoq)VDH#sei>=G`nrf1wiC!-`snbgsIXG=xGQ+}bqSR(UeZ$t% z(Oj5+X2Z3O2Qa2RabDmb{8E6S&c0ed9bJy8hlV~}d5|`p^yGn(IFpvq$qaiv`{{mJ zpJ1@7{wR!9mS&TU_Gh1Y?&`8c!h8r5*8x>h?AJ2pXi()-sVwgGW&$e&{I|(Ywa!pF zq(qTe@3ZS158W4c6Bk)ic-g~$IpY7-7$6jSqWyT%`kIhsNm>Hz<*kb~1zQs@Rpwb` zcgB6<5VUHct<9K=o3CVUyL5weXZ`!ESe>deXPF0nwWI(L_BRO}68+9V{dz1dP6}mX z*p=h)fuT#oV8gN#rD*}j7Xg@y8c1VViK@s_&R#kBlv>9e#JYTK{`oKtl|xpA{Ir41 z)mCLSBO}hiDoOfkoyTCM%Yl4ZR|?JQ_NgW0h~zLc3|+}Z>x40?ljV%^D?gifXRNRN z`UZQdIL%zr-(W(qZp9cm=q*<021p7iQ>u$nKF9RJAA`C;gE@k$ZZ@oEC%-xQHS-_n z@@DC>?TvA0p5FVKpeJI?k6~!3n$m#w@NY@D{Z!SsGX(sz9vT7u^E89TQhK023~ROrld8?-=FK3T2Ivt~Y(XvL;T3dH;CteI zBs>1mXoNlE$&aOKi0UKz#1&Gv?94{8-@-=Lyh}d7MmU9`#m%)J`#uxS%C%Y;M_v*5 zE!|nem>xg{Q!JWe7T%*SqT44^+i@{3rF=7=im-kX=xWAXu_6(OfoXa^kZvxrpWwXN zK*lU89|o=_`|ed|qJ8!2i8r6s<#PV&lPfNXyim!{N-ABSW2KYHFT!+ql!a)si7X;Q z2$!9skH^vGi_(h^^E}_gixqh+aLLRUZ1j5)ew6njN(uIZBZKP-9e$RF?YcdTWXlx1 zF5s5^s&kyX1^%;O7i2Fo*ngn)>nVqzix`G|f8Gq0Nyqlk9Df*H$o8_RL(k!|2}Ozr%?OdV)BJWU7c ziK#lmX8HFC(|eMT+r>GNzLnNuP=Kjl3f}m5_PXGj4~m7w){!2OR1||XOL#i3LsOvE zx}k)u*EplA%+fi2)A24gsS-nj;rr}F$_mfS`GA#f$+Ee>r(h{$n$QEkX zmew6hJ{W8QH3C$yPSSYMVitg=u3HRfH-k!l&b!`mLe8Iega1-${r&~sa}ijCjSP?5 zEeX5q7W4HZq+B1?F`EV8V({F#Oef;}Ec4NDd2G&%htQQ7i8_a!!pbZdhE@Hb8|7c3 z%27yGJL>;*Sfps&PGx&lx@7XMJ~79^hLp+u+L!sR!~H;)$Gn?UV$30J%DMj)J` zCY3EGe>d#4JYF!$jxt%3rn;$e3&zflzP_oERK2E(DZIs6GeC6>u($&DfddsR! z6g2;coX;}<*LXVQ{YwgXmp>8T7g(gT0yP5f1H8fgAH=rjdo&CFjeYw7yXVb`vxl{N zs-o$yZ-7;Q4AubBj#@A(@zArRJ{m?YeInEs)!drN*yecRtEwiYPi41G@VIWZ_(QDi<23nnwdGpbHC`Q{M5 zc4znO85H^BTt;!D_xWLRQt509auz4eqOwgXfN>5Z5XB6TZUWlW?73Vir&gO8?wCC~^}q{J0=6BXvttAmg*FggP6_`Y(*PxCpY)oW@w)PS?Y z|KrYr0PbwVTnxx3@4kPHrzr2SnmM$8c1YJV1r79@KSkal_`*DW{UQm9XPB_OZ2On@D7TNEoyjbM-Y^8;XHQ?vj^3mNy?A6e`u}hg(f{ab zT1o{x@g~aSi!z2BIhD}mcS42sH=oHnAFp-hk8aL*Uj#90Bm7B?gadN;g`k#PgLA$c zlB0XVLY^I=NhpIfg|SsTz~&+~>+Z-J8w46-H2qJ?GRoH7U+0`=Ev7luPZRfCJ$AEC zoGAOA-|EibIJsH(%AEj&awmzYr>QCq-E;8t@5P`aP^5-J@{itJJ zN&MYb6xYuFJTwmv+O1}ZEw2U!PZEURJ~5pgzh-d|+?^FJl@Na)qQ%wQ(;}kR8dm?e$TAk|Pn&-xoOG$cc&7AaE-X)Q*CsJ2& zU+^?f5Rr3b!ZmZhJ$!n*Sz%Y)o?FgY24am$s~i@l-I0j6iVff-xoOrkF%RNno97lD zEzP&2qPYy5Hm4f5KTNJQNLs#k_tgKgaN zt5RutoelJg|Isr7Kq=PlzXaVtJNt-TeM8o~MZe>n1Wa;&7m&iTePxvb++>jr0t+g3 z?ro626bjzPzKm6d4H=J|wQ=il06&_?9;HVtSI`*FR0y^N;|W%&7Bib*e>lNytzA

    )hkWjfdir(1AZjo$AcPFvPk6w;kMYENq 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

    >lvsl_vIQuKFeEd`GK+g-3Q^x5E! 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 pf&U`#Uj+V(z<&|=e;nP(Gl8Zx-)Q$%dZ_lG - + Introduction to Zig

    + +

    Sending donations directly

    You can also donate some amount directly to the author of the project via:

    @@ -404,7 +419,7 @@

    About the auth

    License

    -

    Copyright © 2024 Pedro Duarte Faria. This book is licensed by the CC-BY 4.0 Creative Commons Attribution 4.0 International Public License4.

    +

    Copyright © 2025 Pedro Duarte Faria. This book is licensed by the CC-BY 4.0 Creative Commons Attribution 4.0 International Public License4.

    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

    @@ -419,13 +434,13 @@

    Book

    Book citation

    You can use the following BibTex entry to cite this book:

    -
    @book{pedro2024,
    +
    @book{pedro2025,
         author = {Pedro Duarte Faria},
         title = {Introduction to Zig},
         subtitle = {a project-based book},
    -    month = {October},
    -    edition = {1},
    -    year = {2024},
    +    month = {February},
    +    edition = {2},
    +    year = {2025},
         address = {Belo Horizonte},
         url = {https://github.com/pedropark99/zig-book}
     }
    diff --git a/docs/search.json b/docs/search.json index 80f3c7a2..a0dbe2a7 100644 --- a/docs/search.json +++ b/docs/search.json @@ -14,7 +14,7 @@ "href": "index.html#support-the-project", "title": "Introduction to Zig", "section": "Support the project!", - "text": "Support the project!\nIf you like this project, and you want to support it, you can buy an eBook or a physical copy of the book on Amazon:\n\n Buy the book on Amazon! \n\nSending donations directly\nYou can also donate some amount directly to the author of the project via:\n\nPayPal Donation.\nRevolut.\n\nThese are good ways to support directly the author of the project, which helps to foster more contents like this, and it makes possible for the author to keep writing helpful tools and materials for the community.\n\n\nPayPal\n\n Donate via PayPal 💵 \n\n\nRevolut\nYou can send money via Swift Payment with the following bank and Swift details:\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\nIf you do have a Revolut account, you can scan the following QR code:\n\n Revolut QR Code 💵", + "text": "Support the project!\nIf you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy of the book, either at Amazon, or at Leanpub:\n\n Buy the book on Amazon! \n\n Buy the book on Leanpub! \n\nSending donations directly\nYou can also donate some amount directly to the author of the project via:\n\nPayPal Donation.\nRevolut.\n\nThese are good ways to support directly the author of the project, which helps to foster more contents like this, and it makes possible for the author to keep writing helpful tools and materials for the community.\n\n\nPayPal\n\n Donate via PayPal 💵 \n\n\nRevolut\nYou can send money via Swift Payment with the following bank and Swift details:\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\nIf you do have a Revolut account, you can scan the following QR code:\n\n Revolut QR Code 💵", "crumbs": [ "Welcome" ] @@ -44,7 +44,7 @@ "href": "index.html#license", "title": "Introduction to Zig", "section": "License", - "text": "License\nCopyright © 2024 Pedro Duarte Faria. This book is licensed by the CC-BY 4.0 Creative Commons Attribution 4.0 International Public License4.", + "text": "License\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the CC-BY 4.0 Creative Commons Attribution 4.0 International Public License4.", "crumbs": [ "Welcome" ] @@ -64,7 +64,7 @@ "href": "index.html#book-citation", "title": "Introduction to Zig", "section": "Book citation", - "text": "Book citation\nYou can use the following BibTex entry to cite this book:\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}", + "text": "Book citation\nYou can use the following BibTex entry to cite this book:\n@book{pedro2025,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {February},\n edition = {2},\n year = {2025},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}", "crumbs": [ "Welcome" ] diff --git a/index.qmd b/index.qmd index 3a98532b..cbe7ef75 100644 --- a/index.qmd +++ b/index.qmd @@ -26,11 +26,14 @@ which is a new general-purpose, and low-level language for building robust and o ## Support the project! {.unnumbered} -If you like this project, and you want to support it, you can buy an eBook or a physical copy -of the book on Amazon: +If you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy +of the book, either at Amazon, or at Leanpub: {{< include ./Assets/button.html >}} +{{< include ./Assets/leanpub-button.html >}} + + ### Sending donations directly You can also donate some amount directly to the author of the project via: @@ -118,7 +121,7 @@ Twitter (X): [\@PedroPark9](https://twitter.com/PedroPark9) ## License {.unnumbered} -Copyright © 2024 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license]. +Copyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license]. [^cc-license]: @@ -140,13 +143,13 @@ source("./Scripts/zig-quarto-versions.R") You can use the following BibTex entry to cite this book: ``` -@book{pedro2024, +@book{pedro2025, author = {Pedro Duarte Faria}, title = {Introduction to Zig}, subtitle = {a project-based book}, - month = {October}, - edition = {1}, - year = {2024}, + month = {February}, + edition = {2}, + year = {2025}, address = {Belo Horizonte}, url = {https://github.com/pedropark99/zig-book} } From e91a2de7a7eb7293940e50b466ca239ab49aa683 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 16 Feb 2025 17:48:26 -0300 Subject: [PATCH 070/151] Recompile entire book --- Cover/cover-artv4.jpg | Bin 0 -> 513494 bytes .../01-base64/execute-results/html.json | 4 +--- .../01-zig-weird/execute-results/html.json | 4 +--- .../03-structs/execute-results/html.json | 6 ++---- .../03-unittests/execute-results/html.json | 6 ++---- .../05-pointers/execute-results/html.json | 2 +- .../07-build-system/execute-results/html.json | 4 +--- .../execute-results/html.json | 4 +--- .../execute-results/html.json | 2 +- .../10-stack-project/execute-results/html.json | 6 ++---- .../12-file-op/execute-results/html.json | 4 +--- _freeze/index/execute-results/html.json | 4 +--- docs/Chapters/03-structs.html | 7 ++++--- docs/Chapters/03-unittests.html | 8 ++++---- docs/Chapters/09-error-handling.html | 2 +- docs/Chapters/10-stack-project.html | 12 ++++++------ docs/search.json | 12 ++++++------ 17 files changed, 35 insertions(+), 52 deletions(-) create mode 100644 Cover/cover-artv4.jpg diff --git a/Cover/cover-artv4.jpg b/Cover/cover-artv4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4754914c2b1c855b08ea5e375a5421d3203c8af4 GIT binary patch literal 513494 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

    }hQ= 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�T%VV%#7 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%0A0BzUR;*! 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

    HLn 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 z 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�@P?@j(%b%> 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�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�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 literal 0 HcmV?d00001 diff --git a/_freeze/Chapters/01-base64/execute-results/html.json b/_freeze/Chapters/01-base64/execute-results/html.json index 9eb2b631..7a805424 100644 --- a/_freeze/Chapters/01-base64/execute-results/html.json +++ b/_freeze/Chapters/01-base64/execute-results/html.json @@ -3,9 +3,7 @@ "result": { "engine": "knitr", "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 1 - Building a base64 encoder/decoder {#sec-base64}\n\nAs our first small project, I want to implement a base64 encoder/decoder with you.\nBase64 is an encoding system which translates binary data to text.\nA big chunk of the web uses base64 to deliver binary data to systems\nthat can only read text data.\n\nThe most common example of a modern use case for base64 is essentially any email system,\nlike GMail, Outlook, etc. Because email systems normally use\nthe Simple Mail Transfer Protocol (SMTP), which is a web protocol\nthat supports only text data. So, if you need, for any reason, to\nsend a binary file (like for example, a PDF, or an Excel file) as\nan attachment in your email, these binary files are normally\nconverted to base64, before they are included in the SMTP message.\nSo, the base64 encoding is largely used in these email systems to include\nbinary data into the SMTP message.\n\n\n\n\n\n\n## How the base64 algorithm work?\n\nBut how exactly does the algorithm behind the base64 encoding work? Let's discuss that. First, I will\nexplain the base64 scale, which is the 64-character scale that is the basis for\nthe base64 encoding system.\n\nAfter that, I explain the algorithm behind a base64 encoder, which is the part of the algorithm that is responsible for encoding messages\ninto the base64 encoding system. Then, after that, I explain the algorithm behind a base64 decoder, which is\nthe part of the algorithm that is responsible for translating base64 messages back into their original meaning.\n\nIf you are unsure about the differences between an \"encoder\" and a \"decoder\",\ntake a look at @sec-encode-vs-decode.\n\n\n### The base64 scale {#sec-base64-scale}\n\nThe base64 encoding system is based on a scale that goes from 0 to 63 (hence the name).\nEach index in this scale is represented by a character (it is a scale of 64 characters).\nSo, in order to convert some binary data, to the base64 encoding, we need to convert each binary number to the corresponding\ncharacter in this \"scale of 64 characters\".\n\nThe base64 scale starts with all ASCII uppercase letters (A to Z) which represents\nthe first 25 indexes in this scale (0 to 25). After that, we have all ASCII lowercase letters\n(a to z), which represents the range 26 to 51 in the scale. After that, we\nhave the one digit numbers (0 to 9), which represents the indexes from 52 to 61 in the scale.\nFinally, the last two indexes in the scale (62 and 63) are represented by the characters `+` and `/`,\nrespectively.\n\nThese are the 64 characters that compose the base64 scale. The equal sign character (`=`) is not part of the scale itself,\nbut it is a special character in the base64 encoding system. This character is used solely as a suffix, to mark the end of the character sequence,\nor, to mark the end of meaningful characters in the sequence.\n\nThe bullet points below summarises the base64 scale:\n\n- range 0 to 25 is represented by: ASCII uppercase letters `-> [A-Z]`;\n- range 26 to 51 is represented by: ASCII lowercase letters `-> [a-z]`;\n- range 52 to 61 is represented by: one digit numbers `-> [0-9]`;\n- index 62 and 63 are represented by the characters `+` and `/`, respectively;\n- the character `=` represents the end of meaningful characters in the sequence;\n\n\n\n\n### Creating the scale as a lookup table {#sec-base64-table}\n\nThe best way to represent this scale in code, is to represent it as a *lookup table*.\nLookup tables are a classic strategy in computer science to speed up calculations. The basic idea\nis to replace a runtime calculation (which can take a long time to be done) with a basic array indexing\noperation.\n\nInstead of calculating the results everytime you need them, you calculate all possible results at once, and then, you store them in an array\n(which behaves lake a \"table\"). Then, every time you need to use one of the characters in the base64 scale, instead of\nusing many resources to calculate the exact character to be used, you simply retrieve this character\nfrom the array where you stored all the possible characters in the base64 scale.\nWe retrieve the character that we need directly from memory.\n\nWe can start building a Zig struct to store our base64 decoder/encoder logic.\nWe start with the `Base64` struct below. For now, we only have one single data member in this\nstruct, i.e. the member `_table`, which represents our lookup table. We also have an `init()` method,\nto create a new instance of a `Base64` object, and, a `_char_at()` method, which is a\n\"get character at index $x$\" type of function.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Base64 = struct {\n _table: *const [64]u8,\n\n pub fn init() Base64 {\n const upper = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n const lower = \"abcdefghijklmnopqrstuvwxyz\";\n const numbers_symb = \"0123456789+/\";\n return Base64{\n ._table = upper ++ lower ++ numbers_symb,\n };\n }\n\n pub fn _char_at(self: Base64, index: usize) u8 {\n return self._table[index];\n }\n};\n```\n:::\n\n\n\n\n\nIn other words, the `_char_at()` method is responsible for getting the character in the lookup\ntable (i.e. the `_table` struct data member) that corresponds to a particular index in the\n\"base64 scale\". So, in the example below, we know that the character that corresponds to the\nindex 28 in the \"base64 scale\" is the character \"c\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst base64 = Base64.init();\ntry stdout.print(\n \"Character at index 28: {c}\\n\",\n .{base64._char_at(28)}\n);\n```\n:::\n\n\n\n\n```\nCharacter at index 28: c\n```\n\n\n\n### A base64 encoder {#sec-base64-encoder-algo}\n\nThe algorithm behind a base64 encoder usually works on a window of 3 bytes. Because each byte has\n8 bits, so, 3 bytes forms a set of $8 \\times 3 = 24$ bits. This is desirable for the base64 algorithm, because\n24 bits is divisible by 6, which forms $24 / 6 = 4$ groups of 6 bits each.\n\nTherefore, the base64 algorithm works by converting 3 bytes at a time\ninto 4 characters from the base64 scale. It keeps iterating through the input string,\n3 bytes at a time, and converting them into the base64 scale, producing 4 characters\nper iteration. It keeps iterating, and producing these \"new characters\"\nuntil it hits the end of the input string.\n\nNow, you may think, what if you have a particular string that have a number of bytes\nthat is not divisible by 3? What happens? For example, if you have a string\nthat contains only two characters/bytes, such as \"Hi\". How the\nalgorithm would behave in such situation? You find the answer at @fig-base64-algo1.\nYou can see at @fig-base64-algo1 that the string \"Hi\", when converted to base64,\nbecomes the string \"SGk=\":\n\n![The logic behind a base64 encoder](./../Figures/base64-encoder-flow.png){#fig-base64-algo1}\n\nTaking the string \"Hi\" as an example, we have 2 bytes, or, 16 bits in total. So, we lack a full byte (8 bits)\nto complete the window of 24 bits that the base64 algorithm likes to work on. The first thing that\nthe algorithm does, is to check how to divide the input bytes into groups of 6 bits.\n\nIf the algorithm notices that there is a group of 6 bits that, have some bits in it, but, at the same time, it is not full\n(in other words, $0 < nbits < 6$, being $nbits$ the number of bits), meaning that, it lacks\nsome bits to fill the 6-bits requirement, the algorithm simply add extra zeros in this group\nto fill the space that it needs. That is why at @fig-base64-algo1, on the third group after the 6-bit transformation,\n2 extra zeros were added to fill the gap in this group.\n\nWhen we have a 6-bit group that is not completely full, like the third group, extra zeros\nare added to fill the gap. But what about when an entire 6-bit group is empty, or, it\nsimply doesn't exist? This is the case of the fourth 6-bit group exposed at\n@fig-base64-algo1.\n\nThis fourth group is necessary, because the algorithm works on 4 groups of 6 bits.\nBut the input string does not have enough bytes to create a fourth 6-bit group.\nEvery time this happens, where an entire group of 6 bits is empty,\nthis group becomes a \"padding group\". Every \"padding group\" is mapped to\nthe character `=` (equal sign), which represents \"null\", or, the end\nof meaningful characters in the sequence. Hence, everytime that the algorithm produces a\n\"padding group\", this group is automatically mapped to `=`.\n\nAs another example, if you give the string \"0\" as input to a base64 encoder, this string is\ntranslated into the base64 sequence \"MA==\".\nThe character \"0\" is, in binary, the sequence `00110000`[^zero-note]. So, with the 6-bit transformation\nexposed at @fig-base64-algo1, this single character would produce these two 6-bit groups: `001100`, `000000`.\nThe remaining two 6-bit groups become \"padding groups\". That is why the last\ntwo characters in the output sequence (MA==) are `==`.\n\n\n[^zero-note]: Notice that, the character \"0\" is different than the actual number 0, which is simply zero in binary.\n\n### A base64 decoder {#sec-base64-decoder-algo}\n\nThe algorithm behind a base64 decoder is essentially the inverse process of a base64 encoder.\nA base64 decoder needs to translate base64 messages back into their original meaning,\ni.e. into the original sequence of binary data.\n\nA base64 decoder usually works on a window of 4 bytes. Because it wants to convert these 4 bytes\nback into the original sequence of 3 bytes, that was converted into 4 groups of 6 bits by the\nbase64 encoder. Remember, in a base64 decoder we are essentially reverting the process made\nby the base64 encoder.\n\nEach byte in the input string (the base64 encoded string) normally contributes to re-create\ntwo different bytes in the output (the original binary data).\nIn other words, each byte that comes out of a base64 decoder is created by transforming merging two different\nbytes in the input together. You can visualize this relationship at @fig-base64-algo2:\n\n![The logic behind a base64 decoder](./../Figures/base64-decoder-flow.png){#fig-base64-algo2}\n\nThe exact transformations, or, the exact steps applied to each byte from the input to transform them\ninto the bytes of the output, are a bit tricky to visualize in a figure like this. Because of that, I have\nsummarized these transformations as \"Some bit shifting and additions ...\" in the figure. These transformations\nwill be described in depth later.\n\nBesides that, if you look again at @fig-base64-algo2, you will notice that the character `=` was completely\nignored by the algorithm. Remember, this is just a special character that marks the end of meaningful characters\nin the base64 sequence. So, every `=` character in a base64 encoded sequence should be ignored by a base64 decoder.\n\n\n## Difference between encode and decode {#sec-encode-vs-decode}\n\nIf you don't have any previous experience with base64, you might not understand the differences\nbetween \"encode\" and \"decode\". Essentially, the terms \"encode\" and \"decode\" here\nhave the exact same meaning as they have in the field of encryption (i.e. they mean the same thing as \"encode\" and \"decode\" in hashing\nalgorithms, like the MD5 algorithm).\n\nThus, \"encode\" means that we want to encode, or, in other words, we want to translate some message into\nthe base64 encoding system. We want to produce the sequence of base64 characters that represent this\noriginal message in the base64 encoding system.\n\nIn contrast, \"decode\" represents the inverse process.\nWe want to decode, or, in other words, translate a base64 message back to its original content.\nSo, in this process we get a sequence of base64 characters as input, and produce as output,\nthe binary data that is represented by this sequence of base64 characters.\n\nAny base64 library is normally composed of these two parts: 1) the encoder, which is a function that encodes\n(i.e. it converts) any sequence of binary data into a sequence of base64 characters; 2) the decoder, which is a function\nthat converts a sequence of base64 characters back into the original sequence of binary data.\n\n\n\n## Calculating the size of the output {#sec-base64-length-out}\n\nOne task that we need to do is to calculate how much space we need to reserve for the\noutput, both of the encoder and decoder. This is simple math, and can be done easily in Zig\nbecause every array has its length (its number of elements) easily accesible by consulting\nthe `.len` property of the array.\n\nFor the encoder, the logic is the following: for each 3 bytes that we find in the input,\n4 new bytes are created in the output. So, we take the number of bytes in the input, divide it\nby 3, use a ceiling function, then, we multiply the result by 4. That way, we get the total\nnumber of bytes that will be produced by the encoder in its output.\n\nThe `_calc_encode_length()` function below encapsulates this logic.\nInside this function, we take the length of the input array,\nwe divide it by 3, and apply a ceil operation over the result by using the\n`divCeil()` function from the Zig Standard Library. Lastly, we multiply\nthe end result by 4 to get the answer we need.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_encode_length(input: []const u8) !usize {\n if (input.len < 3) {\n const n_output: usize = 4;\n return n_output;\n }\n const n_output: usize = try std.math.divCeil(\n usize, input.len, 3\n );\n return n_output * 4;\n}\n```\n:::\n\n\n\n\n\nAlso, you might have notice that, if the input length is less than 3 bytes, then, the output length of the encoder is\nalways 4 bytes. This is the case for every input with less than 3 bytes, because, as I described at @sec-base64-encoder-algo,\nthe algorithm always produces enough \"padding-groups\" in the end result, to complete the 4 bytes window.\n\nNow, for the decoder, we just need to apply the inverse logic: for each 4 bytes in the input, 3 bytes\nwill be produced in the output of the decoder. I mean, this is roughly true, because we also need to\ntake the `=` character into account, which is always ignored by the decoder, as we described at @sec-base64-decoder-algo, and,\nat @fig-base64-algo2. But we can ignore this fact for now, just to keep things simple.\n\nThe function `_calc_decode_length()` exposed below summarizes this logic that we described. It is very similar\nto the function `_calc_encode_length()`. Only the division part is twisted, and also, in the special\ncase where we have less than 4 bytes in the input to work on. Also notice that this time, we apply\na floor operation over the output of the division, by using the `divFloor()`\nfunction (instead of a ceiling operation with `divCeil()`).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_decode_length(input: []const u8) !usize {\n if (input.len < 4) {\n const n_output: usize = 3;\n return n_output;\n }\n const n_output: usize = try std.math.divFloor(\n usize, input.len, 4\n );\n return n_output * 3;\n}\n```\n:::\n\n\n\n\n\n## Building the encoder logic {#sec-encoder-logic}\n\nIn this section, we can start building the logic behind the `encode()` function, which\nwill be responsible for encoding messages into the base64 encoding system.\nIf you are an anxious person, and you want to see now the full source code of the implementation\nfor this base64 encoder/decoder, you can find it at the `ZigExamples` folder in the official repository of\nthis book[^zig-base64-algo].\n\n[^zig-base64-algo]: .\n\n\n\n### The 6-bit transformation {#sec-6bit-transf}\n\nThe 6-bit transformation presented at @fig-base64-algo1 is the core part of the base64 encoder algorithm.\nBy understanding how this transformation is made in code, the rest of the algorithm becomes much simpler\nto comprehend.\n\nIn essence, this 6-bit transformation is made with the help of bitwise operators.\nBitwise operators are essential to any type of low-level operation that is done at the bit-level. For the specific case of the base64 algorithm,\nthe operators *bif shift to the left* (`<<`), *bit shift to the right* (`>>`), and the *bitwise and* (`&`) are used. They\nare the core solution for the 6-bit transformation.\n\nThere are 3 different scenarios that we need to take into account in this transformation. First, is the perfect scenario,\nwhere we have the perfect window of 3 bytes to work on. Second, we have the scenario where we have a window of only\ntwo bytes to work with. And last, we have the scenario where we have a window of one single byte.\n\nIn each of these 3 scenarios, the 6-bit transformation works a bit differently. To make the explanation\neasier, I will use the variable `output` to refer to the bytes in the output of the base64 encoder,\nand the variable `input` to refer to the bytes in the input of the encoder.\n\n\nSo, if you have the perfect window of 3 bytes, these are steps for the 6-bit transformation:\n\n1. `output[0]` is produced by moving the bits from `input[0]` two positions to the right.\n1. `output[1]` is produced by summing two components. First, take the last two bits from `input[0]`, then, move them four positions to the left. Second, move the bits from `input[1]` four positions to the right. Sum these two components.\n1. `output[2]` is produced by summing two components. First, take the last four bits from `input[1]`, then, move them two positions to the left. Second, move the bits from `input[2]` six positions to the right. Sum these two components.\n1. `output[3]` is produced by taking the last six bits from `input[2]`.\n\n\nThis is the perfect scenario, where we have a full window of 3 bytes to work on.\nJust to make things as clear as possible, the @fig-encoder-bitshift demonstrates visually how\nthe step 2 mentioned above works. So the 2nd byte in the `output` of the encoder, is made by taking the 1st byte (dark purple)\nand the 2nd byte (orange) from the input. You can see that, at the end of the process, we get a new\nbyte that contains the last 2 bits from the 1st byte in the `input`, and the first 4 bits\nfrom the 2nd byte in the `input`.\n\n![How the 2nd byte in the output of the encoder is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input.](../Figures/base64-encoder-bit-shift.png){#fig-encoder-bitshift}\n\nOn the other hand, we must be prepared for the instances where we do not have the perfect window of 3 bytes.\nIf you have a window of 2 bytes, then, the steps 3 and 4, which produces the bytes `output[2]` and `output[3]`, change a little bit,\nand they become:\n\n- `output[2]` is produced by taking the last 4 bits from `input[1]`, then, move them two positions to the left.\n- `output[3]` is the character `'='`.\n\n\nFinally, if you have a window of a single byte, then, the steps 2 to 4, which produces the bytes `output[1]`, `output[2]` and `output[3]` change,\nbecoming:\n\n- `output[1]` is produced by taking the last two bits from `input[0]`, then, move them four positions to the left.\n- `output[2]` and `output[3]` are the character `=`.\n\n\nIf these bullet points were a bit confusing for you, you may find the @tbl-transf-6bit more intuitive.\nThis table unifies all this logic into a simple table. Notice that\nthis table also provides the exact expression in Zig that creates the corresponding\nbyte in the output.\n\n\n::: {#tbl-transf-6bit}\n\n| Number of bytes in the window | Byte index in the output | In code |\n|-------------------------------|--------------------------|--------------------------------------------|\n| 3 | 0 | input[0] >> 2 |\n| 3 | 1 | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 3 | 2 | ((input[1] & 0x0f) << 2) + (input[2] >> 6) |\n| 3 | 3 | input[2] & 0x3f |\n| 2 | 0 | input[0] >> 2 |\n| 2 | 1 | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 2 | 2 | ((input[1] & 0x0f) << 2) |\n| 2 | 3 | '=' |\n| 1 | 0 | input[0] >> 2 |\n| 1 | 1 | ((input[0] & 0x03) << 4) |\n| 1 | 2 | '=' |\n| 1 | 3 | '=' |\n\n: How the 6-bit transformation translates into code in different window settings.\n\n:::\n\n\n\n\n\n\n### Bit-shifting in Zig\n\nBit-shifting in Zig works similarly to bit-shifting in C.\nAll bitwise operators that exist in C are available in Zig.\nHere, in the base64 encoder algorithm, they are essential\nto produce the result we want.\n\nFor those who are not familiar with these operators, they are\noperators that operates at the bit-level of your values.\nThis means that these operators takes the bits that form the value\nyou have, and change them in some way. This ultimately also changes\nthe value itself, because the binary representation of this value\nchanges.\n\nWe have already seen at @fig-encoder-bitshift the effect produced by a bit-shift.\nBut let's use the first byte in the output of the base64 encoder as another example of what\nbit-shifting means. This is the easiest byte of the 4 bytes in the output\nto build. Because we only need to move the bits from the first byte in the input two positions to the right,\nwith the *bit shift to the right* (`>>`) operator.\n\nIf we take the string \"Hi\" that we used at @fig-base64-algo1 as an example, the first byte in\nthis string is \"H\", which is the sequence `01001000` in binary.\nIf we move the bits of this byte, two places to the right, we get the sequence `00010010` as result.\nThis binary sequence is the value `18` in decimal, and also, the value `0x12` in hexadecimal.\nNotice that the first 6 bits of \"H\" were moved to the end of the byte.\nWith this operation, we get the first byte of the output.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const input = \"Hi\";\n try stdout.print(\"{d}\\n\", .{input[0] >> 2});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n18\n```\n\n\n:::\n:::\n\n\n\n\nIf you recall @fig-base64-algo1, the first byte present in the output should\nbe equivalent to the 6-bit group `010010`. Although being visually different, the\nsequences `010010` and `00010010` are semantically equal. They mean the same thing.\nThey both represent the number 18 in decimal, and the value `0x12` in hexadecimal.\n\nSo, don't take the \"6-bit group\" factor so seriously. We do not need necessarily to\nget a 6-bit sequence as result. As long as the meaning of the 8-bit sequence we get is the same\nof the 6-bit sequence, we are in the clear.\n\n\n\n### Selecting specific bits with the `&` operator\n\nIf you comeback to @sec-6bit-transf, you will see that, in order to produce\nthe second and third bytes in the output, we need to select specific\nbits from the first and second bytes in the input string. But how\ncan we do that? The answer relies on the *bitwise and* (`&`) operator.\n\nThe @fig-encoder-bitshift already showed you what effect this `&` operator\nproduces in the bits of its operands. But let's make a clear description of it.\n\nIn summary, the `&` operator performs a logical conjunction operation\nbetween the bits of its operands. In more details, the operator `&`\ncompares each bit of the first operand to the corresponding bit of the second operand.\nIf both bits are 1, the corresponding result bit is set to 1.\nOtherwise, the corresponding result bit is set to 0 [@microsoftbitwiseand].\n\nSo, if we apply this operator to the binary sequences `1000100` and `00001101`\nthe result of this operation is the binary sequence `00000100`. Because only\nat the sixth position in both binary sequences we had a 1 value. So any\nposition where we do not have both binary sequences setted to 1, we get\na 0 bit in the resulting binary sequence.\n\nWe lose information about the original bit values\nfrom both sequences in this case. Because we no longer know\nif this 0 bit in the resulting binary sequence was produced by\ncombining 0 with 0, or 1 with 0, or 0 with 1.\n\nAs an example, suppose you have the binary sequence `10010111`, which is the number 151 in decimal. How\ncan we get a new binary sequence which contains only the third and\nfourth bits of this sequence?\n\nWe just need to combine this sequence with `00110000` (is `0x30` in hexadecimal) using the `&` operator.\nNotice that only the third and fourth positions in this binary sequence is setted to 1. As a consequence, only the\nthird and fourth values of both binary sequences are potentially preserved in the output. All the remaining positions\nare setted to zero in the output sequence, which is `00010000` (is the number 16 in decimal).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const bits = 0b10010111;\n try stdout.print(\"{d}\\n\", .{bits & 0b00110000});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n16\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Allocating space for the output\n\nAs I described at @sec-stack, to store an object in the stack,\nthis object needs to have a known and fixed length at compile-time. This is an important\nlimitation for our base64 encoder/decoder case. Because the size of\nthe output (from both the encoder and decoder) depends\ndirectly on the size of the input.\n\nHaving this in mind, we cannot know at compile time which is\nthe size of the output for both the encoder and decoder.\nSo, if we can't know the size of the output at compile time,\nthis means that we cannot store the output for both the encoder\nand decoder in the stack.\n\nConsequently, we need to store this output on the heap,\nand, as I commented at @sec-heap, we can only\nstore objects in the heap by using allocator objects.\nSo, one the arguments to both the `encode()` and `decode()`\nfunctions, needs to be an allocator object, because\nwe know for sure that, at some point inside the body of these\nfunctions, we need to allocate space on the heap to\nstore the output of these functions.\n\nThat is why, both the `encode()` and `decode()` functions that I\npresent in this book, have an argument called `allocator`,\nwhich receives a allocator object as input, identified by\nthe type `std.mem.Allocator` from the Zig Standard Library.\n\n\n\n### Writing the `encode()` function\n\nNow that we have a basic understanding on how the bitwise operators work, and how\nexactly they help us to achieve the result we want to achieve. We can now encapsulate\nall the logic that we have described at @fig-base64-algo1 and @tbl-transf-6bit into a nice\nfunction that we can add to our `Base64` struct definition, that we started at @sec-base64-table.\n\nYou can find the `encode()` function below. Notice that the first argument of this function,\nis the `Base64` struct itself. Therefore, this argument clearly signals\nthat this function is a method from the `Base64` struct.\n\nBecause the `encode()` function itself is fairly long,\nI intentionally omitted the `Base64` struct definition in this source code,\njust for brevity reasons. So, just remember that this function is a public function (or a public method) from the\n`Base64` struct.\n\nFurthermore, this `encode()` function has two other arguments:\n\n1. `input` is the input sequence of characters that you want to encode in base64;\n1. `allocator` is an allocator object to use in the necessary memory allocations.\n\nI described everything you need to know about allocator objects at @sec-allocators.\nSo, if you are not familiar with them, I highly recommend you to comeback to\nthat section, and read it.\nBy looking at the `encode()` function, you will see that we use this\nallocator object to allocate enough memory to store the output of\nthe encoding process.\n\nThe main for loop in the function is responsible for iterating through the entire input string.\nIn every iteration, we use a `count` variable to count how many iterations we had at the\nmoment. When `count` reaches 3, then, we try to encode the 3 characters (or bytes) that we have accumulated\nin the temporary buffer object (`buf`).\n\nAfter encoding these 3 characters and storing the result in the `output` variable, we reset\nthe `count` variable to zero, and start to count again on the next iteration of the loop.\nIf the loop hits the end of the string, and, the `count` variable is less than 3, then, it means that\nthe temporary buffer contains the last 1 or 2 bytes from the input.\nThat is why we have two `if` statements after the for loop. To deal which each possible case.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn encode(self: Base64,\n allocator: std.mem.Allocator,\n input: []const u8) ![]u8 {\n\n if (input.len == 0) {\n return \"\";\n }\n\n const n_out = try _calc_encode_length(input);\n var out = try allocator.alloc(u8, n_out);\n var buf = [3]u8{ 0, 0, 0 };\n var count: u8 = 0;\n var iout: u64 = 0;\n\n for (input, 0..) |_, i| {\n buf[count] = input[i];\n count += 1;\n if (count == 3) {\n out[iout] = self._char_at(buf[0] >> 2);\n out[iout + 1] = self._char_at(\n ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n );\n out[iout + 2] = self._char_at(\n ((buf[1] & 0x0f) << 2) + (buf[2] >> 6)\n );\n out[iout + 3] = self._char_at(buf[2] & 0x3f);\n iout += 4;\n count = 0;\n }\n }\n\n if (count == 1) {\n out[iout] = self._char_at(buf[0] >> 2);\n out[iout + 1] = self._char_at(\n (buf[0] & 0x03) << 4\n );\n out[iout + 2] = '=';\n out[iout + 3] = '=';\n }\n\n if (count == 2) {\n out[iout] = self._char_at(buf[0] >> 2);\n out[iout + 1] = self._char_at(\n ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n );\n out[iout + 2] = self._char_at(\n (buf[1] & 0x0f) << 2\n );\n out[iout + 3] = '=';\n iout += 4;\n }\n\n return out;\n}\n```\n:::\n\n\n\n\n\n\n## Building the decoder logic {#sec-decoder-logic}\n\nNow, we can focus on writing the base64 decoder logic. Remember from @fig-base64-algo2 that,\na base64 decoder does the inverse process of an encoder. So, all we need to do, is to\nwrite a `decode()` function that performs the inverse process that I exposed at @sec-encoder-logic.\n\n\n### Mapping base64 characters to their indexes {#sec-map-base64-index}\n\nOne thing that we need to do, in order to decode a base64-encoded message, is to calculate\nthe index in the base64 scale of every base64 character that we encounter in the decoder input.\n\nIn other words, the decoder receives as input, a sequence of base64 characters. We need\nto translate this sequence of characters into a sequence of indexes. These indexes\nare the index of each character in the base64 scale. This way, we get the value/byte\nthat was calculated in the 6-bit transformation step of the encoder process.\n\nThere are probably better/faster ways to calculate this, especially using a \"divide and conquer\"\ntype of strategy. But for now, I am satisfied with a simple and \"brute force\" type of strategy.\nThe `_char_index()` function below contains this strategy.\n\nWe are essentially looping through the *lookup table* with the base64 scale,\nand comparing the character we got with each character in the base64 scale.\nIf these characters match, then, we return the index of this character in the\nbase64 scale as the result.\n\nNotice that, if the input character is `'='`, the function returns the index 64, which is\n\"out of range\" in the scale. But, as I described at @sec-base64-scale,\nthe character `'='` does not belong to the base64 scale itself.\nIt is a special and meaningless character in base64.\n\nAlso notice that this `_char_index()` function is a method from our `Base64` struct,\nbecause of the `self` argument. Again, I have omitted the `Base64` struct definition in this example\nfor brevity reasons.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn _char_index(self: Base64, char: u8) u8 {\n if (char == '=')\n return 64;\n var index: u8 = 0;\n for (0..63) |i| {\n if (self._char_at(i) == char)\n break;\n index += 1;\n }\n\n return index;\n}\n```\n:::\n\n\n\n\n\n\n### The 6-bit transformation\n\nOnce again, the core part of the algorithm is the 6-bit transformation.\nIf we understand the necessary steps to perform this transformation, the rest\nof the algorithm becomes much easier.\n\nFirst of all, before we actually go to the 6-bit transformation,\nwe need to make sure that we use `_char_index()` to convert the sequence of base64 characters\ninto a sequence of indexes. So the snippet below is important for the job that will be done.\nThe result of `_char_index()` is stored in a temporary buffer, and this temporary buffer\nis what we are going to use in the 6-bit transformation, instead of the actual `input` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (0..input.len) |i| {\n buf[i] = self._char_index(input[i]);\n}\n```\n:::\n\n\n\n\nNow, instead of producing 4 bytes (or 4 characters) as output per each window of 3 characters in the input,\na base64 decoder produces 3 bytes (or 3 characters) as output per each window of 4 characters in the input.\nOnce again, is the inverse process.\n\nSo, the steps to produce the 3 bytes in the output are:\n\n1. `output[0]` is produced by summing two components. First, move the bits from `buf[0]` two positions to the left. Second, move the bits from `buf[1]` 4 positions to the right. Then, sum these two components.\n1. `output[1]` is produced by summing two components. First, move the bits from `buf[1]` four positions to the left. Second, move the bits from `buf[2]` 2 positions to the right. Then, sum these two components.\n1. `output[2]` is produced by summing two components. First, move the bits from `buf[2]` six positions to the left. Then, you sum the result with `buf[3]`.\n\n\nBefore we continue, let's try to visualize how these transformations make the original bytes that we had\nbefore the encoding process. First, think back to the 6-bit transformation performed by the encoder exposed at @sec-encoder-logic.\nThe first byte in the output of the encoder is produced by moving the bits in the first byte of the input two positions to the right.\n\nIf for example the first byte in the input of the encoder was the sequence `ABCDEFGH`, then, the first byte in the output of the encoder would be\n`00ABCDEF` (this sequence would be the first byte in the input of the decoder). Now, if the second byte in the input of the encoder was the sequence\n`IJKLMNOP`, then, the second byte in the encoder output would be `00GHIJKL` (as we demonstrated at @fig-encoder-bitshift).\n\nHence, if the sequences `00ABCDEF` and `00GHIJKL` are the first and second bytes, respectively, in the input of the decoder, the\n@fig-decoder-bitshift demonstrates visually how these two bytes are transformed into the first byte of the output of the decoder.\nNotice that the output byte is the sequence `ABCDEFGH`, which is the original byte from the input of the encoder.\n\n![How the 1st byte in the decoder output is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input](../Figures/base64-decoder-bit-shift.png){#fig-decoder-bitshift}\n\nThe @tbl-6bit-decode presents how the three steps described earlier translate into Zig code:\n\n\n\n::: {#tbl-6bit-decode}\n\n| Byte index in the output | In code |\n|--------------------------|-------------------------------|\n| 0 | (buf[0] << 2) + (buf[1] >> 4) |\n| 1 | (buf[1] << 4) + (buf[2] >> 2) |\n| 2 | (buf[2] << 6) + buf[3] |\n\n: The necessary steps for the 6-transformation in the decode process.\n\n\n:::\n\n\n\n\n\n\n\n### Writing the `decode()` function\n\nThe `decode()` function below contains the entire decoding process.\nWe first calculate the size of the output, with\n`_calc_decode_length()`, then, we allocate enough memory for this output with\nthe allocator object.\n\nThree temporary variables are created: 1) `count`, to hold the window count\nin each iteration of the for loop; 2) `iout`, to hold the current index in the output;\n3) `buf`, which is the temporary buffer that holds the base64 indexes to be\nconverted through the 6-bit transformation.\n\nThen, in each iteration of the for loop we fill the temporary buffer with the current\nwindow of bytes. When `count` hits the number 4, then, we have a full window of\nindexes in `buf` to be converted, and then, we apply the 6-bit transformation\nover the temporary buffer.\n\nNotice that we check if the indexes 2 and 3 in the temporary buffer are the number 64, which, if you recall\nfrom @sec-map-base64-index, is when the `_calc_index()` function receives a `'='` character\nas input. So, if these indexes are equal to the number 64, the `decode()` function knows\nthat it can simply ignore these indexes. They are not converted because, as I described before,\nthe character `'='` has no meaning, despite being the end of meaningful characters in the sequence.\nSo we can safely ignore them when they appear in the sequence.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn decode(self: Base64,\n allocator: std.mem.Allocator,\n input: []const u8) ![]u8 {\n\n if (input.len == 0) {\n return \"\";\n }\n const n_output = try _calc_decode_length(input);\n var output = try allocator.alloc(u8, n_output);\n var count: u8 = 0;\n var iout: u64 = 0;\n var buf = [4]u8{ 0, 0, 0, 0 };\n\n for (0..input.len) |i| {\n buf[count] = self._char_index(input[i]);\n count += 1;\n if (count == 4) {\n output[iout] = (buf[0] << 2) + (buf[1] >> 4);\n if (buf[2] != 64) {\n output[iout + 1] = (buf[1] << 4) + (buf[2] >> 2);\n }\n if (buf[3] != 64) {\n output[iout + 2] = (buf[2] << 6) + buf[3];\n }\n iout += 3;\n count = 0;\n }\n }\n\n return output;\n}\n```\n:::\n\n\n\n\n\n## The end result\n\nNow that we have both `decode()` and `encode()` implemented. We have a fully functioning\nbase64 encoder/decoder implemented in Zig. Here is an usage example of our\n`Base64` struct with the `encode()` and `decode()` methods that we have implemented.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar memory_buffer: [1000]u8 = undefined;\nvar fba = std.heap.FixedBufferAllocator.init(\n &memory_buffer\n);\nconst allocator = fba.allocator();\n\nconst text = \"Testing some more stuff\";\nconst etext = \"VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=\";\nconst base64 = Base64.init();\nconst encoded_text = try base64.encode(\n allocator, text\n);\nconst decoded_text = try base64.decode(\n allocator, etext\n);\ntry stdout.print(\n \"Encoded text: {s}\\n\", .{encoded_text}\n);\ntry stdout.print(\n \"Decoded text: {s}\\n\", .{decoded_text}\n);\n```\n:::\n\n\n\n\n```\nEncoded text: VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=\nDecoded text: Testing some more stuff\n```\n\nYou can also see the full source code at once, by visiting the official repository of this book[^repo].\nMore precisely inside the `ZigExamples` folder[^zig-base64-algo].\n\n[^repo]: \n", - "supporting": [ - "01-base64_files" - ], + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/01-zig-weird/execute-results/html.json b/_freeze/Chapters/01-zig-weird/execute-results/html.json index f1342fff..7f926500 100644 --- a/_freeze/Chapters/01-zig-weird/execute-results/html.json +++ b/_freeze/Chapters/01-zig-weird/execute-results/html.json @@ -3,9 +3,7 @@ "result": { "engine": "knitr", "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it is still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. They really make it sometimes hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscure the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that get's compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e. it is where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contain Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nTherefore, Zig contains a native build system in it, and\nwe can use this build system to write small scripts in Zig,\nwhich describes the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e. creating new objects)\nare made in Zig. You can create a new object in Zig by using the following syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). At @sec-assignments we talk more about objects in general.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n```\n:::\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that at @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIs worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt is like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portable C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig build.zig.zon main src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nIn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e. the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. Thus, if you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith a \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, operations like accessing the `stdout` (or opening a file) on Windows\ndepends on resources that are available only at *runtime* (you will learn more about compile-time\nversus runtime at @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword at @sec-comptime.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation at a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues \n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described in @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig later in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig? \nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar to our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentation.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It is a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (on YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e. identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n age = 25;\n ~~^~~\n```\n\nIn contrast, if you use `var`, then, the object created is a variable object.\nWith `var` you can declare this object in your source code, and then,\nchange the value of this object how many times you want over future points\nin your source code.\n\nSo, using the same code example exposed above, if I change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it is an \"variable object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIs important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code use this object while it is uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object. \n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e. if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n const age = 15;\n ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to a special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It is discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also get's discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig have many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e. the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\nIs worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it have the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array. \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it is a slice that\naccess all elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhave 2 elements in it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" at @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth at @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially at @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned at @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e. the start and the end of this range)\nis known at compile-time, the slice object that get's created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nat @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that get's created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e. a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can \ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n 1, 2, 3, 4, 5,\n 6, 7, 8, 9, 10\n};\n// This slice have a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n```\n:::\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat get's created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, the `slice` object have a runtime known range, because the end index of the range\nis not known at compile time. In other words, the size of the array at `buffer` is not known\nat compile time. When we execute this program, the size of the array might be 10, or, it might be 12\ndepending on where we execute it. Therefore, we don't know at compile time if\nthe slice object have a range of size 10, or, a range of size 12.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var n: usize = 0;\n if (builtin.target.os.tag == .windows) {\n n = 10;\n } else {\n n = 12;\n }\n const buffer = try allocator.alloc(u64, n);\n const slice = buffer[0..];\n _ = slice;\n}\n```\n:::\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code have its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e. a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n y += 1;\n break :add_one y;\n};\nif (x == 124 and y == 124) {\n try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nIn summary, there are two types of string values that you care about in Zig, which are:\n\n- String literal values.\n- String objects.\n\nA string literal value is just a pointer to a null-terminated array of bytes (i.e. similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string into the data type of the value itself.\nTherefore, a string literal value have a data type in the format `*const [n:0]u8`. The `n` in the data type\nindicates the size of the string.\n\nOn the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes,\nor, in other words, a slice of `u8` values (slices were presented at @sec-arrays). Thus,\na string object have a data type of `[]u8` or `[]const u8`, depending if the string object is\nmarked as constant with `const`, or as variable with `var`.\n\nBecause a string object is essentially a slice, it means that a string object always contains two things:\na pointer to an array of bytes (i.e. `u8` values) that represents the string value; and also, a length value,\nwhich specifies the size of the slice, or, how many elements there is in the slice.\nIs worth to emphasize that the array of bytes in a string object is not null-terminated, like in a\nstring literal value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n\"A literal value\";\n// This is a string object:\nconst object: []const u8 = \"A string object\";\n```\n:::\n\n\n\n\nZig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example\";\n try stdout.print(\"Bytes that represents the string object: \", .{});\n for (string_object) |byte| {\n try stdout.print(\"{X} \", .{byte});\n }\n try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n 73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n### Strings in C\n\nAt first glance, a string literal value in Zig looks very similar to how C treats strings as well.\nIn more details, string values in C are treated internally as an array of arbitrary bytes,\nand this array is also null-terminated.\n\nBut one key difference between a Zig string literal and a C string, is that Zig also stores the length of\nthe string inside the object itself. In the case of a string literal value, this length is stored in the\ndata type of the value (i.e. the `n` variable in `[n:0]u8`). While, in a string object, the length is stored\nin the `len` attribute of the slice that represents the string object. This small detail makes your code safer,\nbecause it is much easier for the Zig compiler to check if you are trying to access an element that is\n\"out of bounds\", i.e. if your trying to access memory that does not belong to you.\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n char* array = \"An example of string in C\";\n int index = 0;\n while (1) {\n if (array[index] == '\\0') {\n break;\n }\n index++;\n }\n printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible. In a string object for example, you can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example of string literal in Zig\";\n try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it is a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const simple_array = [_]i32{1, 2, 3, 4};\n const string_obj: []const u8 = \"A string object\";\n std.debug.print(\n \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n );\n std.debug.print(\n \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n );\n std.debug.print(\n \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n );\n std.debug.print(\n \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nType 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons\n st [4]i32Type 4: []const u8\n```\n\n\n:::\n:::\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIs important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"Ⱥ\";\n _ = try stdout.write(\n \"Bytes that represents the string object: \"\n );\n for (string_object) |char| {\n try stdout.print(\"{X} \", .{char});\n }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n var iterator = utf8.iterator();\n while (iterator.nextCodepointSlice()) |codepoint| {\n try stdout.print(\n \"got codepoint {}\\n\",\n .{std.fmt.fmtSliceHexUpper(codepoint)},\n );\n }\n}\n\n```\n:::\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig at @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers at @sec-root-file and especially at @sec-assignments.\n- How strings work in Zig at @sec-zig-strings.\n- How to use arrays and slices at @sec-arrays.\n- How to import functionality from other Zig modules at @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* at @sec-structs-and-oop.\n- Basic control flow syntax at @sec-zig-control-flow.\n- Enums at @sec-enum;\n- Pointers and Optionals at @sec-pointer;\n- Error handling with `try` and `catch` at @sec-error-handling;\n- Unit tests at @sec-unittests;\n- Vectors at @sec-vectors-simd;\n- Build System at @sec-build-system;\n\n\n\n\n", - "supporting": [ - "01-zig-weird_files" - ], + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/03-structs/execute-results/html.json b/_freeze/Chapters/03-structs/execute-results/html.json index 543363c1..2629908d 100644 --- a/_freeze/Chapters/03-structs/execute-results/html.json +++ b/_freeze/Chapters/03-structs/execute-results/html.json @@ -2,10 +2,8 @@ "hash": "ddf3054f897e82f090f3aa7c5890ec78", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `role`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object has type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e. four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n```\n:::\n\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It is important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n else => {\n try stdout.print(\n \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n );\n },\n}\n```\n:::\n\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n```\n:::\n\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function gets executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, is worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression get's executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that get's printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n // code to execute\n}\n```\n:::\n\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It is the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e. the logical test is equal to false), the function raises an assertion error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e. constant) object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n x = x + 2;\n return x;\n}\n\npub fn main() !void {\n const y = add2(4);\n std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n x = x + 2;\n ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e. `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n const d: u32 = 2;\n x.* = x.* + d;\n}\n\npub fn main() !void {\n var x: u32 = 4;\n add2(&x);\n std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n pub fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n pub fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nEvery method that you declare in your struct that is marked with the keyword `pub`,\nbecomes a public method of this particular struct.\n\nSo every method that you create inside your struct, is, at first, a private method\nof that struct. Meaning that, this method can only be called from within this\nstruct. But, if you mark this method as public, with the keyword `pub`, then,\nyou can call the method directly from an instance of the `User` struct.\n\nIn other words, the functions marked by the keyword `pub`\nare members of the public API of that struct.\nFor example, if I did not mark the `print_name()` method as public,\nthen, I could not execute the line `u.print_name()`. Because I would\nnot be authorized to call this method directly in my code.\n\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n```\n:::\n\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt is not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n```\n:::\n\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods are affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e. changes the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n```\n:::\n\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it is not about the input object, it is about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special part in this place. More specifically, it is\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and it is\ntrying to infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n```\n:::\n\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e. we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it is explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file2ed34a8fc96.test_0...OKAll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe, and there are situations where these assumptions do not hold. For example,\nwhen casting an integer value into a float value, or vice-versa, it is not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file2ed34bfb9fa5.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e. they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file2ed324328e1f.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e. a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" get's executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object get's saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n .{ .max_threads = num_threads }\n);\n```\n:::\n", - "supporting": [ - "03-structs_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `role`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object has type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e. four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n```\n:::\n\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It is important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n else => {\n try stdout.print(\n \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n );\n },\n}\n```\n:::\n\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n```\n:::\n\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function gets executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, is worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression get's executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that get's printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n // code to execute\n}\n```\n:::\n\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It is the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e. the logical test is equal to false), the function raises an assertion error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e. constant) object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n x = x + 2;\n return x;\n}\n\npub fn main() !void {\n const y = add2(4);\n std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n x = x + 2;\n ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e. `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n const d: u32 = 2;\n x.* = x.* + d;\n}\n\npub fn main() !void {\n var x: u32 = 4;\n add2(&x);\n std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n pub fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n pub fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nEvery method that you declare in your struct that is marked with the keyword `pub`,\nbecomes a public method of this particular struct.\n\nSo every method that you create inside your struct, is, at first, a private method\nof that struct. Meaning that, this method can only be called from within this\nstruct. But, if you mark this method as public, with the keyword `pub`, then,\nyou can call the method directly from an instance of the `User` struct.\n\nIn other words, the functions marked by the keyword `pub`\nare members of the public API of that struct.\nFor example, if I did not mark the `print_name()` method as public,\nthen, I could not execute the line `u.print_name()`. Because I would\nnot be authorized to call this method directly in my code.\n\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n```\n:::\n\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt is not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n```\n:::\n\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods are affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e. changes the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n```\n:::\n\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it is not about the input object, it is about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special part in this place. More specifically, it is\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and it is\ntrying to infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n```\n:::\n\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e. we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it is explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file9f8940318094.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe, and there are situations where these assumptions do not hold. For example,\nwhen casting an integer value into a float value, or vice-versa, it is not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file9f8954828844.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e. they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file9f8944ca02e1.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e. a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" get's executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object get's saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n .{ .max_threads = num_threads }\n);\n```\n:::\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/03-unittests/execute-results/html.json b/_freeze/Chapters/03-unittests/execute-results/html.json index 73102f4a..37cb076d 100644 --- a/_freeze/Chapters/03-unittests/execute-results/html.json +++ b/_freeze/Chapters/03-unittests/execute-results/html.json @@ -2,10 +2,8 @@ "hash": "28d3cb0fae2775c98b5945221b3f555c", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Unit tests {#sec-unittests}\n\nIn this chapter, I want to dive in on how unit tests are done in\nZig. We are going to talk about what is the testing workflow in Zig, and\nalso, about the `test` command from the `zig` compiler.\n\n\n## Introducing the `test` block\n\nIn Zig, unit tests are written inside a `test` declaration, or, how I prefer to call it, inside a `test` block.\nEvery `test` block is written by using the keyword `test`.\nYou can optionally use a string literal to write a label, which is responsible for identifying\nthe specific group of unit tests that you are writing inside this specific `test` block.\n\nIn the example below, we are testing if the sum of two objects (`a` and `b`)\nis equal to 4. The `expect()` function from the Zig Standard Library\nis a function that receives a logical test as input. If this logical test\nresults in `true`, then, the test passes. But if it results\nin `false`, then, the test fails.\n\nYou can write any Zig code you want inside a `test` block.\nPart of this code might be some necessary commands to setup your testing\nenvironment, or just initializing some objects that you need to use\nin your unit tests.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest \"testing simple sum\" {\n const a: u8 = 2;\n const b: u8 = 2;\n try expect((a + b) == 4);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file153713a3190e.test.testing simple sum...OKA\n All 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\nYou can have multiple `test` blocks written on the same Zig module.\nAlso, you can mix `test` blocks with your source code, with no problems\nor consequences. If you mix `test` blocks with your normal source code,\nwhen you execute the `build`, `build-exe`, `build-obj` or `build-lib` commands from the\n`zig` compiler that we exposed at @sec-compile-code, these `test` blocks are automatically\nignored by the compiler.\n\nIn other words, the `zig` compiler builds and execute your unit tests only\nwhen you ask it to. By default, the compiler always ignore `test`\nblocks written in your Zig modules. The compiler normally checks only if\nthere are any syntax errors in these `test` blocks.\n\nIf you take a look at the source code for most of the files present in the\nZig Standard Library[^zig-std-lib], you can see that the `test` blocks\nare written together with the normal source code of the library.\nYou can see this for example, at the [`array_list` module](https://github.com/ziglang/zig/blob/master/lib/std/array_list.zig)[^zig-array].\nSo, the standard that the Zig developers decided to adopt\nis to keep their unit tests together with the source code\nof the functionality that they are testing.\n\nEach programmer might have a different opinion on this.\nSome of them might prefer to keep unit tests separate from the actual\nsource code of their application. If that is your case, you can\nsimply create a separate `tests` folder in your project, and\nstart writing Zig modules that contains only unit tests (as you would normally do\non a Python project with `pytest`, for example), and everything will work fine.\nIt boils down to which is your preference here.\n\n[^zig-std-lib]: \n[^zig-array]: \n\n\n## How to run your tests\n\nIf the `zig` compiler ignores any `test` block by default, how can\nyou compile and run your unit tests? The answer is the `test` command from\nthe `zig` compiler. By running the `zig test` command, the compiler will\nfind every instance of a `test` block in your Zig modules, and, it will\ncompile and run the unit tests that you wrote.\n\n\n```bash\nzig test simple_sum.zig\n```\n\n```\n1/1 simple_sum.test.testing simple sum... OK\nAll 1 tests passed.\n```\n\n\n## Testing memory allocations\n\nOne of the advantages of Zig is that it offers great tools\nthat help us, programmers, to avoid (but also detect) memory problems, such as\nmemory leaks and double-frees. The `defer` keyword\nis especially helpful in this regard.\n\nWhen developing your source code, you, the programmer, is responsible for making\nsure that your code do not produce such problems. However,\nyou can also use a special type of an allocator object in Zig\nthat is capable of automatically detecting such problems for you.\nThis is the `std.testing.allocator` object.\nThis allocator object offers some basic memory safety detection\nfeatures, which are capable of detecting memory leaks.\n\nAs we described at @sec-heap, to allocate memory on the heap, you need\nto use an allocator object, and your functions that use these objects to allocate memory\non the heap, should receive an allocator object as one of its inputs.\nEvery memory on the heap that you allocate using these allocator objects,\nmust also be freed using this same allocator object.\n\nSo, if you want to test the memory allocations performed by your functions,\nand make sure that you don't have problems in these allocations, you can simply\nwrite unit tests for these functions, where you provide the\n`std.testing.allocator` object as input to these functions.\n\nLook at the example below, where I'm defining a function that clearly causes\na memory leak. Because we allocate memory, but, at the same time,\nwe do not free this allocated memory at any point. So, when the function\nreturns, we lose the reference to the `buffer` object, which contains\nthe allocated memory, and, as a result, we can no longer free this memory.\n\nNotice that, inside a `test` block I execute this function with\nthe `std.testing.allocator`. The allocator object was capable\nof looking deeper in our program, and detecting the memory leak. As a result,\nthis allocator object returns an error message of \"memory leaked\", and also,\na stack trace showing the exact point where the memory was leaked.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nfn some_memory_leak(allocator: Allocator) !void {\n const buffer = try allocator.alloc(u32, 10);\n _ = buffer;\n // Return without freeing the\n // allocated memory\n}\n\ntest \"memory leak\" {\n const allocator = std.testing.allocator;\n try some_memory_leak(allocator);\n}\n```\n:::\n\n\n\n\n```\nTest [1/1] leak_memory.test.memory leak...\n [gpa] (err): memory address 0x7c1fddf39000 leaked: \n./ZigExamples/debugging/leak_memory.zig:4:39: 0x10395f2\n const buffer = try allocator.alloc(u32, 10);\n ^\n./ZigExamples/debugging/leak_memory.zig:12:25: 0x10398ea\n try some_memory_leak(allocator);\n\n... more stack trace\n```\n\n\n## Testing errors\n\nOne common style of unit tests are those that look for\nspecific errors in your functions. In other words, you write\na unit test that tries to assert if a specific function call\nreturns any error, or a specific type of error.\n\nIn C++ you would normally write this style of unit tests using, for example,\nthe functions `REQUIRE_THROWS()` or `CHECK_THROWS()` from the [`Catch2` test framework](https://github.com/catchorg/Catch2/tree/devel)[^catch2].\nIn the case of a Python project, you would probably use the\n[`raises()` function from `pytest`](https://docs.pytest.org/en/7.1.x/reference/reference.html#pytest-raises)[^pytest].\nWhile in Rust, you would probably use `assert_eq!()` in conjunction with `Err()`.\n\n[^pytest]: \n[^catch2]: \n\n\nBut in Zig, we use the `expectError()` function, from the `std.testing` module.\nWith this function, you can test if a specific function call returns the exact\ntype of error that you expect it to return. To use this function, you first write\n`try expectError()`. Then, on the first argument, you provide the type of error that you\nare expecting from the function call. Then, on the second argument, you write\nthe function call that you expect to fail.\n\nThe code example below demonstrates such type of unit test in Zig.\nNotice that, inside the function `alloc_error()` we are allocating\n100 bytes of memory, or, an array of 100 elements, for the object `ibuffer`. However,\nin the `test` block, we are using the `FixedBufferAllocator()`\nallocator object, which is limited to 10 bytes of space, because\nthe object `buffer`, which we provided to the allocator object,\nhave only 10 bytes of space.\n\nThat is why, the `alloc_error()` function raises an `OutOfMemory` error\non this case.\nBecause this function is trying to allocate more space than the allocator\nobject allows.\nSo, in essence, we are testing for a specific type of error,\nwhich is `OutOfMemory`. If the `alloc_error()` function returns any other type of error,\nthen, the `expectError()` function would make the entire test fail.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst expectError = std.testing.expectError;\nfn alloc_error(allocator: Allocator) !void {\n var ibuffer = try allocator.alloc(u8, 100);\n defer allocator.free(ibuffer);\n ibuffer[0] = 2;\n}\n\ntest \"testing error\" {\n var buffer: [10]u8 = undefined;\n var fba = std.heap.FixedBufferAllocator.init(&buffer);\n const allocator = fba.allocator();\n try expectError(error.OutOfMemory, alloc_error(allocator));\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file1537546f248.test.testing error...OKAll 1 t\n tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## Testing simple equalities\n\nIn Zig, there are some different ways you can test for an equality.\nYou already saw that we can use `expect()` with the logical operator `==`\nto essentially reproduce an equality test. But we also have\nsome other helper functions that you should know about, especially\n`expectEqual()`, `expectEqualSlices()` and `expectEqualStrings()`.\n\n\nThe `expectEqual()` function, as the name suggests, is a classic\ntest equality function. It receives two objects as input. The first\nobject is the value that you expect to be in the second object.\nWhile second object is the object you have, or, the object that your application\nproduced as result. So, with `expectEqual()` you are essentially\ntesting if the values stored inside these two objects\nare equal or not.\n\nYou can see in the example below that, the test performed by\n`expectEqual()` failed. Because the objects `v1` and `v2` contain\ndifferent values in them.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"values are equal?\" {\n const v1 = 15;\n const v2 = 18;\n try std.testing.expectEqual(v1, v2);\n}\n```\n:::\n\n\n\n\n```\n1/1 ve.test.values are equal?...\n expected 15, found 18\n FAIL (TestExpectedEqual)\nve.zig:5:5: test.values are equal? (test)\n try std.testing.expectEqual(v1, v2);\n ^\n0 passed; 0 skipped; 1 failed.\n```\n\n\nAlthough useful, the `expectEqual()` function does not work with arrays.\nFor testing if two arrays are equal, you should use the `expectEqualSlices()`\nfunction instead. This function have three arguments. First, you provide\nthe data type contained in both arrays that you are trying to compare.\nWhile the second and third arguments corresponds to the array objects that you want to compare.\n\nIn the example below, we are using this function to test if two array\nobjects (`array1` and `array2`) are equal or not. Since they\nare in fact equal, the unit test passed with no errors.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"arrays are equal?\" {\n const array1 = [3]u32{1, 2, 3};\n const array2 = [3]u32{1, 2, 3};\n try std.testing.expectEqualSlices(\n u32, &array1, &array2\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file15377bbafb73.test.arrays are equal?...OKAl\n ll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\nAt last, you might also want to use the `expectEqualStrings()` function.\nAs the name suggests, you can use this function to test if two strings\nare equal or not. Just provide the two string objects that you want to compare,\nas inputs to the function.\n\nIf the function finds any existing differences between the two strings,\nthen, the function will raise an error, and also, print an error message\nthat shows the exact difference between the two string objects provided,\nas the example below demonstrates:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"strings are equal?\" {\n const str1 = \"hello, world!\";\n const str2 = \"Hello, world!\";\n try std.testing.expectEqualStrings(\n str1, str2\n );\n}\n```\n:::\n\n\n\n\n```\n1/1 t.test.strings are equal?... \n====== expected this output: =========\nhello, world!␃\n======== instead found this: =========\nHello, world!␃\n======================================\nFirst difference occurs on line 1:\nexpected:\nhello, world!\n^ ('\\x68')\nfound:\nHello, world!\n^ ('\\x48')\n```\n\n", - "supporting": [ - "03-unittests_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Unit tests {#sec-unittests}\n\nIn this chapter, I want to dive in on how unit tests are done in\nZig. We are going to talk about what is the testing workflow in Zig, and\nalso, about the `test` command from the `zig` compiler.\n\n\n## Introducing the `test` block\n\nIn Zig, unit tests are written inside a `test` declaration, or, how I prefer to call it, inside a `test` block.\nEvery `test` block is written by using the keyword `test`.\nYou can optionally use a string literal to write a label, which is responsible for identifying\nthe specific group of unit tests that you are writing inside this specific `test` block.\n\nIn the example below, we are testing if the sum of two objects (`a` and `b`)\nis equal to 4. The `expect()` function from the Zig Standard Library\nis a function that receives a logical test as input. If this logical test\nresults in `true`, then, the test passes. But if it results\nin `false`, then, the test fails.\n\nYou can write any Zig code you want inside a `test` block.\nPart of this code might be some necessary commands to setup your testing\nenvironment, or just initializing some objects that you need to use\nin your unit tests.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest \"testing simple sum\" {\n const a: u8 = 2;\n const b: u8 = 2;\n try expect((a + b) == 4);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filea5b06c1ec326.test.testing simple sum...OKA\n All 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\nYou can have multiple `test` blocks written on the same Zig module.\nAlso, you can mix `test` blocks with your source code, with no problems\nor consequences. If you mix `test` blocks with your normal source code,\nwhen you execute the `build`, `build-exe`, `build-obj` or `build-lib` commands from the\n`zig` compiler that we exposed at @sec-compile-code, these `test` blocks are automatically\nignored by the compiler.\n\nIn other words, the `zig` compiler builds and execute your unit tests only\nwhen you ask it to. By default, the compiler always ignore `test`\nblocks written in your Zig modules. The compiler normally checks only if\nthere are any syntax errors in these `test` blocks.\n\nIf you take a look at the source code for most of the files present in the\nZig Standard Library[^zig-std-lib], you can see that the `test` blocks\nare written together with the normal source code of the library.\nYou can see this for example, at the [`array_list` module](https://github.com/ziglang/zig/blob/master/lib/std/array_list.zig)[^zig-array].\nSo, the standard that the Zig developers decided to adopt\nis to keep their unit tests together with the source code\nof the functionality that they are testing.\n\nEach programmer might have a different opinion on this.\nSome of them might prefer to keep unit tests separate from the actual\nsource code of their application. If that is your case, you can\nsimply create a separate `tests` folder in your project, and\nstart writing Zig modules that contains only unit tests (as you would normally do\non a Python project with `pytest`, for example), and everything will work fine.\nIt boils down to which is your preference here.\n\n[^zig-std-lib]: \n[^zig-array]: \n\n\n## How to run your tests\n\nIf the `zig` compiler ignores any `test` block by default, how can\nyou compile and run your unit tests? The answer is the `test` command from\nthe `zig` compiler. By running the `zig test` command, the compiler will\nfind every instance of a `test` block in your Zig modules, and, it will\ncompile and run the unit tests that you wrote.\n\n\n```bash\nzig test simple_sum.zig\n```\n\n```\n1/1 simple_sum.test.testing simple sum... OK\nAll 1 tests passed.\n```\n\n\n## Testing memory allocations\n\nOne of the advantages of Zig is that it offers great tools\nthat help us, programmers, to avoid (but also detect) memory problems, such as\nmemory leaks and double-frees. The `defer` keyword\nis especially helpful in this regard.\n\nWhen developing your source code, you, the programmer, is responsible for making\nsure that your code do not produce such problems. However,\nyou can also use a special type of an allocator object in Zig\nthat is capable of automatically detecting such problems for you.\nThis is the `std.testing.allocator` object.\nThis allocator object offers some basic memory safety detection\nfeatures, which are capable of detecting memory leaks.\n\nAs we described at @sec-heap, to allocate memory on the heap, you need\nto use an allocator object, and your functions that use these objects to allocate memory\non the heap, should receive an allocator object as one of its inputs.\nEvery memory on the heap that you allocate using these allocator objects,\nmust also be freed using this same allocator object.\n\nSo, if you want to test the memory allocations performed by your functions,\nand make sure that you don't have problems in these allocations, you can simply\nwrite unit tests for these functions, where you provide the\n`std.testing.allocator` object as input to these functions.\n\nLook at the example below, where I'm defining a function that clearly causes\na memory leak. Because we allocate memory, but, at the same time,\nwe do not free this allocated memory at any point. So, when the function\nreturns, we lose the reference to the `buffer` object, which contains\nthe allocated memory, and, as a result, we can no longer free this memory.\n\nNotice that, inside a `test` block I execute this function with\nthe `std.testing.allocator`. The allocator object was capable\nof looking deeper in our program, and detecting the memory leak. As a result,\nthis allocator object returns an error message of \"memory leaked\", and also,\na stack trace showing the exact point where the memory was leaked.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nfn some_memory_leak(allocator: Allocator) !void {\n const buffer = try allocator.alloc(u32, 10);\n _ = buffer;\n // Return without freeing the\n // allocated memory\n}\n\ntest \"memory leak\" {\n const allocator = std.testing.allocator;\n try some_memory_leak(allocator);\n}\n```\n:::\n\n\n\n\n```\nTest [1/1] leak_memory.test.memory leak...\n [gpa] (err): memory address 0x7c1fddf39000 leaked: \n./ZigExamples/debugging/leak_memory.zig:4:39: 0x10395f2\n const buffer = try allocator.alloc(u32, 10);\n ^\n./ZigExamples/debugging/leak_memory.zig:12:25: 0x10398ea\n try some_memory_leak(allocator);\n\n... more stack trace\n```\n\n\n## Testing errors\n\nOne common style of unit tests are those that look for\nspecific errors in your functions. In other words, you write\na unit test that tries to assert if a specific function call\nreturns any error, or a specific type of error.\n\nIn C++ you would normally write this style of unit tests using, for example,\nthe functions `REQUIRE_THROWS()` or `CHECK_THROWS()` from the [`Catch2` test framework](https://github.com/catchorg/Catch2/tree/devel)[^catch2].\nIn the case of a Python project, you would probably use the\n[`raises()` function from `pytest`](https://docs.pytest.org/en/7.1.x/reference/reference.html#pytest-raises)[^pytest].\nWhile in Rust, you would probably use `assert_eq!()` in conjunction with `Err()`.\n\n[^pytest]: \n[^catch2]: \n\n\nBut in Zig, we use the `expectError()` function, from the `std.testing` module.\nWith this function, you can test if a specific function call returns the exact\ntype of error that you expect it to return. To use this function, you first write\n`try expectError()`. Then, on the first argument, you provide the type of error that you\nare expecting from the function call. Then, on the second argument, you write\nthe function call that you expect to fail.\n\nThe code example below demonstrates such type of unit test in Zig.\nNotice that, inside the function `alloc_error()` we are allocating\n100 bytes of memory, or, an array of 100 elements, for the object `ibuffer`. However,\nin the `test` block, we are using the `FixedBufferAllocator()`\nallocator object, which is limited to 10 bytes of space, because\nthe object `buffer`, which we provided to the allocator object,\nhave only 10 bytes of space.\n\nThat is why, the `alloc_error()` function raises an `OutOfMemory` error\non this case.\nBecause this function is trying to allocate more space than the allocator\nobject allows.\nSo, in essence, we are testing for a specific type of error,\nwhich is `OutOfMemory`. If the `alloc_error()` function returns any other type of error,\nthen, the `expectError()` function would make the entire test fail.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst expectError = std.testing.expectError;\nfn alloc_error(allocator: Allocator) !void {\n var ibuffer = try allocator.alloc(u8, 100);\n defer allocator.free(ibuffer);\n ibuffer[0] = 2;\n}\n\ntest \"testing error\" {\n var buffer: [10]u8 = undefined;\n var fba = std.heap.FixedBufferAllocator.init(&buffer);\n const allocator = fba.allocator();\n try expectError(error.OutOfMemory, alloc_error(allocator));\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filea5b059c00874.test.testing error...OKAll 1 \n tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## Testing simple equalities\n\nIn Zig, there are some different ways you can test for an equality.\nYou already saw that we can use `expect()` with the logical operator `==`\nto essentially reproduce an equality test. But we also have\nsome other helper functions that you should know about, especially\n`expectEqual()`, `expectEqualSlices()` and `expectEqualStrings()`.\n\n\nThe `expectEqual()` function, as the name suggests, is a classic\ntest equality function. It receives two objects as input. The first\nobject is the value that you expect to be in the second object.\nWhile second object is the object you have, or, the object that your application\nproduced as result. So, with `expectEqual()` you are essentially\ntesting if the values stored inside these two objects\nare equal or not.\n\nYou can see in the example below that, the test performed by\n`expectEqual()` failed. Because the objects `v1` and `v2` contain\ndifferent values in them.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"values are equal?\" {\n const v1 = 15;\n const v2 = 18;\n try std.testing.expectEqual(v1, v2);\n}\n```\n:::\n\n\n\n\n```\n1/1 ve.test.values are equal?...\n expected 15, found 18\n FAIL (TestExpectedEqual)\nve.zig:5:5: test.values are equal? (test)\n try std.testing.expectEqual(v1, v2);\n ^\n0 passed; 0 skipped; 1 failed.\n```\n\n\nAlthough useful, the `expectEqual()` function does not work with arrays.\nFor testing if two arrays are equal, you should use the `expectEqualSlices()`\nfunction instead. This function have three arguments. First, you provide\nthe data type contained in both arrays that you are trying to compare.\nWhile the second and third arguments corresponds to the array objects that you want to compare.\n\nIn the example below, we are using this function to test if two array\nobjects (`array1` and `array2`) are equal or not. Since they\nare in fact equal, the unit test passed with no errors.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"arrays are equal?\" {\n const array1 = [3]u32{1, 2, 3};\n const array2 = [3]u32{1, 2, 3};\n try std.testing.expectEqualSlices(\n u32, &array1, &array2\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filea5b054e42b80.test.arrays are equal?...OKAl\n ll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\nAt last, you might also want to use the `expectEqualStrings()` function.\nAs the name suggests, you can use this function to test if two strings\nare equal or not. Just provide the two string objects that you want to compare,\nas inputs to the function.\n\nIf the function finds any existing differences between the two strings,\nthen, the function will raise an error, and also, print an error message\nthat shows the exact difference between the two string objects provided,\nas the example below demonstrates:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"strings are equal?\" {\n const str1 = \"hello, world!\";\n const str2 = \"Hello, world!\";\n try std.testing.expectEqualStrings(\n str1, str2\n );\n}\n```\n:::\n\n\n\n\n```\n1/1 t.test.strings are equal?... \n====== expected this output: =========\nhello, world!␃\n======== instead found this: =========\nHello, world!␃\n======================================\nFirst difference occurs on line 1:\nexpected:\nhello, world!\n^ ('\\x68')\nfound:\nHello, world!\n^ ('\\x48')\n```\n\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/05-pointers/execute-results/html.json b/_freeze/Chapters/05-pointers/execute-results/html.json index bce4789c..12c21289 100644 --- a/_freeze/Chapters/05-pointers/execute-results/html.json +++ b/_freeze/Chapters/05-pointers/execute-results/html.json @@ -2,7 +2,7 @@ "hash": "8fdb1694a88afd9b81c337b29ec84c86", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Pointers and Optionals {#sec-pointer}\n\nOn our next project we are going to build a HTTP server from scratch.\nBut in order to do that, we need to learn more about pointers and how they work in Zig.\nPointers in Zig are similar to pointers in C. But they come with some extra advantages in Zig.\n\nA pointer is an object that contains a memory address. This memory address is the address where\na particular value is stored in memory. It can be any value. Most of the times,\nit is a value that comes from another object (or variable) present in our code.\n\nIn the example below, I'm creating two objects (`number` and `pointer`).\nThe `pointer` object contains the memory address where the value of the `number` object\n(the number 5) is stored. So, that is a pointer in a nutshell. It is a memory\naddress that points to a particular existing value in the memory. You could\nalso say, that, the `pointer` object points to the memory address where the `number` object is\nstored.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\n_ = pointer;\n```\n:::\n\n\n\n\n\nWe create a pointer object in Zig by using the `&` operator. When you put this operator\nbefore the name of an existing object, you get the memory address of this object as result.\nWhen you store this memory address inside a new object, this new object becomes a pointer object.\nBecause it stores a memory address.\n\nPeople mostly use pointers as an alternative way to access a particular value.\nFor example, I can use the `pointer` object to access the value stored by\nthe `number` object. This operation of accessing the value that the\npointer \"points to\" is normally called of *dereferencing the pointer*.\nWe can dereference a pointer in Zig by using the `*` method of the pointer object. Like in the example\nbelow, where we take the number 5 pointed by the `pointer` object,\nand double it.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\nconst doubled = 2 * pointer.*;\nstd.debug.print(\"{d}\\n\", .{doubled});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n10\n```\n\n\n:::\n:::\n\n\n\n\n\n\nThis syntax to dereference the pointer is nice. Because we can easily chain it with\nmethods of the value pointed by the pointer. We can use the `User` struct that we have\ncreated at @sec-structs-and-oop as an example. If you comeback to that section,\nyou will see that this struct have a method named `print_name()`.\n\nSo, for example, if we have an user object, and a pointer that points to this user object,\nwe can use the pointer to access this user object, and, at the same time, call the method `print_name()`\non it, by chaining the dereference method (`*`) with the `print_name()` method. Like in the\nexample below:\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst u = User.init(1, \"pedro\", \"email@gmail.com\");\nconst pointer = &u;\ntry pointer.*.print_name();\n```\n:::\n\n\n\n\n\n```\npedro\n```\n\nWe can also use pointers to effectively alter the value of an object.\nFor example, I could use the `pointer` object to set\nthe value of the object `number` to 6, like in the example below.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\n\n\n\n\nTherefore, as I mentioned earlier, people use pointers as an alternative way to access a particular value.\nAnd they use it especially when they do not want to \"move\" these values around. There are situations where,\nyou want to access a particular value in a different scope (i.e. a different location) of your code,\nbut you do not want to \"move\" this value to this new scope (or location) that you are in.\n\nThis matters especially if this value is big in size. Because if it is, then,\nmoving this value becomes an expensive operation to do.\nThe computer will have to spend a considerable amount of time\ncopying this value to this new location.\n\nTherefore, many programmers prefer to avoid this heavy operation of copying the value\nto the new location, by accessing this value through pointers.\nWe are going to talk more about this \"moving operation\" over the next sections.\nFor now, just keep in mind that avoiding this \"move operation\" is\none of main reasons why pointers are used in programming languages.\n\n\n\n\n\n## Constant objects vs variable objects {#sec-pointer-var}\n\nYou can have a pointer that points to a constant object, or, a pointer that points to a variable object.\nBut regardless of who this pointer is, a pointer **must always respect the characteristics of the object that it points to**.\nAs a consequence, if the pointer points to a constant object, then, you cannot use this pointer\nto change the value that it points to. Because it points to a value that is constant. As we discussed at @sec-assignments, you cannot\nchange a value that is constant.\n\nFor example, if I have a `number` object, which is constant, I cannot execute\nthe expression below where I'm trying to change the value of `number` to 6 through\nthe `pointer` object. As demonstrated below, when you try to do something\nlike that, you get a compile time error:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number = 5;\nconst pointer = &number;\npointer.* = 6;\n```\n:::\n\n\n\n\n\n```\np.zig:6:12: error: cannot assign to constant\n pointer.* = 6;\n```\n\nIf I change the `number` object to be a variable object, by introducing the `var` keyword,\nthen, I can successfully change the value of this object through a pointer, as demonstrated below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\n\n\n\nYou can see this relationship between \"constant versus variable\" on the data type of\nyour pointer object. In other words, the data type of a pointer object already gives you\nsome clues about whether the value that it points to is constant or not.\n\nWhen a pointer object points to a constant value, then, this pointer have a data type `*const T`,\nwhich means \"a pointer to a constant value of type `T`\".\nIn contrast, if the pointer points to a variable value, then, the type of the pointer is usually `*T`, which is\nsimply \"a pointer to a value of type `T`\".\nHence, whenever you see a pointer object whose data type is in the format `*const T`, then,\nyou know that you cannot use this pointer to change the value that it points to.\nBecause this pointer points to a constant value of type `T`.\n\n\nWe have talked about the value pointed by the pointer being constant or not,\nand the consequences that arises from it. But, what about the pointer object itself? I mean, what happens\nif the pointer object itself is constant or not? Think about it.\nWe can have a constant pointer that points to a constant value.\nBut we can also have a variable pointer that points to a constant value. And vice-versa.\n\nUntil this point, the `pointer` object was always constant,\nbut what this means for us? What is the consequence of the\n`pointer` object being constant? The consequence is that\nwe cannot change the pointer object, because it is constant. We can use the\npointer object in multiple ways, but we cannot change the\nmemory address that is inside this pointer object.\n\nHowever, if we mark the `pointer` object as a variable object,\nthen, we can change the memory address pointed by this `pointer` object.\nThe example below demonstrates that. Notice that the object pointed\nby the `pointer` object changes from `c1` to `c2`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c1: u8 = 5;\nconst c2: u8 = 6;\nvar pointer = &c1;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\npointer = &c2;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\n```\n:::\n\n\n\n\n\n```\n5\n6\n```\n\nThus, by setting the `pointer` object to a `var` or `const` object,\nyou specify if the memory address contained in this pointer object can change or not\nin your program. On the other side, you can change the value pointed by the pointer,\nif, and only if this value is stored in a variable object. If this value\nis in a constant object, then, you cannot change this value through a pointer.\n\n\n## Types of pointer\n\nIn Zig, there are two types of pointers [@zigdocs], which are:\n\n- single-item pointer (`*`);\n- many-item pointer (`[*]`);\n\n\nSingle-item pointer objects are objects whose data types are in the format `*T`.\nSo, for example, if an object have a data type `*u32`, it means that, this\nobject contains a single-item pointer that points to an unsigned 32-bit integer value.\nAs another example, if an object have type `*User`, then, it contains\na single-item pointer to an `User` value.\n\nIn contrast, many-item pointers are objects whose data types are in the format `[*]T`.\nNotice that the star symbol (`*`) is now inside a pair of brackets (`[]`). If the star\nsymbol is inside a pair of brackets, you know that this object is a many-item pointer.\n\nWhen you apply the `&` operator over an object, you will always get a single-item pointer.\nMany-item pointers are more of a \"internal type\" of the language, more closely\nrelated to slices. So, when you deliberately create a pointer with the `&` operator,\nyou always get a single-item pointer as result.\n\n\n\n## Pointer arithmetic\n\nPointer arithmetic is available in Zig, and they work the same way they work in C.\nWhen you have a pointer that points to an array, the pointer usually points to\nthe first element in the array, and you can use pointer arithmetic to\nadvance this pointer and access the other elements in the array.\n\n\nNotice in the example below, that initially, the `ptr` object was pointing\nto the first element in the array `ar`. But then, I started to walk through the array, by advancing\nthe pointer with simple pointer arithmetic.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{ 1, 2, 3, 4 };\nvar ptr: [*]const i32 = &ar;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\n```\n:::\n\n\n\n\n\n```\n1\n2\n3\n```\n\nAlthough you can create a pointer to an array like that, and\nstart to walk through this array by using pointer arithmetic,\nin Zig, we prefer to use slices, which were presented at @sec-arrays.\n\nBehind the hood, slices already are pointers,\nand they also come with the `len` property, which indicates\nhow many elements are in the slice. This is good because the `zig` compiler\ncan use it to check for potential buffer overflows, and other problems like that.\n\nAlso, you don't need to use pointer arithmetic to walk through the elements\nof a slice. You can simply use the `slice[index]` syntax to directly access\nany element you want in the slice.\nAs I mentioned at @sec-arrays, you can get a slice from an array by using\na range selector inside brackets. In the example below, I'm creating\na slice (`sl`) that covers the entire `ar` array. I can access any\nelement of `ar` from this slice, and, the slice itself already is a pointer\nbehind the hood.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{1,2,3,4};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\n\n\n## Optionals and Optional Pointers\n\nLet's talk about optionals and how they relate to pointers in Zig.\nBy default, objects in Zig are **non-nullable**. This means that, in Zig,\nyou can safely assume that any object in your source code is not null.\n\nThis is a powerful feature of Zig when you compare it to the developer experience in C.\nBecause in C, any object can be null at any point, and, as consequence, a pointer in C\nmight point to a null value. This is a common source of undefined behaviour in C.\nWhen programmers work with pointers in C, they have to constantly check if\ntheir pointers are pointing to null values or not.\n\nIf for some reason, your Zig code produces a null value somewhere, and, this null\nvalue ends up in an object that is non-nullable, a runtime error is always\nraised by your Zig program. Take the program below as an example.\nThe `zig` compiler can see the `null` value at compile time, and, as result,\nit raises a compile time error. But, if a `null` value is raised during\nruntime, a runtime error is also raised by the Zig program, with a\n\"attempt to use null value\" message.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nnumber = null;\n```\n:::\n\n\n\n\n```\np5.zig:5:14: error: expected type 'u8',\n found '@TypeOf(null)'\n number = null;\n ^~~~\n```\n\n\nYou don't get this type of safety in C.\nIn C, you don't get warnings or errors about null values being produced in your program.\nIf for some reason, your code produces a null value in C, most of the times, you end up getting a segmentation fault error\nas result, which can mean many things.\nThat is why programmers have to constantly check for null values in C.\n\nPointers in Zig are also, by default, **non-nullable**. This is another amazing\nfeature in Zig. So, you can safely assume that any pointer that you create in\nyour Zig code is pointing to a non-null value.\nTherefore, you don't have this heavy work of checking if the pointers you create\nin Zig are pointing to a null value.\n\n\n### What are optionals?\n\nOk, we know now that all objects are non-nullable by default in Zig.\nBut what if we actually need to use an object that might receive a null value?\nHere is where optionals come in.\n\nAn optional object in Zig is an object that can be null.\nTo mark an object as optional, we use the `?` operator. When you put\nthis `?` operator right before the data type of an object, you transform\nthis data type into an optional data type, and the object becomes an optional object.\n\nTake the snippet below as an example. We are creating a new variable object\ncalled `num`. This object have the data type `?i32`, which means that,\nthis object contains either a signed 32-bit integer (`i32`), or, a null value.\nBoth alternatives are valid values to the `num` object.\nThat is why, I can actually change the value of this object to null, and,\nno errors are raised by the `zig` compiler, as demonstrated below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\nnum = null;\n```\n:::\n\n\n\n\n\n### Optional pointers\n\nYou can also mark a pointer object as an optional pointer, meaning that,\nthis object contains either a null value, or, a pointer that points to a value.\nWhen you mark a pointer as optional, the data type of this pointer object\nbecomes `?*const T` or `?*T`, depending if the value pointed by the pointer\nis a constant value or not. The `?` identifies the object as optional, while\nthe `*` identifies it as a pointer object.\n\nIn the example below, we are creating a variable object named `num`, and an\noptional pointer object named `ptr`. Notice that the data type of the object\n`ptr` indicates that it is either a null value, or a pointer to an `i32` value.\nAlso, notice that the pointer object (`ptr`) can be marked as optional, even if\nthe object `num` is not optional.\n\nWhat this code tells us is that, the `num` variable will never contain a null value.\nThis variable will always contain a valid `i32` value. But in contrast, the `ptr` object might contain either a null\nvalue, or, a pointer to an `i32` value.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: i32 = 5;\nvar ptr: ?*i32 = #\nptr = null;\nnum = 6;\n```\n:::\n\n\n\n\n\nBut what happens if we turn the table, and mark the `num` object as optional,\ninstead of the pointer object. If we do that, then, the pointer object is\nnot optional anymore. It would be a similar (although different) result. Because then, we would have\na pointer to an optional value. In other words, a pointer to a value that is either a\nnull value, or, a not-null value.\n\nIn the example below, we are recreating this idea. Now, the `ptr` object\nhave a data type of `*?i32`, instead of `?*i32`. Notice that the `*` symbol comes before of `?`\nthis time. So now, we have a pointer that points to a value that is either null\n, or, a signed 32-bit integer.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\n// ptr have type `*?i32`, instead of `?*i32`.\nconst ptr = #\n_ = ptr;\n```\n:::\n\n\n\n\n\n\n### Null handling in optionals {#sec-null-handling}\n\nWhen you have an optional object in your Zig code, you have to explicitly handle\nthe possibility of this object being null. It is like error-handling with `try` and `catch`.\nIn Zig you also have to handle null values like if they were a type of error.\n\nWe can do that, by using either:\n\n- an if statement, like you would do in C.\n- the `orelse` keyword.\n- unwrap the optional value with the `?` method.\n\nWhen you use an if statement, you use a pair of pipes\nto unwrap the optional value, and use this \"unwrapped object\"\ninside the if block.\nUsing the example below as a reference, if the object `num` is null,\nthen, the code inside the if statement is not executed. Otherwise,\nthe if statement will unwrap the object `num` into the `not_null_num`\nobject. This `not_null_num` object is guaranteed to be not null inside\nthe scope of the if statement.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst num: ?i32 = 5;\nif (num) |not_null_num| {\n try stdout.print(\"{d}\\n\", .{not_null_num});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n5\n```\n\n\n:::\n:::\n\n\n\n\n\nNow, the `orelse` keyword behaves like a binary operator. You connect two expressions with this keyword.\nOn the left side of `orelse`, you provide the expression that might result\nin a null value, and on the right side of `orelse`, you provide another expression\nthat will not result in a null value.\n\nThe idea behind the `orelse` keyword is: if the expression on the left side\nresult in a not-null value, then, this not-null value is used. However,\nif this expression on the left side result in a null value, then, the value\nof the expression on the right side is used instead.\n\nLooking at the example below, since the `x` object is currently null, the\n`orelse` decided to use the alternative value, which is the number 15.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x: ?i32 = null;\nconst dbl = (x orelse 15) * 2;\ntry stdout.print(\"{d}\\n\", .{dbl});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n30\n```\n\n\n:::\n:::\n\n\n\n\n\nYou can use the if statement or the `orelse` keyword, when you want to\nsolve (or deal with) this null value. However, if there is no clear solution\nto this null value, and the most logic and sane path is to simply panic\nand raise a loud error in your program when this null value is encountered,\nyou can use the `?` method of your optional object.\n\nIn essence, when you use this `?` method, the optional object is unwrapped.\nIf a not-null value is found in the optional object, then, this not-null value is used.\nOtherwise, the `unreachable` keyword is used. You can read more about this\n[`unreacheable` keyword at the official documentation](https://ziglang.org/documentation/master/#unreachable)[^un-docs].\nBut in essence, when you build your Zig source code using the build modes `ReleaseSafe` or `Debug`, this\n`unreacheable` keyword causes the program to panic and raise an error during runtime,\nlike in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn return_null(n: i32) ?i32 {\n if (n == 5) return null;\n return n;\n}\n\npub fn main() !void {\n const x: i32 = 5;\n const y: ?i32 = return_null(x);\n try stdout.print(\"{d}\\n\", .{y.?});\n}\n```\n:::\n\n\n\n\n\n```\nthread 12767 panic: attempt to use null value\np7.zig:12:34: 0x103419d in main (p7):\n try stdout.print(\"{d}\\n\", .{y.?});\n ^\n```\n\n\n[^un-docs]: .\n\n\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Pointers and Optionals {#sec-pointer}\n\nOn our next project we are going to build a HTTP server from scratch.\nBut in order to do that, we need to learn more about pointers and how they work in Zig.\nPointers in Zig are similar to pointers in C. But they come with some extra advantages in Zig.\n\nA pointer is an object that contains a memory address. This memory address is the address where\na particular value is stored in memory. It can be any value. Most of the times,\nit is a value that comes from another object (or variable) present in our code.\n\nIn the example below, I'm creating two objects (`number` and `pointer`).\nThe `pointer` object contains the memory address where the value of the `number` object\n(the number 5) is stored. So, that is a pointer in a nutshell. It is a memory\naddress that points to a particular existing value in the memory. You could\nalso say, that, the `pointer` object points to the memory address where the `number` object is\nstored.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\n_ = pointer;\n```\n:::\n\n\n\n\nWe create a pointer object in Zig by using the `&` operator. When you put this operator\nbefore the name of an existing object, you get the memory address of this object as result.\nWhen you store this memory address inside a new object, this new object becomes a pointer object.\nBecause it stores a memory address.\n\nPeople mostly use pointers as an alternative way to access a particular value.\nFor example, I can use the `pointer` object to access the value stored by\nthe `number` object. This operation of accessing the value that the\npointer \"points to\" is normally called of *dereferencing the pointer*.\nWe can dereference a pointer in Zig by using the `*` method of the pointer object. Like in the example\nbelow, where we take the number 5 pointed by the `pointer` object,\nand double it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\nconst doubled = 2 * pointer.*;\nstd.debug.print(\"{d}\\n\", .{doubled});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n10\n```\n\n\n:::\n:::\n\n\n\n\n\nThis syntax to dereference the pointer is nice. Because we can easily chain it with\nmethods of the value pointed by the pointer. We can use the `User` struct that we have\ncreated at @sec-structs-and-oop as an example. If you comeback to that section,\nyou will see that this struct have a method named `print_name()`.\n\nSo, for example, if we have an user object, and a pointer that points to this user object,\nwe can use the pointer to access this user object, and, at the same time, call the method `print_name()`\non it, by chaining the dereference method (`*`) with the `print_name()` method. Like in the\nexample below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst u = User.init(1, \"pedro\", \"email@gmail.com\");\nconst pointer = &u;\ntry pointer.*.print_name();\n```\n:::\n\n\n\n\n```\npedro\n```\n\nWe can also use pointers to effectively alter the value of an object.\nFor example, I could use the `pointer` object to set\nthe value of the object `number` to 6, like in the example below.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\n\n\n\nTherefore, as I mentioned earlier, people use pointers as an alternative way to access a particular value.\nAnd they use it especially when they do not want to \"move\" these values around. There are situations where,\nyou want to access a particular value in a different scope (i.e. a different location) of your code,\nbut you do not want to \"move\" this value to this new scope (or location) that you are in.\n\nThis matters especially if this value is big in size. Because if it is, then,\nmoving this value becomes an expensive operation to do.\nThe computer will have to spend a considerable amount of time\ncopying this value to this new location.\n\nTherefore, many programmers prefer to avoid this heavy operation of copying the value\nto the new location, by accessing this value through pointers.\nWe are going to talk more about this \"moving operation\" over the next sections.\nFor now, just keep in mind that avoiding this \"move operation\" is\none of main reasons why pointers are used in programming languages.\n\n\n\n\n\n## Constant objects vs variable objects {#sec-pointer-var}\n\nYou can have a pointer that points to a constant object, or, a pointer that points to a variable object.\nBut regardless of who this pointer is, a pointer **must always respect the characteristics of the object that it points to**.\nAs a consequence, if the pointer points to a constant object, then, you cannot use this pointer\nto change the value that it points to. Because it points to a value that is constant. As we discussed at @sec-assignments, you cannot\nchange a value that is constant.\n\nFor example, if I have a `number` object, which is constant, I cannot execute\nthe expression below where I'm trying to change the value of `number` to 6 through\nthe `pointer` object. As demonstrated below, when you try to do something\nlike that, you get a compile time error:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number = 5;\nconst pointer = &number;\npointer.* = 6;\n```\n:::\n\n\n\n\n```\np.zig:6:12: error: cannot assign to constant\n pointer.* = 6;\n```\n\nIf I change the `number` object to be a variable object, by introducing the `var` keyword,\nthen, I can successfully change the value of this object through a pointer, as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\n\n\nYou can see this relationship between \"constant versus variable\" on the data type of\nyour pointer object. In other words, the data type of a pointer object already gives you\nsome clues about whether the value that it points to is constant or not.\n\nWhen a pointer object points to a constant value, then, this pointer have a data type `*const T`,\nwhich means \"a pointer to a constant value of type `T`\".\nIn contrast, if the pointer points to a variable value, then, the type of the pointer is usually `*T`, which is\nsimply \"a pointer to a value of type `T`\".\nHence, whenever you see a pointer object whose data type is in the format `*const T`, then,\nyou know that you cannot use this pointer to change the value that it points to.\nBecause this pointer points to a constant value of type `T`.\n\n\nWe have talked about the value pointed by the pointer being constant or not,\nand the consequences that arises from it. But, what about the pointer object itself? I mean, what happens\nif the pointer object itself is constant or not? Think about it.\nWe can have a constant pointer that points to a constant value.\nBut we can also have a variable pointer that points to a constant value. And vice-versa.\n\nUntil this point, the `pointer` object was always constant,\nbut what this means for us? What is the consequence of the\n`pointer` object being constant? The consequence is that\nwe cannot change the pointer object, because it is constant. We can use the\npointer object in multiple ways, but we cannot change the\nmemory address that is inside this pointer object.\n\nHowever, if we mark the `pointer` object as a variable object,\nthen, we can change the memory address pointed by this `pointer` object.\nThe example below demonstrates that. Notice that the object pointed\nby the `pointer` object changes from `c1` to `c2`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c1: u8 = 5;\nconst c2: u8 = 6;\nvar pointer = &c1;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\npointer = &c2;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\n```\n:::\n\n\n\n\n```\n5\n6\n```\n\nThus, by setting the `pointer` object to a `var` or `const` object,\nyou specify if the memory address contained in this pointer object can change or not\nin your program. On the other side, you can change the value pointed by the pointer,\nif, and only if this value is stored in a variable object. If this value\nis in a constant object, then, you cannot change this value through a pointer.\n\n\n## Types of pointer\n\nIn Zig, there are two types of pointers [@zigdocs], which are:\n\n- single-item pointer (`*`);\n- many-item pointer (`[*]`);\n\n\nSingle-item pointer objects are objects whose data types are in the format `*T`.\nSo, for example, if an object have a data type `*u32`, it means that, this\nobject contains a single-item pointer that points to an unsigned 32-bit integer value.\nAs another example, if an object have type `*User`, then, it contains\na single-item pointer to an `User` value.\n\nIn contrast, many-item pointers are objects whose data types are in the format `[*]T`.\nNotice that the star symbol (`*`) is now inside a pair of brackets (`[]`). If the star\nsymbol is inside a pair of brackets, you know that this object is a many-item pointer.\n\nWhen you apply the `&` operator over an object, you will always get a single-item pointer.\nMany-item pointers are more of a \"internal type\" of the language, more closely\nrelated to slices. So, when you deliberately create a pointer with the `&` operator,\nyou always get a single-item pointer as result.\n\n\n\n## Pointer arithmetic\n\nPointer arithmetic is available in Zig, and they work the same way they work in C.\nWhen you have a pointer that points to an array, the pointer usually points to\nthe first element in the array, and you can use pointer arithmetic to\nadvance this pointer and access the other elements in the array.\n\n\nNotice in the example below, that initially, the `ptr` object was pointing\nto the first element in the array `ar`. But then, I started to walk through the array, by advancing\nthe pointer with simple pointer arithmetic.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{ 1, 2, 3, 4 };\nvar ptr: [*]const i32 = &ar;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\n```\n:::\n\n\n\n\n```\n1\n2\n3\n```\n\nAlthough you can create a pointer to an array like that, and\nstart to walk through this array by using pointer arithmetic,\nin Zig, we prefer to use slices, which were presented at @sec-arrays.\n\nBehind the hood, slices already are pointers,\nand they also come with the `len` property, which indicates\nhow many elements are in the slice. This is good because the `zig` compiler\ncan use it to check for potential buffer overflows, and other problems like that.\n\nAlso, you don't need to use pointer arithmetic to walk through the elements\nof a slice. You can simply use the `slice[index]` syntax to directly access\nany element you want in the slice.\nAs I mentioned at @sec-arrays, you can get a slice from an array by using\na range selector inside brackets. In the example below, I'm creating\na slice (`sl`) that covers the entire `ar` array. I can access any\nelement of `ar` from this slice, and, the slice itself already is a pointer\nbehind the hood.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{1,2,3,4};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\n\n## Optionals and Optional Pointers\n\nLet's talk about optionals and how they relate to pointers in Zig.\nBy default, objects in Zig are **non-nullable**. This means that, in Zig,\nyou can safely assume that any object in your source code is not null.\n\nThis is a powerful feature of Zig when you compare it to the developer experience in C.\nBecause in C, any object can be null at any point, and, as consequence, a pointer in C\nmight point to a null value. This is a common source of undefined behaviour in C.\nWhen programmers work with pointers in C, they have to constantly check if\ntheir pointers are pointing to null values or not.\n\nIf for some reason, your Zig code produces a null value somewhere, and, this null\nvalue ends up in an object that is non-nullable, a runtime error is always\nraised by your Zig program. Take the program below as an example.\nThe `zig` compiler can see the `null` value at compile time, and, as result,\nit raises a compile time error. But, if a `null` value is raised during\nruntime, a runtime error is also raised by the Zig program, with a\n\"attempt to use null value\" message.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nnumber = null;\n```\n:::\n\n\n\n```\np5.zig:5:14: error: expected type 'u8',\n found '@TypeOf(null)'\n number = null;\n ^~~~\n```\n\n\nYou don't get this type of safety in C.\nIn C, you don't get warnings or errors about null values being produced in your program.\nIf for some reason, your code produces a null value in C, most of the times, you end up getting a segmentation fault error\nas result, which can mean many things.\nThat is why programmers have to constantly check for null values in C.\n\nPointers in Zig are also, by default, **non-nullable**. This is another amazing\nfeature in Zig. So, you can safely assume that any pointer that you create in\nyour Zig code is pointing to a non-null value.\nTherefore, you don't have this heavy work of checking if the pointers you create\nin Zig are pointing to a null value.\n\n\n### What are optionals?\n\nOk, we know now that all objects are non-nullable by default in Zig.\nBut what if we actually need to use an object that might receive a null value?\nHere is where optionals come in.\n\nAn optional object in Zig is an object that can be null.\nTo mark an object as optional, we use the `?` operator. When you put\nthis `?` operator right before the data type of an object, you transform\nthis data type into an optional data type, and the object becomes an optional object.\n\nTake the snippet below as an example. We are creating a new variable object\ncalled `num`. This object have the data type `?i32`, which means that,\nthis object contains either a signed 32-bit integer (`i32`), or, a null value.\nBoth alternatives are valid values to the `num` object.\nThat is why, I can actually change the value of this object to null, and,\nno errors are raised by the `zig` compiler, as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\nnum = null;\n```\n:::\n\n\n\n\n### Optional pointers\n\nYou can also mark a pointer object as an optional pointer, meaning that,\nthis object contains either a null value, or, a pointer that points to a value.\nWhen you mark a pointer as optional, the data type of this pointer object\nbecomes `?*const T` or `?*T`, depending if the value pointed by the pointer\nis a constant value or not. The `?` identifies the object as optional, while\nthe `*` identifies it as a pointer object.\n\nIn the example below, we are creating a variable object named `num`, and an\noptional pointer object named `ptr`. Notice that the data type of the object\n`ptr` indicates that it is either a null value, or a pointer to an `i32` value.\nAlso, notice that the pointer object (`ptr`) can be marked as optional, even if\nthe object `num` is not optional.\n\nWhat this code tells us is that, the `num` variable will never contain a null value.\nThis variable will always contain a valid `i32` value. But in contrast, the `ptr` object might contain either a null\nvalue, or, a pointer to an `i32` value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: i32 = 5;\nvar ptr: ?*i32 = #\nptr = null;\nnum = 6;\n```\n:::\n\n\n\n\nBut what happens if we turn the table, and mark the `num` object as optional,\ninstead of the pointer object. If we do that, then, the pointer object is\nnot optional anymore. It would be a similar (although different) result. Because then, we would have\na pointer to an optional value. In other words, a pointer to a value that is either a\nnull value, or, a not-null value.\n\nIn the example below, we are recreating this idea. Now, the `ptr` object\nhave a data type of `*?i32`, instead of `?*i32`. Notice that the `*` symbol comes before of `?`\nthis time. So now, we have a pointer that points to a value that is either null\n, or, a signed 32-bit integer.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\n// ptr have type `*?i32`, instead of `?*i32`.\nconst ptr = #\n_ = ptr;\n```\n:::\n\n\n\n\n\n### Null handling in optionals {#sec-null-handling}\n\nWhen you have an optional object in your Zig code, you have to explicitly handle\nthe possibility of this object being null. It is like error-handling with `try` and `catch`.\nIn Zig you also have to handle null values like if they were a type of error.\n\nWe can do that, by using either:\n\n- an if statement, like you would do in C.\n- the `orelse` keyword.\n- unwrap the optional value with the `?` method.\n\nWhen you use an if statement, you use a pair of pipes\nto unwrap the optional value, and use this \"unwrapped object\"\ninside the if block.\nUsing the example below as a reference, if the object `num` is null,\nthen, the code inside the if statement is not executed. Otherwise,\nthe if statement will unwrap the object `num` into the `not_null_num`\nobject. This `not_null_num` object is guaranteed to be not null inside\nthe scope of the if statement.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst num: ?i32 = 5;\nif (num) |not_null_num| {\n try stdout.print(\"{d}\\n\", .{not_null_num});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n5\n```\n\n\n:::\n:::\n\n\n\n\nNow, the `orelse` keyword behaves like a binary operator. You connect two expressions with this keyword.\nOn the left side of `orelse`, you provide the expression that might result\nin a null value, and on the right side of `orelse`, you provide another expression\nthat will not result in a null value.\n\nThe idea behind the `orelse` keyword is: if the expression on the left side\nresult in a not-null value, then, this not-null value is used. However,\nif this expression on the left side result in a null value, then, the value\nof the expression on the right side is used instead.\n\nLooking at the example below, since the `x` object is currently null, the\n`orelse` decided to use the alternative value, which is the number 15.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x: ?i32 = null;\nconst dbl = (x orelse 15) * 2;\ntry stdout.print(\"{d}\\n\", .{dbl});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n30\n```\n\n\n:::\n:::\n\n\n\n\nYou can use the if statement or the `orelse` keyword, when you want to\nsolve (or deal with) this null value. However, if there is no clear solution\nto this null value, and the most logic and sane path is to simply panic\nand raise a loud error in your program when this null value is encountered,\nyou can use the `?` method of your optional object.\n\nIn essence, when you use this `?` method, the optional object is unwrapped.\nIf a not-null value is found in the optional object, then, this not-null value is used.\nOtherwise, the `unreachable` keyword is used. You can read more about this\n[`unreacheable` keyword at the official documentation](https://ziglang.org/documentation/master/#unreachable)[^un-docs].\nBut in essence, when you build your Zig source code using the build modes `ReleaseSafe` or `Debug`, this\n`unreacheable` keyword causes the program to panic and raise an error during runtime,\nlike in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn return_null(n: i32) ?i32 {\n if (n == 5) return null;\n return n;\n}\n\npub fn main() !void {\n const x: i32 = 5;\n const y: ?i32 = return_null(x);\n try stdout.print(\"{d}\\n\", .{y.?});\n}\n```\n:::\n\n\n\n\n```\nthread 12767 panic: attempt to use null value\np7.zig:12:34: 0x103419d in main (p7):\n try stdout.print(\"{d}\\n\", .{y.?});\n ^\n```\n\n\n[^un-docs]: .\n\n\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/_freeze/Chapters/07-build-system/execute-results/html.json b/_freeze/Chapters/07-build-system/execute-results/html.json index 5205e5b4..daf845bf 100644 --- a/_freeze/Chapters/07-build-system/execute-results/html.json +++ b/_freeze/Chapters/07-build-system/execute-results/html.json @@ -3,9 +3,7 @@ "result": { "engine": "knitr", "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Build System {#sec-build-system}\n\n\nIn this chapter, we are going to talk about the build system, and how an entire project\nis built in Zig.\nOne key advantage of Zig is that it includes a build system embedded in the language itself.\nThis is great, because then you do not have to depend on an external system, separated\nfrom the compiler, to build your code.\n\n\nYou can find a good description of Zig's build system\non the [article entitled \"Build System\"](https://ziglang.org/learn/build-system/#user-provided-options)[^zig-art1]\nfrom the official Zig's website.\nWe also have the excellent [series of posts written by Felix](https://zig.news/xq/zig-build-explained-part-1-59lf)[^felix].\nHence, this chapter represents an extra resource for you to consult and rely on.\n\n[^felix]: \n[^zig-art1]: \n\nBuilding code is one of the things that Zig is best at. One thing that is particularly\ndifficult in C/C++ and even in Rust, is to cross-compile source code to multiple targets\n(e.g. multiple computer architectures and operating systems),\nand the `zig` compiler is known for being one of the best existing pieces of software\nfor this particular task.\n\n\n\n\n## How source code is built?\n\nWe already have talked about the challenges of building source code in low-level languages\nat @sec-project-files. As we described at that section, programmers invented Build Systems\nto surpass these challenges on the process of building source code in low-level languages.\n\nLow-level languages uses a compiler to compile (or to build) your source code into binary instructions.\nIn C and C++, we normally use compilers like `gcc`, `g++` or `clang` to compile\nour C and C++ source code into these instructions.\nEvery language have its own compiler, and this is no different in Zig.\n\nIn Zig, we have the `zig` compiler to compile our Zig source code into\nbinary instructions that can be executed by our computer.\nIn Zig, the compilation (or the build) process involves\nthe following components:\n\n- The Zig modules that contains your source code;\n- Library files (either a dynamic library or a static library);\n- Compiler flags that tailors the build process to your needs.\n\nThese are the things that you need to connect together in order to build your\nsource code in Zig. In C and C++, you would have an extra component, which are the header files of\nthe libraries that you are using. But header files do not exist in Zig, so, you only need\nto care about them if you are linking your Zig source code with a C library.\nIf that is not your case, you can forget about it.\n\nYour build process is usually organized in a build script. In Zig, we normally\nwrite this build script into a Zig module in the root directory of our project,\nnamed as `build.zig`. You write this build script, then, when you run it, your project\nget's built into binary files that you can use and distribute to your users.\n\nThis build script is normally organized around *target objects*. A target is simply\nsomething to be built, or, in other words, it's something that you want the `zig` compiler\nto build for you. This concept of \"targets\" is present in most Build Systems,\nespecially in CMake[^cmake].\n\n[^cmake]: \n\nThere are four types of target objects that you can build in Zig, which are:\n\n- An executable (e.g. a `.exe` file on Windows).\n- A shared library (e.g. a `.so` file in Linux or a `.dll` file on Windows).\n- A static library (e.g. a `.a` file in Linux or a `.lib` file on Windows).\n- An executable file that executes only unit tests (or, a \"unit tests executable\").\n\nWe are going to talk more about these target objects at @sec-targets.\n\n\n\n## The `build()` function {#sec-build-fun}\n\nA build script in Zig always contains a public (and top-level) `build()` function declared.\nIt is like the `main()` function on the main Zig module of your project, that we discussed at @sec-main-file.\nBut instead of creating the entrypoint to your code, this `build()` function is the entrypoint to the build process.\n\nThis `build()` function should accept a pointer to a `Build` object as input, and it should use this \"build object\" to perform\nthe necessary steps to build your project. The return type of this function is always `void`,\nand this `Build` struct comes directly from the Zig Standard Library (`std.Build`). So, you can \naccess this struct by just importing the Zig Standard Library into your `build.zig` module.\n\nJust as a very simple example, here you can see the source code necessary to build\nan executable file from the `hello.zig` Zig module.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n });\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n\nYou can define and use other functions and objects in this build script. You can also import\nother Zig modules as you would normally do in any other module of your project.\nThe only real requirement for this build script, is to have a public and top-level\n`build()` function defined, that accepts a pointer to a `Build` struct as input.\n\n\n## Target objects {#sec-targets}\n\nAs we described over the previous sections, a build script is composed around target objects.\nEach target object is normally a binary file (or an output) that you want to get from the build process. You can list\nmultiple target objects in your build script, so that the build process generates multiple\nbinary files for you at once.\n\nFor example, maybe you are a developer working in a cross-platform application,\nand, because this application is cross-platform, you probably need to release\nbinary files of your software for each OS supported by your application to your end users.\nThus, you can define a different target object in your build script\nfor each OS (Windows, Linux, etc.) where you want to publish your software.\nThis will make the `zig` compiler to build your project to multiple target OS's at once.\nThe Zig Build System official documentation have a [great code example that demonstrates this strategy](https://ziglang.org/learn/build-system/#handy-examples)[^zig-ex].\n\n[^zig-ex]: \n\n\nA target object is created by the following methods of the `Build` struct that we introduced\nat @sec-build-fun:\n\n- `addExecutable()` creates an executable file;\n- `addSharedLibrary()` creates a shared library file;\n- `addStaticLibrary()` creates a static library file;\n- `addTest()` creates an executable file that executes unit tests.\n\n\nThese functions are methods from the `Build` struct that you receive\nas input of the `build()` function. All of them, create as output\na `Compile` object, which represents a target object to be compiled\nby the `zig` compiler. All of these functions accept a similar struct literal as input.\nThis struct literal defines three essential specs about this target object that you are building:\n`name`, `target` and `root_source_file`.\n\nWe have already seen these three options being used on the previous example,\nwhere we used the `addExecutable()` method to create an executable target object.\nThis example is reproduced below. Notice the use of the `path()` method\nfrom the `Build` struct, to define a path in the `root_source_file` option.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n});\n```\n:::\n\n\n\n\nThe `name` option specify the name that you want to give to the binary file defined\nby this target object. So, in this example, we are building an executable file named `hello`.\nIs common to set this `name` option to the name of your project.\n\n\nFurthermore, the `target` option specify the target computer architecture (or the target operating system) of this\nbinary file. For example, if you want this target object to run on a Windows machine\nthat uses a `x86_64` architecture, you can set this `target` option to `x86_64-windows-gnu` for example.\nThis will make the `zig` compiler to compile the project to run on a `x86_64` Windows machine.\nYou can see the full list of architectures and OS's that the `zig` compiler supports by running\nthe `zig targets` command in the terminal.\n\nNow, if you are building the project to run on the current machine\nthat you are using to run this build script, you can set this `target`\noption to the `host` method of the `Build` object, like we did in the example above.\nThis `host` method identifies the current machine where you are\ncurrently running the `zig` compiler.\n\n\nAt last, the `root_source_file` option specifies the root Zig module of your project.\nThat is the Zig module that contains the entrypoint to your application (i.e. the `main()` function), or, the main API of your library.\nThis also means that, all the Zig modules that compose your project are automatically discovered\nfrom the import statements you have inside this \"root source file\".\nThe `zig` compiler can detect when a Zig module depends on the other through the import statements,\nand, as a result, it can discover the entire map of Zig modules used in your project.\n\nThis is handy, and it is different from what happens in other build systems.\nIn CMake for example, you have to explicitly list the paths to all source files that you want to\ninclude in your build process. This is probably a symptom of the \"lack of conditional\ncompilation\" in the C and C++ compilers. Since they lack this feature, you have\nto explicitly choose which source files should be sent to the C/C++ compiler, because not\nevery C/C++ code is portable or supported in every operating system, and, therefore,\nwould cause a compilation error in the C/C++ compiler.\n\n\nNow, one important detail about the build process is that, you have to **explicitly\ninstall the target objects that you create in your build script**, by using the\n`installArtifact()` method of the `Build` struct.\n\nEverytime you invoke the build process of your project, by calling the `build` command\nof the `zig` compiler, a new directory named `zig-out` is created in the root\ndirectory of your project. This new directory contains the outputs of the build process,\nthat is, the binary files built from your source code.\n\nWhat the `installArtifact()` method do is to install (or copy) the built target objects\nthat you defined to this `zig-out` directory.\nThis means that, if you do not\ninstall the target objects you define in your build script, these target objects are\nessentially discarded at the end of the build process.\n\nFor example, you might be building a project that uses a third party library that is built\ntogether with the project. So, when you build your project, you would need first, to\nbuild the third party library, and then, you link it with the source code of your project.\nSo, in this case, we have two binary files that are generated in the build process (the executable file of your project, and the third party library).\nBut only one is of interest, which is the executable file of our project.\nWe can discard the binary file of the third party library, by simply not installing it\ninto this `zig-out` directory.\n\nThis `installArtifact()` method is pretty straightforward. Just remember to apply it to every\ntarget object that you want to save into the `zig-out` directory, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n});\n\nb.installArtifact(exe);\n```\n:::\n\n\n\n\n\n## Setting the build mode\n\nWe have talked about the three essential options that are set when you create a new target object.\nBut there is also a fourth option that you can use to set the build mode of this target object,\nwhich is the `optimize` option.\nThis option is called this way, because the build modes in Zig are treated more of\nan \"optimization vs safety\" problem. So optimization plays an important role here.\nDon't worry, I'm going back to this question very soon.\n\nIn Zig, we have four build modes (which are listed below). Each one of these build modes offer\ndifferent advantages and characteristics. As we described at @sec-compile-debug-mode, the `zig` compiler\nuses the `Debug` build mode by default, when you don't explicitly choose a build mode.\n\n- `Debug`, mode that produces and includes debugging information in the output of the build process (i.e. the binary file defined by the target object);\n- `ReleaseSmall`, mode that tries to produce a binary file that is small in size;\n- `ReleaseFast`, mode that tries to optimize your code, in order to produce a binary file that is as fast as possible;\n- `ReleaseSafe`, mode that tries to make your code as safe as possible, by including safeguards when possible.\n\nSo, when you build your project, you can set the build mode of your target object to `ReleaseFast` for example, which will tell\nthe `zig` compiler to apply important optimizations in your code. This creates a binary file\nthat simply runs faster on most contexts, because it contains a more optimized version of your code.\nHowever, as a result, we often lose some safety features in our code.\nBecause some safety checks are removed from the final binary file,\nwhich makes your code run faster, but in a less safe manner.\n\nThis choice depends on your current priorities. If you are building a cryptography or banking system, you might\nprefer to prioritize safety in your code, so, you would choose the `ReleaseSafe` build mode, which is a little\nslower to run, but much more secure, because it includes all possible runtime safety checks in the binary file\nbuilt in the build process. In the other hand, if you are writing a game for example, you might prefer to prioritize performance\nover safety, by using the `ReleaseFast` build mode, so that your users can experience faster frame rates in your game.\n\nIn the example below, we are creating the same target object that we have used on previous examples.\nBut this time, we are specifying the build mode of this target object to the `ReleaseSafe` mode.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n .optimize = .ReleaseSafe\n});\nb.installArtifact(exe);\n```\n:::\n\n\n\n\n\n## Setting the version of your build\n\nEverytime you build a target object in your build script, you can assign a version\nnumber to this specific build, following a semantic versioning framework.\nYou can find more about semantic versioning by visiting the [Semantic Versioning website](https://semver.org/)[^semver].\nAnyway, in Zig, you can specify the version of your build, by providing a `SemanticVersion` struct to\nthe `version` option, like in the example below:\n\n\n[^semver]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n .version = .{\n .major = 2, .minor = 9, .patch = 7\n }\n});\nb.installArtifact(exe);\n```\n:::\n\n\n\n\n\n## Detecting the OS in your build script {#sec-detect-os}\n\nIs very common in Build Systems to use different options, or, to include different modules, or,\nto link against different libraries depending on the Operational System (OS)\nthat you are targeting in the build process.\n\nIn Zig, you can detect the target OS of the build process, by looking\nat the `os.tag` inside the `builtin` module from the Zig library.\nIn the example below, we are using an if statement to run some\narbitrary code when the target of the build process is a\nWindows system.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nif (builtin.target.os.tag == .windows) {\n // Code that runs only when the target of\n // the compilation process is Windows.\n}\n```\n:::\n\n\n\n\n\n## Adding a run step to your build process\n\nOne thing that is neat in Rust is that you can compile and run your\nsource code with one single command (`cargo run`) from the Rust compiler.\nWe saw at @sec-compile-run-code how can we perform a similar job in Zig, by\nbuilding and running our Zig source code through the `run` command from the `zig` compiler.\n\nBut how can we, at the same time, build and run the binary file specified by a target object in our\nbuild script?\nThe answer is by including a \"run artifact\" in our build script.\nA run artifact is created through the `addRunArtifact()` method from the `Build` struct.\nWe simply provide as input to this function the target object that describes the binary file that we\nwant to execute. As a result, this function creates a run artifact that is capable of executing\nthis binary file.\n\nIn the example below, we are defining an executable binary file named `hello`,\nand we use this `addRunArtifact()` method to create a run artifact that will execute\nthis `hello` executable file.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"src/hello.zig\"),\n .target = b.host\n});\nb.installArtifact(exe);\nconst run_arti = b.addRunArtifact(exe);\n```\n:::\n\n\n\n\nNow that we have created this run artifact, we need to include it in\nthe build process. We do that by declaring a new step in our build\nscript to call this artifact, through the `step()` method of the `Build`\nstruct.\n\nWe can give any name we want to this step, but, for our\ncontext here, I'm going to name this step as \"run\".\nAlso, I give it a brief description to this step (\"Run the project\").\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst run_step = b.step(\n \"run\", \"Run the project\"\n);\n```\n:::\n\n\n\n\n\nNow that we have declared this \"run step\" we need to tell Zig that\nthis \"run step\" depends on the run artifact.\nIn other words, a run artifact always depends on a \"step\" to effectively be executed.\nBy creating this dependency\nwe finally stablish the necessary commands to build and run the executable file\nfrom the build script.\n\nWe can establish a dependency between the run step and the run artifact\nby using the `dependsOn()` method from the run step. So, we first\ncreate the run step, and then, we link it with the run artifact, by\nusing this `dependsOn()` method from the run step.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nrun_step.dependOn(&run_arti.step);\n```\n:::\n\n\n\n\nThe entire source code of this specific build script that\nwe wrote, piece by piece, in this section, is\navailable in the `build_and_run.zig` module. You can\nsee this module by\n[visiting the official repository of this book](https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_and_run.zig)\n[^module-src].\n\n\n[^module-src]: \n\nWhen you declare a new step in your build script, this step\nbecomes available through the `build` command in the `zig` compiler.\nYou can actually see this step by running `zig build --help` in the terminal, like\nin the example below, where we can see that this new \"run\"\nstep that we declared in the build script appeared in the output.\n\n```bash\nzig build --help\n```\n\n```\nSteps:\n ...\n run Run the project\n ...\n```\n\nNow, everything that we need to is to\ncall this \"run\" step that we created in our build script. We\ncall it by using the name that we gave to this step\nafter the `build` command from the `zig` compiler.\nThis will cause the compiler to build our executable file\nand execute it at the same time.\n\n```bash\nzig build run\n```\n\n## Build unit tests in your project\n\nWe have talked at length about writing unit tests in Zig at @sec-unittests,\nand we also have talked about how to execute these unit tests through\nthe `test` command of the `zig` compiler. However,\nas we did with the `run` command on the previous section, we also might want to\ninclude some commands in our build script to also build and execute the unit tests in our project.\n\nSo, once again, we are going to discuss how a specific built-in command from the `zig` compiler,\n(in this case, the `test` command) can be used in a build script in Zig.\nHere is where a \"test target object\" comes into play.\nAs was described at @sec-targets, we can create a test target object by using the `addTest()` method of\nthe `Build` struct. The first thing that we need to do is to\ndeclare a test target object in our build script.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst test_exe = b.addTest(.{\n .name = \"unit_tests\",\n .root_source_file = b.path(\"src/main.zig\"),\n .target = b.host,\n});\nb.installArtifact(test_exe);\n```\n:::\n\n\n\n\n\nA test target object essentially selects all `test` blocks in all Zig modules\nacross your project, and builds only the source code present inside\nthese `test` blocks in your project. As a result, this target object\ncreates an executable file that contains only the source code present\nin all of these `test` blocks (i.e. the unit tests) in your project.\n\nPerfect! Now that we have declared this test target object, an executable file\nnamed `unit_tests` is built by the `zig` compiler when we trigger the build\nscript with the `build` command. After the build\nprocess is finished, we can simply execute this `unit_tests` executable\nin the terminal.\n\nHowever, if you remember the previous section, we already learned\nhow can we create a run step in our build script, to execute an executable file\nbuilt by the build script.\n\nSo, we could simply add a run step in our build script to run these unit tests\nfrom a single command in the `zig` compiler, to make our lifes easier.\nIn the example below, we demonstrate the commands to\nregister a new build step called \"tests\" in our build script\nto run these unit tests.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst run_arti = b.addRunArtifact(test_exe);\nconst run_step = b.step(\"tests\", \"Run unit tests\");\nrun_step.dependOn(&run_arti.step);\n```\n:::\n\n\n\n\nNow that we registered this new build step, we can trigger it by calling the command below\nin the terminal. You can also checkout the complete source\ncode for this specific build script at the `build_tests.zig` module at the\n[official repository of this book](https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_tests.zig)\n[^module-src2].\n\n\n[^module-src2]: \n\n\n```bash\nzig build tests\n```\n\n\n## Tailoring your build process with user-provided options\n\nSometimes, you want to make a build script that is customizable by the user\nof your project. You can do that by creating user-provided options in\nyour build script. We create an user-provided option by using the\n`option()` method from the `Build` struct.\n\nWith this method, we create a \"build option\" which can be passed\nto the `build.zig` script at the command line. The user have the power of setting\nthis option at the `build` command from the\n`zig` compiler. In other words, each build option that we create\nbecomes a new command line argument that is accessible through the `build` command\nof the compiler.\n\nThese \"user-provided options\" are set by using the prefix `-D` in the command line.\nFor example, if we declare an option named `use_zlib`, that receives a boolean value which\nindicates if we should link our source code to `zlib` or not, we can set the value\nof this option in the command line with `-Duse_zlib`. The code example below\ndemonstrates this idea:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const use_zlib = b.option(\n bool,\n \"use_zlib\",\n \"Should link to zlib?\"\n ) orelse false;\n const exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"example.zig\"),\n .target = b.host,\n });\n if (use_zlib) {\n exe.linkSystemLibrary(\"zlib\");\n }\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n\n```bash\nzig build -Duse_zlib=false\n```\n\n\n## Linking to external libraries\n\n\nOne essential part of every build process is the linking stage.\nThis stage is responsible for combining the multiple object files\nthat represent your code, into a single executable file. It also links\nthis executable file to external libraries, if you use any in your code.\n\nIn Zig, we have two notions of a \"library\", which are: 1) a system's library;\n2) a local library. A system's library is just a library that already is installed\nin your system. While a local library is a library that belongs to the current\nproject. Is a library that is present in your project directory, and\nthat you are building together with your project source code.\n\nThe basic difference between the two, is that a system's library is already\nbuilt and installed in your system, supposedly, and all you need to do\nis to link your source code to this library to start using it.\nWe do that by using the `linkSystemLibrary()` method from a\n`Compile` object. This method accepts the name of the library\nin a string as input. Remember from @sec-targets that a `Compile` object\nis a target object that you declare in your build script.\n\nWhen you link a particular target object with a system's library,\nthe `zig` compiler will use `pkg-config` to find where\nare the binary files and also the header files of this library\nin your system.\nWhen it finds these files, the linker present in the `zig` compiler\nwill link your object files with the files of this library to\nproduce a single binary file for you.\n\nIn the example below, we are creating an executable file named `image_filter`,\nand, we are linking this executable file to the C Standard Library with the\nmethod `linkLibC()`, but we also are linking this executable file to the\nC library `libpng` that is currently installed in my system.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const exe = b.addExecutable(.{\n .name = \"image_filter\",\n .root_source_file = b.path(\"src/main.zig\"),\n .target = target,\n .optimize = optimize,\n });\n exe.linkLibC();\n exe.linkSystemLibrary(\"png\");\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n\nIf you are linking with a C library in your project, is generally a good idea\nto also link your code with the C Standard Library. Because is very likely\nthat this C library uses some functionality of the C Standard Library at some point.\nThe same goes to C++ libraries. So, if you are linking with\nC++ libraries, is a good idea to link your project with the C++\nStandard Library by using the `linkLibCpp()` method.\n\nOn the order side, when you want to link with a local library,\nyou should use the `linkLibrary()` method of a `Compile` object.\nThis method expects to receive another `Compile` object as input.\nThat is, another target object defined in your build script,\nusing either the `addStaticLibrary()` or `addSharedLibrary()` methods\nwhich defines a library to be built.\n\nAs we discussed earlier, a local library is a library\nthat is local to your project, and that is being built together\nwith your project. So, you need to create a target object in your build script\nto build this local library. Then, you link the target objects of interest in your project,\nwith this target object that identifies this local library.\n\nTake a look at this example extracted from the build script of the [`libxev` library](https://github.com/mitchellh/libxev/tree/main)[^libxev2].\nYou can see in this snippet that\nwe are declaring a shared library file, from the `c_api.zig`\nmodule. Then, later in the build script, we declare an\nexecutable file named `\"dynamic-binding-test\"`, which\nlinks to this shared library that we defined earlier\nin the script.\n\n[^libxev2]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst optimize = b.standardOptimizeOption(.{});\nconst target = b.standardTargetOptions(.{});\n\nconst dynamic_lib = b.addSharedLibrary(.{\n .name = dynamic_lib_name,\n .root_source_file = b.path(\"src/c_api.zig\"),\n .target = target,\n .optimize = optimize,\n});\nb.installArtifact(dynamic_lib);\n// ... more lines in the script\nconst dynamic_binding_test = b.addExecutable(.{\n .name = \"dynamic-binding-test\",\n .target = target,\n .optimize = optimize,\n});\ndynamic_binding_test.linkLibrary(dynamic_lib);\n```\n:::\n\n\n\n\n\n\n## Building C code {#sec-building-c-code}\n\nThe `zig` compiler comes with a C compiler embedded in it. In other words,\nyou can use the `zig` compiler to build C projects. This C compiler is available\nthrough the `cc` command of the `zig` compiler.\n\nAs an example, let's use the famous [FreeType library](https://freetype.org/)[^freetype].\nFreeType is one of the most widely used pieces of software in the world.\nIt is a C library designed to produce high-quality fonts. But it is also\nheavily used in the industry to natively render text and fonts\nin the screen of your computer.\n\nIn this section, we are going to write a build script, piece by piece, that is capable\nof building the FreeType project from source.\nYou can find the source code of this build script on the\n[`freetype-zig` repository](https://github.com/pedropark99/freetype-zig/tree/main)[^freetype-zig]\navailable at GitHub.\n\n[^freetype]: \n[^freetype-zig]: \n\nAfter you download the source code of FreeType from the official website[^freetype],\nyou can start writing the `build.zig` module. We begin by defining the target object\nthat defines the binary file that we want to compile.\n\nAs an example, I will build the project as a static library file using the `addStaticLibrary()` method\nto create the target object.\nAlso, since FreeType is a C library, I will also link the library\nagainst `libc` through the `linkLibC()` method, to guarantee that any use\nof the C Standard Library is covered in the compilation process.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst target = b.standardTargetOptions(.{});\nconst opti = b.standardOptimizeOption(.{});\nconst lib = b.addStaticLibrary(.{\n .name = \"freetype\",\n .optimize = opti,\n .target = target,\n});\nlib.linkLibC();\n```\n:::\n\n\n\n\n### Creating C compiler flags\n\nCompiler flags are also known as \"compiler options\" by many programmers,\nor also, as \"command options\" in the GCC official documentation.\nIt's fair to also call them as the \"command-line arguments\" of the C compiler.\nIn general, we use compiler flags to turn on (or turn off) some features from the compiler,\nor to tweak the compilation process to fit the needs of our project.\n\nIn build scripts written in Zig, we normally list the C compiler flags to be used in the compilation process\nin a simple array, like in the example below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c_flags = [_][]const u8{\n \"-Wall\",\n \"-Wextra\",\n \"-Werror\",\n};\n```\n:::\n\n\n\n\nIn theory, there is nothing stopping you from using this array to add \"include paths\" (with the `-I` flag)\nor \"library paths\" (with the `-L` flag) to the compilation process. But there are formal ways in Zig to\nadd these types of paths in the compilation process. Both are discussed at @sec-include-paths\nand @sec-library-paths.\n\nAnyway, in Zig, we add C flags to the build process together with the C files that we want to compile, by using the\n`addCSourceFile()` and `addCSourceFiles()` methods. In the example above, we have just declared\nthe C flags that we want to use. But we haven't added them to the build process yet.\nTo do that, we also need to list the C files to be compiled.\n\n### Listing your C files\n\nThe C files that contains \"cross-platform\" source code are listed in the `c_source_files`\nobject below. These are the C files that are included by default in every platform\nsupported by the FreeType library. Now, since the amount of C files in the FreeType library is big,\nI have omitted the rest of the files in the code example below, for brevity purposes.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c_source_files = [_][]const u8{\n \"src/autofit/autofit.c\",\n \"src/base/ftbase.c\",\n // ... and many other C files.\n};\n```\n:::\n\n\n\n\nNow, in addition to \"cross-platform\" source code, we also have some C files in the FreeType project\nthat are platform-specific, meaning that, they contain source code that can only be compiled in specific platforms,\nand, as a result, they are only included in the build process on these specific target platforms.\nThe objects that list these C files are exposed in the code example below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst windows_c_source_files = [_][]const u8{\n \"builds/windows/ftdebug.c\",\n \"builds/windows/ftsystem.c\"\n};\nconst linux_c_source_files = [_][]const u8{\n \"src/base/ftsystem.c\",\n \"src/base/ftdebug.c\"\n};\n```\n:::\n\n\n\n\nNow that we declared both the files that we want to include and the C compiler flags to be used,\nwe can add them to the target object that describes the FreeType library, by using the\n`addCSourceFile()` and `addCSourceFiles()` methods.\n\nBoth of these functions are methods from a `Compile` object (i.e. a target object).\nThe `addCSourceFile()` method is capable of adding a single C file to the target object,\nwhile the `addCSourceFiles()` method is used to add multiple C files in a single command.\nYou might prefer to use `addCSourceFile()` when you need to use different compiler flags\non specific C files in your project. But, if you can use the same compiler flags\nacross all C files, then, you will probably find `addCSourceFiles()` a better choice.\n\nNotice that we are using the `addCSourceFiles()` method in the example below,\nto add both the C files and the C compiler flags. Also notice that we\nare using the `os.tag` that we learned about at @sec-detect-os, to add the platform-specific\nC files.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nlib.addCSourceFiles(\n &c_source_files, &c_flags\n);\n\nswitch (builtin.target.os.tag) {\n .windows => {\n lib.addCSourceFiles(\n &windows_c_source_files,\n &c_flags\n );\n },\n .linux => {\n lib.addCSourceFiles(\n &linux_c_source_files,\n &c_flags\n );\n },\n else => {},\n}\n```\n:::\n\n\n\n\n\n### Defining C Macros\n\nC Macros are an essential part of the C programming language,\nand they are commonly defined through the `-D` flag from a C compiler.\nIn Zig, you can define a C Macro to be used in your build process\nby using the `defineCMacro()` method from the target object that\ndefines the binary file that you are building.\n\nIn the example below, we are using the `lib` object that we have defined\non the previous sections to define some C Macros used by the FreeType project\nin the compilation process. These C Macros specify if FreeType\nshould (or should not) include functionalities from different\nexternal libraries.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nlib.defineCMacro(\"FT_DISABLE_ZLIB\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_PNG\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_HARFBUZZ\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_BZIP2\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_BROTLI\", \"TRUE\");\nlib.defineCMacro(\"FT2_BUILD_LIBRARY\", \"TRUE\");\n```\n:::\n\n\n\n\n\n### Adding library paths {#sec-library-paths}\n\nLibrary paths are paths in your computer where the C compiler will look (or search) for\nlibrary files to link against your source code. In other words, when you use a library in your\nC source code, and you ask the C compiler to link your source code against this library,\nthe C compiler will search for the binary files of this library across the paths listed\nin this \"library paths\" set.\n\nThese paths are platform specific, and, by default, the C compiler starts by looking at a\npre-defined set of places in your computer. But you can add more paths (or more places)\nto this list. For example, you may have a library installed in a non-conventional place of your\ncomputer, and you can make the C compiler \"see\" this \"non-conventional place\" by adding this path\nto this list of pre-defined paths.\n\nIn Zig, you can add more paths to this set by using the `addLibraryPath()` method from your target object.\nFirst, you defined a `LazyPath` object, containing the path you want to add, then,\nyou provide this object as input to the `addLibraryPath()` method, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst lib_path: std.Build.LazyPath = .{\n .cwd_relative = \"/usr/local/lib/\"\n};\nlib.addLibraryPath(lib_path);\n```\n:::\n\n\n\n\n\n\n\n### Adding include paths {#sec-include-paths}\n\nThe preprocessor search path is a popular concept from the\nC community, but it is also known by many C programmers as \"include paths\", because\nthe paths in this \"search path\" relate to the `#include` statements found in the C files.\n\nInclude paths are similar to library paths. They are a set of pre-defined places in your computer where\nthe C compiler will look for files during the compilation process. But instead of looking for\nlibrary files, the include paths are places where the compiler looks for header files included\nin your C source code.\nThis is why many C programmers prefer to call these paths as the \"preprocessor search path\".\nBecause header files are processed during the preprocessor stage of the compilation\nprocess.\n\nSo, every header file that you include in your C source code, through a `#include` statements needs to\nbe found somewhere, and the C compiler will search for this header file across the paths listed in this \"include paths\" set.\nInclude paths are added to the compilation process through the `-I` flag.\n\nIn Zig, you can add new paths to this pre-defined set of paths, by using the `addIncludePath()` method\nfrom your target object. This method also accepts a `LazyPath` object as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst inc_path: std.Build.LazyPath = .{\n .path = \"./include\"\n};\nlib.addIncludePath(inc_path);\n```\n:::\n", - "supporting": [ - "07-build-system_files" - ], + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/09-data-structures/execute-results/html.json b/_freeze/Chapters/09-data-structures/execute-results/html.json index d7ca70b5..7f635a42 100644 --- a/_freeze/Chapters/09-data-structures/execute-results/html.json +++ b/_freeze/Chapters/09-data-structures/execute-results/html.json @@ -3,9 +3,7 @@ "result": { "engine": "knitr", "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Data Structures\n\nIn this chapter, I want to present the most common Data Structures that are available from\nthe Zig Standard Library, especially `ArrayList` and also `HashMap`. These are generic Data Structures\nthat you can use to store and control any type of data that is produced by your application.\n\n## Dynamic Arrays {#sec-dynamic-array}\n\nIn high level languages, arrays are usually dynamic. They can easily grow\nin size when they have to, and you don't need to worry about it.\nIn contrast, arrays in low level languages are usually static by default.\nThis is the reality of C, C++, Rust and also Zig. Static arrays were presented at\n@sec-arrays, but in this section, we are going to talk about dynamic arrays in Zig.\n\nDynamic arrays are simply arrays that can grow in size during the runtime\nof your program. Most low level languages have some implementation of\na dynamic array in their standard library. C++ have `std::vector`, Rust have `Vec`,\nand Zig have `std.ArrayList`.\n\nThe `std.ArrayList` struct provides a contiguous and growable array for you.\nIt works like any other dynamic array, it allocates a contiguous block of memory, and when this block have no space left,\n`ArrayList` allocates another contiguous and bigger block of memory, copies the\nelements to this new location, and erases (or frees) the previous block of memory.\n\n\n### Capacity vs Length\n\nWhen we talk about dynamic arrays, we usually have two similar concepts that\nare very essential to how a dynamic array works behind the hood.\nThese concepts are *capacity* and *length*. In some contexts, especially\nin C++, *length* is also called of *size*.\n\nAlthough they look similar, these concepts represent different things\nin the context of a dynamic array. *Capacity* is the number of items (or elements)\nthat your dynamic array can currently hold without the need to allocate more memory.\n\nIn contrast, the *length* refers to how many elements in the array\nare currently being used, or, in other words, how many elements in this array\nthat you have assigned a value to. Every dynamic array works around\na block of allocated memory, which represents an array with total capacity for $n$ elements.\nHowever, only a portion of these $n$ elements are being used most of the time. This portion\nof $n$ is the *length* of the array. So every time you append a new value\nto the array, you are incrementing its *length* by one.\n\nThis means that a dynamic array usually works with an extra margin, or, an extra space\nwhich is currently empty, but it is waiting and ready to be used. This \"extra space\"\nis essentially the difference between *capacity* and *length*. *Capacity* represents\nthe total number of elements that the array can hold without the need to re-allocate\nor re-expand the array, while the *length* represents how much of this capacity\nis currently being used to hold/store values.\n\n@fig-capacity-length presents this idea visually. Notice that, at first,\nthe capacity of the array is greater than the length of the array.\nSo, the dynamic array have extra space that is currently empty, but it\nis ready to receive a value to be stored.\n\n![Difference between capacity and length in a dynamic array](./../Figures/dynamic-array.png){#fig-capacity-length}\n\nWe can also see at @fig-capacity-length that, when *length* and *capacity* are equal, it means that the array have no space left.\nWe have reached the ceiling of our capacity, and because of that, if we want to store more values\nin this array, we need to expand it. We need to get a bigger space that can hold more values\nthan what we currently have.\n\nA dynamic array works by expanding the underlying array, whenever the *length* becomes equal\nto the *capacity* of the array. It basically allocates a new contiguous block of memory that is bigger\nthan the previous one, then, it copies all values that are currently being stored to this new\nlocation (i.e. this new block of memory), then, it frees the previous block of\nmemory. At the end of this process, the new underlying array have a bigger *capacity*, and, therefore,\nthe *length* becomes, once again, smaller than the *capacity* of the array.\n\nThis is the cycle of an dynamic array. Notice that, throughout this cycle, the *capacity* is always\neither equal to or higher than the *length* of the array. If youh have an `ArrayList` object (let's suppose\nyou named it `buffer`), you can check the current capacity of your array by accessing the `capacity`\nattribute of your `ArrayList` object, while the current *length* of it is available at the `items.len`\nattribute.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// Check capacity\nbuffer.capacity;\n// Check length\nbuffer.items.len;\n```\n:::\n\n\n\n\n\n### Creating an `ArrayList` object\n\nIn order to use `ArrayList`, you must provide an allocator object to it.\nRemember, Zig does not have a default memory allocator. And as I described at @sec-allocators, all memory\nallocations must be done by an allocator object that you define, that\nyou have control over. In our example here, I'm going to use\na general purpose allocator, but you can use any other allocator\nof your preference.\n\nWhen you initialize an `ArrayList` object, you must provide the data type of the elements of\nthe array. In other words, this defines the type of data that this array (or container) will\nstore. Therefore, if I provide the `u8` type to it, then, I will create a dynamic\narray of `u8` values. However, if I provide a struct that I have defined instead, like the struct `User`\nfrom @sec-structs-and-oop, then, a dynamic array of `User` values\nwill be created. In the example below, with the expression `ArrayList(u8)` we\nare creating a dynamic array of `u8` values.\n\nAfter you provide the data type of the elements of the array, you can initialize\nan `ArrayList` object by either using the `init()` or the `initCapacity()` methods.\nThe former method receives only the allocator object\nas input, while the latter method receives both the allocator object and a capacity number as inputs.\nWith the latter method, you not only initialize the struct, but you\nalso set the starting capacity of the allocated array.\n\nUsing the `initCapacity()` method is the preferred way to initialize your dynamic array.\nBecause reallocations, or, in other words, the process of expanding the capacity of the array,\nis always a high cost operation. You should take any possible opportunity to avoid reallocations in\nyour array. If you know how much space your array needs to occupy at the beginning,\nyou should always use `initCapacity()` to create your dynamic array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 100);\ndefer buffer.deinit();\n```\n:::\n\n\n\n\n\nIn the example above, the `buffer` object starts as an array of 100 elements. If this\n`buffer` object needs to create more space to accomodate more elements during the runtime of your program, the `ArrayList`\ninternals will perform the necessary actions for you automatically.\nAlso notice the `deinit()` method being used to destroy the `buffer` object at the\nend of the current scope, by freeing all the memory that was allocated for the dynamic\narray stored in this `buffer` object.\n\n\n### Adding new elements to the array\n\nNow that we have created our dynamic array, we can start to use it. You can append (a.k.a \"add\")\nnew values to this array by using the `append()` method. This method works the same way\nas the `append()` method from a Python list, or, the `emplace_back()` method from `std::vector` of C++.\nYou provide a single value to this method, and the method appends this value to the array.\n\nYou can also use the `appendSlice()` method to append multiple values at once. You provide\na slice (slices were described at @sec-arrays) to this method, and the method adds all values present\nin this slice to your dynamic array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry buffer.append('H');\ntry buffer.append('e');\ntry buffer.append('l');\ntry buffer.append('l');\ntry buffer.append('o');\ntry buffer.appendSlice(\" World!\");\n```\n:::\n\n\n\n\n### Removing elements from the array {#sec-dynamic-array-remove}\n\nYou can use the `pop()` method to \"pop\" or remove\nthe last element in the array. Is worth noting that this method\ndo not change the capacity of the array. It just deletes or erases\nthe last value stored in the array.\n\nAlso, this method returns as result the value that got deleted. That is, you can\nuse this method to both get the last value in the array, and also, remove\nit from the array. It is a \"get and remove value\" type of method.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exclamation_mark = buffer.pop();\n```\n:::\n\n\n\n\nNow, if you want to remove specific elements from specific positions\nof your array, you can use the `orderedRemove()` method from your\n`ArrayList` object. With this method, you can provide an index as input,\nthen, the method will delete the value that is at this index in the array.\nYou are effectively reducing the *length* of the array everytime you execute\nan `orderedRemove()` operation.\n\nIn the example below, we first create an `ArrayList` object, and we fill it\nwith numbers. Then, we use `orderedRemove()` to remove the value at\nindex 3 in the array, two consecutive times.\n\nAlso, notice that we are assigning the result of `orderedRemove()` to the\nunderscore character. So we are discarding the result value of this method.\nThe `orderedRemove()` method returns the value that got deleted, in a similar\nstyle to the `pop()` method.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 100);\ndefer buffer.deinit();\n\nfor (0..10) |i| {\n const index: u8 = @intCast(i);\n try buffer.append(index);\n}\n\nstd.debug.print(\n \"{any}\\n\", .{buffer.items}\n);\n_ = buffer.orderedRemove(3);\n_ = buffer.orderedRemove(3);\n\nstd.debug.print(\"{any}\\n\", .{buffer.items});\nstd.debug.print(\"{any}\\n\", .{buffer.items.len});\n```\n:::\n\n\n\n\n```\n{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }\n{ 0, 1, 2, 5, 6, 7, 8, 9 }\n8\n```\n\nOne key characteristic about `orderedRemove()` is that it preserves the order\nof the values in the array. So, it deletes the value that you asked it to\nremove, but it also makes sure that the order of the values that remain in the array\nstay the same as before.\n\nNow, if you don't care about the order of the values, for example, maybe you want to treat\nyour dynamic array as a set of values, like the `std::unordered_set`\nstructure from C++, you can use the `swapRemove()` method instead. This method\nworks similarly to the `orderedRemove()` method. You give an index to this\nmethod, then, it deletes the value that is at this index in the array.\nBut this method does not preserve the original order of the values that remain\nin the array. As a result, `swapRemove()` is, in general, faster than `orderedRemove()`.\n\n\n### Inserting elements at specific indexes\n\nWhen you need to insert values in the middle of your array,\ninstead of just appending them to the end of the array, you need to use\nthe `insert()` and `insertSlice()` methods, instead of\nthe `append()` and `appendSlice()` methods.\n\nThese two methods work very similarly to `insert()` and `insert_range()`\nfrom the C++ `std::vector` class. You provide an index to these methods,\nand they insert the values that you provide at that index in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 10);\ndefer buffer.deinit();\n\ntry buffer.appendSlice(\"My Pedro\");\ntry buffer.insert(4, '3');\ntry buffer.insertSlice(2, \" name\");\nfor (buffer.items) |char| {\n try stdout.print(\"{c}\", .{char});\n}\n```\n:::\n\n\n\n\n```\nMy name P3edro\n```\n\n\n### Conclusion\n\nIf you feel the lack of some other method, I recommend\nyou to read the [official documentation for the `ArrayListAligned`](https://ziglang.org/documentation/master/std/#std.array_list.ArrayListAligned)[^zig-array2]\nstruct, which describes most of the methods available\nthrough the `ArrayList` object.\n\nYou will notice that there is a lot of other methods in this page that\nI did not described here, and I recommend you to explore these methods,\nand understand how they work.\n\n[^zig-array2]: \n\n\n\n## Maps or HashTables {#sec-maps-hashtables}\n\nSome professionals know this type of data structure by different terms, like \"map\",\n\"hashmap\" or \"associative arrays\". But the most common term used is *hashtable*.\nEvery programming language normally have some implementation of a hashtable in their\nstandard libraries. Python have `dict()`, C++ have `std::map` and `std::unordered_map`, Rust\nhave `HashMap`, Javascript have `Object()` and `Map()`, etc.\n\n\n\n### What is a hashtable?\n\nA hashtable is a data structure based on key-value pairs.\nYou provide a key and a value to this structure, then, the hashtable will store\nthe input value at a location that can be identified by the input\nkey that you provided.\nIt does that by using an underlying array and a hash function.\nThese two components are essential to how a hashtable works.\n\nUnder the hood, the hashtable contains an array. This array is where the values\nare stored, and the elements of this array are usually called of *buckets*.\nSo the values that you provide to the hashtable are stored inside buckets,\nand you access each bucket by using an index.\n\nWhen you provide a key to a hashtable, it passes this key to the\nhash function. This hash function uses some sort of hashing algorithm to transform\nthis key into an index. This index is actually an array index. It is a position\nin the underlying array of the hashtable.\nThis is how a key identifies a specific position (or location) inside the hashtable\nstructure.\n\nTherefore, you provide a key to the hashtable, and this key identifies a specific location\ninside the hashtable, then, the hashtable takes the input value that you provided,\nand stores this value in the location identified by this input key.\nYou could say that the key maps to the value stored in the hashtable. You find\nthe value, by using the key that identifies the location where the value is stored.\nThe @fig-hashtable presents this process visually.\n\n\n![A diagram of a Hashtable. Source: Wikipedia, the free encyclopedia.](./../Figures/hashtable.svg){#fig-hashtable}\n\n\nThe operation described in the previous paragraph is normally called an *insertion* operation.\nBecause you are inserting new values into the hashtable.\nBut there are other types of operations in hashtables such as *delete* and *lookup*.\nDelete is self describing, it is when you delete (or remove) a value from the hashtable.\nWhile lookup corresponds to when you look at a value that is stored in\nthe hashtable, by using the key that identifies the location where this value is stored.\n\nSometimes, instead of storing the values directly, the underlying array of the hashtable might be an array of pointers,\ni.e. the buckets of the array stores pointers that points to the value,\nor also, may be an array of linked lists.\nThese cases are common on hashtables that allows duplicate keys, or, in other words,\non hashtables that effectively handle \"collisions\" that may arise from the hash function.\n\nDuplicate keys, or this \"collision\" thing that I'm talking about, is when you have two different keys\nthat points to the same location (i.e. to the same index)\nin the underlying array of the hashtable. This might happen depending on the characteristics of the hash function\nthat is being used in the hashtable. Some implementations of the hashtable will actively deal with collisions,\nmeaning that, they will handle this case in some way. For example, the hashtable\nmight transform all buckets into linked lists. Because with a linked list you can store\nmultiple values into a single bucket.\n\nThere are different techniques to handle collisions in hashtables, which I will not describe\nin this book, because it is not our main scope here. But you can find a good description of\nsome of the most common techniques at the Wikipedia page of hashtables [@wikipedia_hashtables].\n\n\n### Hashtables in Zig {#sec-hashmap}\n\nThe Zig Standard Library provides different implementations of a hashtable.\nEach implementation have its own cons and pros, which we will\ndiscuss later on, and all of them are available through the `std.hash_map` module.\n\nThe `HashMap` struct is a general-purpose hashtable,\nwhich have very fast operations (lookup, insertion, delete), and also,\nquite high load factors for low memory usage. You can create and provide a context object\nto the `HashMap` constructor. This context object allows you to tailor\nthe behaviour of the hashtable itself, because you can\nprovide a hash function implementation to be used by the hashtable\nthrough this context object.\n\nBut let's not worry about this context object now, because it is meant to be used\nby \"experts in the field of hashtables\". Since we are most likely not\nexperts in this field, we are going to take the easy way to create\na hashtable. Which is by using the `AutoHashMap()` function.\n\n\nThis `AutoHashMap()` function is essentially a \"create a hashtable object that uses the default settings\"\ntype of function. It automatically chooses a context object, and, therefore, a hash function implementation,\nfor you. This function receives two data types as input, the first input is the data type of the keys\nthat will be used in this hashtable, while the second input is the data type of the data that will be\nstored inside the hashtable, that is, the data type of the values to be stored.\n\nIn the example below, we are providing the data type `u32` in the first argument, and `u16` in the second argument of this\nfunction. This means that we are going to use `u32` values as keys in this hashtable, while `u16` values are the actual values\nthat are going to be stored into this hashtable.\nAt the end of this process, the `hash_table` object contains a `HashMap` object\nthat uses the default settings and context.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst AutoHashMap = std.hash_map.AutoHashMap;\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var hash_table = AutoHashMap(u32, u16).init(allocator);\n defer hash_table.deinit();\n\n try hash_table.put(54321, 89);\n try hash_table.put(50050, 55);\n try hash_table.put(57709, 41);\n std.debug.print(\n \"N of values stored: {d}\\n\",\n .{hash_table.count()}\n );\n std.debug.print(\n \"Value at key 50050: {d}\\n\",\n .{hash_table.get(50050).?}\n );\n\n if (hash_table.remove(57709)) {\n std.debug.print(\n \"Value at key 57709 successfully removed!\\n\",\n .{}\n );\n }\n std.debug.print(\n \"N of values stored: {d}\\n\",\n .{hash_table.count()}\n );\n}\n```\n:::\n\n\n\n\n```\nN of values stored: 3\nValue at key 50050: 55\nValue at key 57709 successfully removed!\nN of values stored: 2\n```\n\nYou can add/put new values into the hashtable by using the `put()` method. The first argument\nis the key to be used, and the second argument is the actual value that you want to store inside\nthe hashtable. In the example below, we first add the value 89 using the key 54321, next, we add\nthe value 55 using the key 50050, etc.\n\nNotice that we have used the method `count()` to see how many values are currently stored in the\nhashtable. After that, we also use the `get()` method to access (or look) at the value stored in\nthe position identified by the key 500050. The output of this `get()` method is an optional value.\nThis is why we use the `?` method at the end to get the actual value.\n\nAlso notice that we can remove (or delete) values from the hashtable by using the `remove()` method.\nYou provide the key that identifies the value that you want to delete, then, the method will\ndelete this value and return a `true` value as output. This `true` value essentially tells us\nthat the method successfully deleted the value.\n\nBut this delete operation might not be always successful. For example, you might provide the wrong\nkey to this method. I mean, maybe you provide\n(either intentionally or unintentionally) a key that points to an empty bucket,\ni.e. a bucket that still doesn't have a value in it.\nIn this case, the `remove()` method would return a `false` value.\n\n\n\n### Iterating through the hashtable\n\nIterating through the keys and values that are currently being stored in\nthe hashtable is a very common necessity.\nYou can do that in Zig by using an iterator object that can iterate\nthrough the elements of your hashtable object.\n\nThis iterator object works like any other iterator object that you would\nfind in languages such as C++ and Rust. It is basically a pointer object\nthat points to some value in the container, and has a `next()` method\nthat you can use to navigate (or iterate) through the values in the\ncontainer.\n\nYou can create such iterator object by using the `iterator()` method of the hashtable object.\nThis method returns an iterator object, from which you can use the `next()` method in conjunction\nwith a while loop to iterate through the elements of your hashtable. The `next()` method returns an optional\n`Entry` value, and therefore, you must unwrap this optional value to get the actual `Entry` value\nfrom which you can access the key and also the value identified by this key.\n\nWith this `Entry` value at hand, you can access the key of this current entry by using the `key_ptr`\nattribute and dereferencing the pointer that lives inside of it, while the value identified by this\nkey is accessed through the `value_ptr` attribute instead, which is also a pointer to be dereferenced.\nThe code example below demonstrates the use of these elements:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst AutoHashMap = std.hash_map.AutoHashMap;\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var hash_table = AutoHashMap(u32, u16).init(allocator);\n defer hash_table.deinit();\n\n try hash_table.put(54321, 89);\n try hash_table.put(50050, 55);\n try hash_table.put(57709, 41);\n\n var it = hash_table.iterator();\n while (it.next()) |kv| {\n // Access the current key\n std.debug.print(\"Key: {d} | \", .{kv.key_ptr.*});\n // Access the current value\n std.debug.print(\"Value: {d}\\n\", .{kv.value_ptr.*});\n }\n}\n```\n:::\n\n\n\n\n```\nKey: 54321 | Value: 89\nKey: 50050 | Value: 55\nKey: 57709 | Value: 41\n```\n\n\nIf you want to iterate specifically through the values or the keys of your hashtable,\nyou can create a key iterator or a value iterator object. These are also iterator\nobjects, which have the same `next()` method that you can use to iterate through the\nhashtable.\n\nKey iterators are created from the `keyIterator()` method of your\nhashtable object, while value iterators are created from the `valueIterator()` method.\nAll you have to do is to unwrap the value from the `next()` method and deference it\ndirectly to access the key or the value that you are iterating over.\nThe code example below demonstrates the use of a key iterator,\nbut you can replicate the same logic to a value iterator.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar kit = hash_table.keyIterator();\nwhile (kit.next()) |key| {\n std.debug.print(\"Key: {d}\\n\", .{key.*});\n}\n```\n:::\n\n\n\n\n```\nKey: 54321\nKey: 50050\nKey: 57709\n```\n\n\n### The `ArrayHashMap` hashtable {#sec-array-map}\n\nIf you need to iterate through the elements of your hashtable constantly,\nyou might want to use the `ArrayHashMap` struct for your specific case,\ninstead of going with the usual and general-purpose `HashMap` struct.\n\nThe `ArrayHashMap` struct creates a hashtable that is faster to iterate over.\nThat is why this specific type of hashtable might be valuable to you.\nSome other properties of a `ArrayHashMap` hashtable are:\n\n- the order of insertion is preserved, i.e. the order of the values that you find while iterating through this hashtable is actually the order in which these values were inserted in the hashtable.\n- the key-value pairs are stored sequentially, one after another.\n\n\nYou can create an `ArrayHashMap` object by using, once again, a helper function that\nchooses automatically for you a hash function implementation. This is the\n`AutoArrayHashMap()` function, which works very similarly to the `AutoHashMap()`\nfunction that we presented at @sec-hashmap.\n\nYou provide two data types to this function. The data type of the keys that will be\nused in this hashtable, and the data type of the values that will be stored in\nthis hashtable.\n\nAn `ArrayHashMap` object have essentially the exact same methods from the `HashMap` struct.\nSo you can insert new values into the hashtable by using the `put()` method, and you can look (or get)\na value from the hashtable by using the `get()` method. But the `remove()` method is not available\nin this specific type of hashtable.\n\nIn order to delete values from the hashtable, you would use the same methods that you find in\nan `ArrayList` object, i.e. a dynamic array. I presented these methods at @sec-dynamic-array-remove,\nwhich are the `swapRemove()` and `orderedRemove()` methods. These methods have the same meaning here, or,\nthe same effect that they have in an `ArrayList` object.\n\nThis means that, with `swapRemove()` you remove the value from the hashtable, but you do not preserve\nthe order in which the values were inserted into the structure. While `orderedRemove()` is able\nto retain the order in which these values were inserted.\n\nBut instead of providing an index as input to `swapRemove()` or `orderedRemove()`, like I described\nat @sec-dynamic-array-remove, these methods here in an `ArrayHashMap` take a key as input, like\nthe `remove()` method from a `HashMap` object. If you want to provide an index as input, instead\nof a key, you should use the `swapRemoveAt()` and `orderedRemoveAt()` methods.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar hash_table = AutoArrayHashMap(u32, u16)\n .init(allocator);\ndefer hash_table.deinit();\n```\n:::\n\n\n\n\n\n\n### The `StringHashMap` hashtable {#sec-string-hash-map}\n\nOne thing that you will notice in the other two types of hashtables that I have\npresented over the last sections, is that neither of them accepts a slice data type\nin their keys.\nWhat this means is that you cannot use a slice value to represent a key in\nthese types of hashtable.\n\nThe most obvious consequence of this, is that you cannot use strings as keys\nin these hashtables. But it is extremely common to use strings as keys\nin hashtables.\n\nTake this very simple Javascript code snippet as an example. We are creating\na simple hashtable object named `people`. Then, we add a new entry to this\nhashtable, which is identified by the string `'Pedro'`. This string is the\nkey in this case, while the object containing different personal information such as\nage, height and city, is the value to be stored in the hashtable.\n\n```js\nvar people = new Object();\npeople['Pedro'] = {\n 'age': 25,\n 'height': 1.67,\n 'city': 'Belo Horizonte'\n};\n```\n\nThis pattern of using strings as keys is very common in\nall sorts of situations. That is why the Zig Standard Library offers a\nspecific type of hashtable for this purpose, which is created through the `StringHashMap()` function.\nThis function creates a hashtable that uses strings as keys. The only input of this\nfunction is the data type of the values that will be stored into this hashtable.\n\nIn the example below, I'm creating a hashtable to store the ages of different people.\nEach key in this hashtable is represented by the name of each person, while the value stored in the\nhashtable is the age of this person identified by the key.\n\nThat is why I provide the `u8` data type (which is the data type used by the age values) as input to this `StringHashMap()` function.\nAs the result, it creates a hashtable that uses string values as keys, and, that stores\n`u8` values in it. Notice that an allocator object is provided at the `init()` method of the\nresulting object from the `StringHashMap()` function.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var ages = std.StringHashMap(u8).init(allocator);\n defer ages.deinit();\n\n try ages.put(\"Pedro\", 25);\n try ages.put(\"Matheus\", 21);\n try ages.put(\"Abgail\", 42);\n\n var it = ages.iterator();\n while (it.next()) |kv| {\n std.debug.print(\"Key: {s} | \", .{kv.key_ptr.*});\n std.debug.print(\"Age: {d}\\n\", .{kv.value_ptr.*});\n }\n}\n```\n:::\n\n\n\n\n```\nKey: Pedro | Age: 25\nKey: Abgail | Age: 42\nKey: Matheus | Age: 21\n```\n\n\n### The `StringArrayHashMap` hashtable\n\nThe Zig Standard Library also provides a type of hashtable that mix the cons and pros of the\n`StringHashMap` and `ArrayHashMap` together. That is, a hashtable\nthat uses strings as keys, but also have the advantages from `ArrayHashMap`.\nIn other words, you can have a hashtable that is fast to iterate over,\nthat preserves insertion order, and also, that uses strings as keys.\n\nYou can create such type of hashtable by using the `StringArrayHashMap()` function.\nThis function accepts a data type as input, which is the data type of the values that are\ngoing to be stored inside this hashtable, in the same style as the function presented\nat @sec-string-hash-map.\n\nYou can insert new values into this hashtable by using the same `put()` method that\nwe have discussed at @sec-string-hash-map. And you can also get values from the hashtable\nby using the same `get()` method.\nLike its `ArrayHashMap` brother, to delete values from this specific type of hashtable,\nwe also use the `orderedRemove()` and `swapRemove()` methods, with the same effects that\nI have described at @sec-array-map.\n\nIf we take the code example that was exposed at @sec-string-hash-map, we can\nachieve the exact same result with `StringArrayHashMap()`:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar ages = std.StringArrayHashMap(u8).init(allocator);\n```\n:::\n\n\n\n\n\n\n\n## Linked lists\n\nThe Zig Standard Library provides an implementation for both singly and doubly linked lists.\nA linked list is a linear data structure that looks like a chain, or, a rope.\nThe main advantage of this data structure is that you normally have very fast\ninsertion and deletion operations. But, as a disadvantage, iterating through\nthis data structure is usually not so fast as iterating through an array.\n\nThe idea behind a linked list is to build a structure that consists of a sequence of nodes\nconnected to each other by pointers. This means that linked lists are usually not contiguous\nin memory, because each node might be anywhere in memory. They do not need to be close to\none another.\n\nAt @fig-linked-list we can see a diagram of a singly linked list. We begin at the first node\n(which is usually called \"the head of the linked list\"). Then, from this\nfirst node we uncover the remaining nodes in the structure, by following the locations pointed\nby the pointers found in each node.\n\nEach node has two things in it. It has the value that is stored in the current node\n, and also, a pointer. This pointer points to the next node in the list. If this pointer\nis null, then, it means that we have reached the end of our linked list.\n\n![A diagram of a singly linked list.](./../Figures/linked-list.png){#fig-linked-list}\n\n\nAt @fig-linked-list2 we can see a diagram of a doubly linked list. The only thing that really\nchanges now is that every node in the linked list has both a pointer to the previous node,\nand, a pointer to the next node. So every node in a doubly linked list has two pointers in it. These are\nusually called the `prev` (for \"previous\") and the `next` (for \"next\") pointers of the node.\n\nIn the singly linked list example, we had only one single pointer in each node, and this singular\npointer was always pointing to the next node in the sequence. This means that singly linked lists\nnormally have only the `next` pointer in them.\n\n![A diagram of a doubly linked list.](./../Figures/doubly-linked-list.png){#fig-linked-list2}\n\n\nLinked lists are available in Zig through the functions `SinglyLinkedList()` and\n`DoublyLinkedList()`, for \"singly linked lists\" and \"doubly linked lists\", respectively. These functions are\nactually generic functions, which we are going to talk more about at @sec-generic-fun.\n\nFor now, just understand that, in order to create a linked list object,\nwe begin by providing a data type to these functions. This data type defines\nthe type of data that each node in this linked list will store. In the example below,\nwe are creating a singly linked list of `u32` values.\nSo each node in this linked list will store a `u32` value.\n\nBoth the `SinglyLinkedList()` and `DoublyLinkedList()` functions returns a type,\ni.e. a struct definition, as output. Therefore, the object `Lu32` is actually\na struct definition. It defines the type \"singly linked list of `u32` values\".\n\nNow that we have the definition of the struct, we need to instantiate a `Lu32` object.\nWe normally instantiate struct objects in Zig by using an `init()` method.\nBut in this case, we are instantiating the struct directly, by using an empty\n`struct` literal, in the expression `Lu32{}`.\n\nIn this example, we first create multiple node objects, and after we create them,\nwe start to insert and connect these nodes to build the linked list, using the\n`prepend()` and `insertAfter()` methods. Notice that the `prepend()` method\nis a method from the linked list object, while the `insertAfter()` is a method\npresent in the node objects.\n\nIn essence, the `prepend()` method inserts a node at the beginning of the linked\nlist. In other words, the node that you provide to this method, becomes the new\n\"head node\" of the linked list. It becomes the first node in the list (see @fig-linked-list).\n\nOn the other side, the `insertAfter()` method is used to basically connect two nodes together.\nWhen you provide a node to this method, it creates a pointer to this input node,\nand stores this pointer in the `next` attribute of the current node, from which the method was called from.\n\nBecause doubly linked lists have both a `next` and a `prev` attributes in each node\n(as described at @fig-linked-list2), a node object created from\na `DoublyLinkedList` object have both an `insertBefore()` (for `prev`)\nand an `insertAfter()` (for `next`) methods available.\n\nThus, if we have used a doubly linked list, we can use the `insertBefore()` method\nto store the pointer to the input node in the `prev` attribute. This would put the input\nnode as the \"previous node\", or, the node before the current node. In contrast, the `insertAfter()` method\nputs the pointer created to the input node in the `next` attribute of the current node,\nand as result, the input node becomes the \"next node\" of the current node.\n\nSince we are using a singly linked list in this example, we have only the `insertAfter()` method\navailable in the node objects that we create from our `Lu32` type.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SinglyLinkedList = std.SinglyLinkedList;\nconst Lu32 = SinglyLinkedList(u32);\n\npub fn main() !void {\n var list = Lu32{};\n var one = Lu32.Node{ .data = 1 };\n var two = Lu32.Node{ .data = 2 };\n var three = Lu32.Node{ .data = 3 };\n var four = Lu32.Node{ .data = 4 };\n var five = Lu32.Node{ .data = 5 };\n\n list.prepend(&two); // {2}\n two.insertAfter(&five); // {2, 5}\n list.prepend(&one); // {1, 2, 5}\n two.insertAfter(&three); // {1, 2, 3, 5}\n three.insertAfter(&four); // {1, 2, 3, 4, 5}\n}\n```\n:::\n\n\n\n\n\nThere are other methods available from the linked list object, depending if this object is\na singly linked list or a doubly linked list, that might be very useful for you. You can find a\nsummary of them in the bullet points below:\n\n- `remove()` to remove a specific node from the linked list.\n- if singly linked list, `len()` to count how many nodes there is in the linked list.\n- if doubly linked list, checkout the `len` attribute to see how many nodes there is in the linked list.\n- if singly linked list, `popFirst()` to remove the first node (i.e. the \"head\") from the linked list.\n- if doubly linked list, `pop()` and `popFirst()` to remove the last and first nodes from the linked list, respectively.\n- if doubly linked list, `append()` to add a new node to end of the linked list (i.e. inverse of `prepend()`).\n\n\n\n## Multi array structure\n\nZig introduces a new data structure called `MultiArrayList()`. It is a different version of the dynamic array\nthat we have introduced at @sec-dynamic-array. The difference between this structure and the `ArrayList()`\nthat we know from @sec-dynamic-array, is that `MultiArrayList()` creates a separate dynamic array\nfor each field of the struct that you provide as input.\n\nConsider the following code example. We create a new custom struct called `Person`. This\nstruct contains three different data members, or, three different fields. As consequence,\nwhen we provide this `Person` data type as input to `MultiArrayList()`, this\ncreates a \"struct of three different arrays\" called `PersonArray`. In other words,\nthis `PersonArray` is a struct that contains three internal dynamic arrays in it.\nOne array for each field found in the `Person` struct definition.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Person = struct {\n name: []const u8,\n age: u8,\n height: f32,\n};\nconst PersonArray = std.MultiArrayList(Person);\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var people = PersonArray{};\n defer people.deinit(allocator);\n\n try people.append(allocator, .{\n .name = \"Auguste\", .age = 15, .height = 1.54\n });\n try people.append(allocator, .{\n .name = \"Elena\", .age = 26, .height = 1.65\n });\n try people.append(allocator, .{\n .name = \"Michael\", .age = 64, .height = 1.87\n });\n}\n```\n:::\n\n\n\n\nIn other words, instead of creating an array of \"persons\", the `MultiArrayList()` function\ncreates a \"struct of arrays\". Each data member of this struct is a different array that stores\nthe values of a specific field from the `Person` values that were added (or, appended) to this \"struct of arrays\".\nOne important detail is that each of these separate internal arrays stored inside `PersonArray`\nare dynamic arrays. This means that these arrays can grow in capacity automatically as needed, to accomodate\nmore values.\n\nThe @fig-multi-array exposed below presents a diagram that describes the `PersonArray` struct\nthat we have created in the previous code example. Notice that the values of the data members\npresent in each of the three `Person` values that we have appended into the `PersonArray` object\n, are scattered across three different internal arrays of the `PersonArray` object.\n\n![A diagram of the `PersonArray` struct.](./../Figures/multi-array.png){#fig-multi-array}\n\nYou can easily access each of these arrays separately, and iterate over the values of each array.\nFor that, you will need to call the `items()` method from the `PersonArray` object, and provide as input\nto this method, the name of the field that you want to iterate over.\nIf you want to iterate through the `.age` array for example, then, you need to call `items(.age)` from\nthe `PersonArray` object, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (people.items(.age)) |*age| {\n try stdout.print(\"Age: {d}\\n\", .{age.*});\n}\n```\n:::\n\n\n\n\n```\nAge: 15\nAge: 26\nAge: 64\n```\n\n\nIn the above example, we are iterating over the values of the `.age` array, or,\nthe internal array of the `PersonArray` object that contains the values of the `age`\ndata member from the `Person` values that were added to the multi array struct.\n\nIn this example we are calling the `items()` method directly from the `PersonArray`\nobject. However, it is recommended on most situations to call this `items()` method\nfrom a \"slice object\", which you can create from the `slice()` method.\nThe reason for this is that calling `items()` multiple times have better performance\nif you use a slice object.\n\nTherefore, if you are planning to access only one of the\ninternal arrays from your \"multi array struct\", it is fine to call `items()` directly\nfrom the multi array object. But if you need to access many of the internal arrays\nfrom your \"multi array struct\", then, you will likely need to call `items()` more\nthan once, and, in such circumstance, is better to call `items()` through a slice object.\nThe example below demonstrates the use of such object:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar slice = people.slice();\nfor (slice.items(.age)) |*age| {\n age.* += 10;\n}\nfor (slice.items(.name), slice.items(.age)) |*n,*a| {\n try stdout.print(\n \"Name: {s}, Age: {d}\\n\", .{n.*, a.*}\n );\n}\n```\n:::\n\n\n\n\n```\nName: Auguste, Age: 25\nName: Elena, Age: 36\nName: Michael, Age: 74\n```\n\n\n## Conclusion\n\nThere are many other data structures that I haven't presented here.\nBut you can check them out at the official Zig Standard Library documentation page.\nActually, when you get into the [homepage of the documentation](https://ziglang.org/documentation/master/std/#)[^home], the first thing\nthat appears to you in this page, is a list of types and data structures that\nare available in the Zig Standard Library.\nThere are some very specific data structures in this list, like a\n[`BoundedArray` struct](https://ziglang.org/documentation/master/std/#std.bounded_array.BoundedArray)[^bounded]\n, but there is also some more general structures, such as a\n[`PriorityQueue` struct](https://ziglang.org/documentation/master/std/#std.priority_queue.PriorityQueue)[^priority].\n\n\n[^home]: \n[^priority]: .\n[^bounded]: \n\n\n\n\n\n\n", - "supporting": [ - "09-data-structures_files" - ], + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/09-error-handling/execute-results/html.json b/_freeze/Chapters/09-error-handling/execute-results/html.json index a655e2a5..39ca6f04 100644 --- a/_freeze/Chapters/09-error-handling/execute-results/html.json +++ b/_freeze/Chapters/09-error-handling/execute-results/html.json @@ -2,7 +2,7 @@ "hash": "0e6b825195db1ba992b740206fa34ec0", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Error handling and unions {#sec-error-handling}\n\nIn this chapter, I want to discuss how error handling is done in Zig.\nWe already briefly learned about one of the available strategies to handle errors in Zig,\nwhich is the `try` keyword presented at @sec-main-file. But we still haven't learned about\nthe other methods, such as the `catch` keyword.\nI also want to discuss in this chapter how union types are created in Zig.\n\n## Learning more about errors in Zig\n\nBefore we get into how error handling is done, we need to learn more about what errors are in Zig.\nAn error is actually a value in Zig [@zigoverview]. In other words, when an error occurs inside your Zig program,\nit means that somewhere in your Zig codebase, an error value is being generated.\nAn error value is similar to any integer value that you create in your Zig code.\nYou can take an error value and pass it as input to a function,\nand you can also cast (or coerce) it into a different type of an error value.\n\nThis have some similarities with exceptions in C++ and Python.\nBecause in C++ and Python, when an exception happens inside a `try` block,\nyou can use a `catch` block (in C++) or an `except` block (in Python)\nto capture the exception produced in the `try` block,\nand pass it to functions as an input.\n\nHowever, error values in Zig are treated very differently than exceptions.\nFirst, you cannot ignore error values in your Zig code. Meaning that, if an error\nvalue appears somewhere in your source code, this error value must be explicitly handled in some way.\nThis also means that you cannot discard error values by assigning them to an underscore,\nas you could do with normal values and objects.\n\nTake the source code below as an example. Here we are trying to open a file that does not exist\nin my computer, and as a result, an obvious error value of `FileNotFound` is returned from the `openFile()`\nfunction. But because I'm assigning the result of this function to an underscore, I end up\ntrying to discard an error value.\n\nThe `zig` compiler detects this mistake, and raises a compile\nerror telling me that I'm trying to discard an error value.\nIt also adds a note message that suggests the use of `try`,\n`catch` or an if statement to explicitly handle this error value\nThis note is reinforcing that every possible error value must be explicitly handled in Zig.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst dir = std.fs.cwd();\n_ = dir.openFile(\"doesnt_exist.txt\", .{});\n```\n:::\n\n\n\n\n```\nt.zig:8:17: error: error set is discarded\nt.zig:8:17: note: consider using 'try', 'catch', or 'if'\n```\n\n\n### Returning errors from functions\n\nAs we described at @sec-main-file, when we have a function that might return an error\nvalue, this function normally includes an exclamation mark (`!`) in its return type\nannotation. The presence of this exclamation mark indicates that this function might\nreturn an error value as result, and, the `zig` compiler forces you to always handle explicitly\nthe case of this function returning an error value.\n\nTake a look at the `print_name()` function below. This function might return an error in the `stdout.print()` function call,\nand, as a consequence, its return type (`!void`) includes an exclamation mark in it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_name() !void {\n const stdout = std.getStdOut().writer();\n try stdout.print(\"My name is Pedro!\", .{});\n}\n```\n:::\n\n\n\n\nIn the example above, we are using the exclamation mark to tell the `zig` compiler\nthat this function might return some error. But which error exactly is returned from\nthis function? For now, we are not specifying a specific error value. We only\nknown for now that some error value (whatever it is) might be returned.\n\nBut in fact, you can (if you want to) specify clearly which exact error values\nmight be returned from this function. There are lot of examples of\nthis in the Zig Standard Library. Take this `fill()` function from\nthe `http.Client` module as an example. This function returns\neither a error value of type `ReadError`, or `void`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn fill(conn: *Connection) ReadError!void {\n // The body of this function ...\n}\n```\n:::\n\n\n\n\nThis idea of specifying the exact error values that you expect to be returned\nfrom the function is interesting. Because they automatically become some sort of documentation\nof your function, and also, it allows the `zig` compiler to perform some extra checks over\nyour code. Because it can check if there is any other type of error value\nthat is being generated inside your function, and, that it is not being accounted\nfor in this return type annotation.\n\nAnyway, you can list the types of errors that can be returned from the function\nby listing them on the left side of the exclamation mark. While the valid values\nstay on the right side of the exclamation mark. So the syntax format become:\n\n```\n!\n```\n\n\n### Error sets\n\nBut what about when we have a single function that might return different types of errors?\nWhen you have such a function, you can list\nall of these different types of errors that can be returned from this function,\nthrough a structure in Zig that we call of an *error set*.\n\nAn error set is a special case of an union type. It is an union that contains error values in it.\nNot all programming languages have a notion of an \"union object\".\nBut in summary, an union is just a set of data types.\nUnions are used to allow an object to have multiple data types.\nFor example, a union of `x`, `y` and `z`, means that\nan object can be either of type `x`, or type `y` or type `z`.\n\nWe are going to talk in more depth about unions at @sec-unions.\nBut you can write an error set by writing the keyword `error` before\na pair of curly braces, then you list the error values that can be\nreturned from the function inside this pair of curly braces.\n\nTake the `resolvePath()` function below as an example, which comes from the\n`introspect.zig` module of the Zig Standard Library. We can see in its return type annotation, that this\nfunction return either: 1) a valid slice of `u8` values (`[]u8`); or, 2) one of the three different\ntypes of error values listed inside the error set (`OutOfMemory`, `Unexpected`, etc.).\nThis is an usage example of an error set.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn resolvePath(\n ally: mem.Allocator,\n p: []const u8,\n) error{\n OutOfMemory,\n CurrentWorkingDirectoryUnlinked,\n Unexpected,\n}![]u8 {\n // The body of the function ...\n}\n```\n:::\n\n\n\n\n\nThis is a valid way of annotating the return value of a Zig function. But, if you navigate through\nthe modules that composes the Zig Standard Library, you will notice that, for the majority of cases,\nthe programmers prefer to give a descriptive name to this error set, and then, use this name (or this \"label\")\nof the error set in the return type annotation, instead of using the error set directly.\n\nWe can see that in the `ReadError` error set that we showed earlier in the `fill()` function,\nwhich is defined in the `http.Client` module.\nSo yes, I presented the `ReadError` as if it was just a standard and single error value, but in fact,\nit is an error set defined in the `http.Client` module, and therefore, it actually represents\na set of different error values that might happen inside the `fill()` function.\n\n\nTake a look at the `ReadError` definition reproduced below. Notice that we are grouping all of these\ndifferent error values into a single object, and then, we use this object into the return type annotation of the function.\nLike the `fill()` function that we showed earlier, or, the `readvDirect()` function from the same module,\nwhich is reproduced below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const ReadError = error{\n TlsFailure,\n TlsAlert,\n ConnectionTimedOut,\n ConnectionResetByPeer,\n UnexpectedReadFailure,\n EndOfStream,\n};\n// Some lines of code\npub fn readvDirect(\n conn: *Connection,\n buffers: []std.posix.iovec\n ) ReadError!usize {\n // The body of the function ...\n}\n```\n:::\n\n\n\n\nSo, an error set is just a convenient way of grouping a set of\npossible error values into a single object, or a single type of an error value.\n\n\n### Casting error values\n\nLet's suppose you have two different error sets, named `A` and `B`.\nIf error set `A` is a superset of error set `B`, then, you can cast (or coerce)\nerror values from `B` into error values of `A`.\n\nError sets are just a set of error values. So, if the error set `A`\ncontains all error values from the error set `B`, then `A`\nbecomes a superset of `B`. You could also say\nthat the error set `B` is a subset of error set `A`.\n\nThe example below demonstrates this idea. Because `A` contains all\nvalues from `B`, `A` is a superset of `B`.\nIn math notation, we would say that $A \\supset B$.\nAs a consequence, we can give an error value from `B` as input to the `cast()`\nfunction, and, implicitly cast this input into the same error value, but from the `A` set.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst A = error{\n ConnectionTimeoutError,\n DatabaseNotFound,\n OutOfMemory,\n InvalidToken,\n};\nconst B = error {\n OutOfMemory,\n};\n\nfn cast(err: B) A {\n return err;\n}\n\ntest \"coerce error value\" {\n const error_value = cast(B.OutOfMemory);\n try std.testing.expect(\n error_value == A.OutOfMemory\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file10459ffd0e21.test.coerce error value...OKA\n All 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n## How to handle errors\n\nNow that we learned more about what errors are in Zig,\nlet's discuss the available strategies to handle these errors,\nwhich are:\n\n- `try` keyword;\n- `catch` keyword;\n- an if statement;\n- `errdefer` keyword;\n\n\n\n### What `try` means?\n\nAs I described over the previous sections, when we say that an expression might\nreturn an error, we are basically referring to an expression that have\na return type in the format `!T`.\nThe `!` indicates that this expression returns either an error value, or a value of type `T`.\n\nAt @sec-main-file, I presented the `try` keyword and where to use it.\nBut I did not talked about what exactly this keyword does to your code,\nor, in other words, I have not explained yet what `try` means in your code.\n\nIn essence, when you use the `try` keyword in an expression, you are telling\nthe `zig` compiler the following: \"Hey! Execute this expression for me,\nand, if this expression return an error, please, return this error for me\nand stop the execution of my program. But if this expression return a valid\nvalue, then, return this value, and move on\".\n\nIn other words, the `try` keyword is essentially, a strategy to enter in panic mode, and stop\nthe execution of your program in case an error occurs.\nWith the `try` keyword, you are telling the `zig` compiler, that stopping the execution\nof your program is the most reasonable strategy to take if an error occurs\nin that particular expression.\n\n### The `catch` keyword\n\nOk, now that we understand properly what `try` means, let's discuss `catch` now.\nOne important detail here, is that you can use `try` or `catch` to handle your errors,\nbut you **cannot use `try` and `catch` together**. In other words, `try` and `catch`\nare different and completely separate strategies in the Zig language.\n\nThis is uncommon, and different than what happens in other languages. Most\nprogramming languages that adopts the *try catch* pattern (such as C++, R, Python, Javascript, etc.), normally use\nthese two keywords together to form the complete logic to\nproperly handle the errors.\nAnyway, Zig tries a different approach in the *try catch* pattern.\n\nSo, we learned already about what `try` means, and we also known that both\n`try` and `catch` should be used alone, separate from each other. But\nwhat exactly `catch` do in Zig? With `catch`, we can construct a block of\nlogic to handle the error value, in case it happens in the current expression.\n\nLook at the code example below. Once again, we go back to the previous\nexample where we were trying to open a file that doesn't exist in my computer,\nbut this time, I use `catch` to actually implement a logic to handle the error, instead of\njust stopping the execution right away.\n\nMore specifically, in this example, I'm using a logger object to record some logs into\nthe system, before I return the error, and stop the execution of the program. For example,\nthis could be some part of the codebase of a complex system that I do not have full control over,\nand I want to record these logs before the program crashes, so that I can debug it later\n(e.g. maybe I cannot compile the full program, and properly debug it with a debugger. So, these logs might\nbe a valid strategy to surpass this barrier).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst dir = std.fs.cwd();\nconst file = dir.openFile(\n \"doesnt_exist.txt\", .{}\n) catch |err| {\n logger.record_context();\n logger.log_error(err);\n return err;\n};\n```\n:::\n\n\n\n\n\nTherefore, we use `catch` to create a block of expressions that will handle the error.\nI can return the error value from this block of expressions, like I did in the above example,\nwhich, will make the program enter in panic mode, and, stop the execution.\nBut I could also, return a valid value from this block of code, which would\nbe stored in the `file` object.\n\nNotice that, instead of writing the keyword before the expression that might return the error,\nlike we do with `try`, we write `catch` after the expression. We can open the pair of pipes (`|`),\nwhich captures the error value returned by the expression, and makes\nthis error value available in the scope of the `catch` block as the object named `err`.\nIn other words, because I wrote `|err|` in the code, I can access the error value\nreturned by the expression, by using the `err` object.\n\nAlthough this being the most common use of `catch`, you can also use this keyword\nto handle the error in a \"default value\" style. That is, if the expression returns\nan error, we use the default value instead. Otherwise, we use the valid value returned\nby the expression.\n\nThe Zig official language reference, provides a great example of this \"default value\"\nstrategy with `catch`. This example is reproduced below. Notice that we are trying to parse\nsome unsigned integer from a string object named `str`. In other words, this function\nis trying to transform an object of type `[]const u8` (i.e. an array of characters, a string, etc.)\ninto an object of type `u64`.\n\nBut this parsing process done by the function `parseU64()` may fail, resulting in a runtime error.\nThe `catch` keyword used in this example provides an alternative value (13) to be used in case\nthis `parseU64()` function raises an error. So, the expression below essentially means:\n\"Hey! Please, parse this string into a `u64` for me, and store the results into the\nobject `number`. But, if an error occurs, then, use the value `13` instead\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number = parseU64(str, 10) catch 13;\n```\n:::\n\n\n\n\nSo, at the end of this process, the object `number` will contain either a `u64` integer\nthat was parsed successfully from the input string `str`, or, if an error occurs in the\nparsing process, it will contain the `u64` value `13` that was provided by the `catch`\nkeyword as the \"default\", or, the \"alternative\" value.\n\n\n\n### Using if statements\n\nNow, you can also use if statements to handle errors in your Zig code.\nIn the example below, I'm reproducing the previous example, where\nwe try to parse an integer value from an input string with a function\nnamed `parseU64()`.\n\nWe execute the expression inside the \"if\". If this expression returns an\nerror value, the \"if branch\" (or, the \"true branch\") of the if statement is not executed.\nBut if this expression returns a valid value instead, then, this value is unwrapped\ninto the `number` object.\n\nThis means that, if the `parseU64()` expression returns a valid value, this value becomes available\ninside the scope of this \"if branch\" (i.e. the \"true branch\") through the object that we listed inside the pair\nof pipe character (`|`), which is the object `number`.\n\nIf an error occurs, we can use an \"else branch\" (or the \"false branch\") of the if statement\nto handle the error. In the example below, we are using the `else` in the if statement\nto unwrap the error value (that was returned by `parseU64()`) into the `err` object,\nand handle the error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (parseU64(str, 10)) |number| {\n // do something with `number` here\n} else |err| {\n // handle the error value.\n}\n```\n:::\n\n\n\n\nNow, if the expression that you are executing returns different types of error values,\nand you want to take a different action in each of these types of error values, the\n`try` and `catch` keywords, and the if statement strategy, becomes limited.\n\nFor this type of situation, the official documentation of the language suggests\nthe use of a switch statement together with an if statement [@zigdocs].\nThe basic idea is, to use the if statement to execute the expression, and\nuse the \"else branch\" to pass the error value to a switch statement, where\nyou define a different action for each type of error value that might be\nreturned by the expression executed in the if statement.\n\nThe example below demonstrates this idea. We first try to add (or register) a set of\ntasks to a queue. If this \"registration process\" occurs well, we then try\nto distribute these tasks across the workers of our system. But\nif this \"registration process\" returns an error value, we then use a switch\nstatement in the \"else branch\" to handle each possible error value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (add_tasks_to_queue(&queue, tasks)) |_| {\n distribute_tasks(&queue);\n} else |err| switch (err) {\n error.InvalidTaskName => {\n // do something\n },\n error.TimeoutTooBig => {\n // do something\n },\n error.QueueNotFound => {\n // do something\n },\n // and all the other error options ...\n}\n```\n:::\n\n\n\n\n\n### The `errdefer` keyword {#sec-errdefer2}\n\nA common pattern in C programs in general, is to clean resources when an error occurs during\nthe execution of the program. In other words, one common way to handle errors, is to perform\n\"cleanup actions\" before we exit our program. This guarantees that a runtime error does not make\nour program to leak resources of the system.\n\n\nThe `errdefer` keyword is a tool to perform such \"cleanup actions\" in hostile situations.\nThis keyword is commonly used to clean (or to free) allocated resources, before the execution of our program\nget's stopped because of an error value being generated.\n\nThe basic idea is to provide an expression to the `errdefer` keyword. Then,\n`errdefer` executes this expression if, and only if, an error occurs\nduring the execution of the current scope.\nIn the example below, we are using an allocator object (that we have presented at @sec-allocators)\nto create a new `User` object. If we are successful in creating and registering this new user,\nthis `create_user()` function will return this new `User` object as its return value.\n\nHowever, if for some reason, an error value is generated by some expression\nthat is after the `errdefer` line, for example, in the `db.add(user)` expression,\nthe expression registered by `errdefer` get's executed before the error value is returned\nfrom the function, and before the program enters in panic mode and stops the\ncurrent execution.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn create_user(db: Database, allocator: Allocator) !User {\n const user = try allocator.create(User);\n errdefer allocator.destroy(user);\n\n // Register new user in the Database.\n _ = try db.register_user(user);\n return user;\n}\n```\n:::\n\n\n\n\nBy using `errdefer` to destroy the `user` object that we have just created,\nwe guarantee that the memory allocated for this `user` object\nget's freed, before the execution of the program stops.\nBecause if the expression `try db.add(user)` returns an error value,\nthe execution of our program stops, and we lose all references and control over the memory\nthat we have allocated for the `user` object.\nAs a result, if we do not free the memory associated with the `user` object before the program stops,\nwe cannot free this memory anymore. We simply lose our chance to do the right thing.\nThat is why `errdefer` is essential in this situation.\n\nJust to state clearly the differences between `defer` and `errdefer`\n(which I described at @sec-defer and @sec-errdefer1), it might be worth\nto discuss the subject a bit further. You might still have the question\n\"why use `errdefer` if we can use `defer` instead?\" in your mind.\n\nAlthough being similar, the key difference between `errdefer` and `defer` keyword\nis when the provided expression get's executed.\nThe `defer` keyword always execute the provided expression at the end of the\ncurrent scope, no matter how your code exits this scope.\nIn contrast, `errdefer` executes the provided expression only when an error occurs in the\ncurrent scope.\n\nThis becomes important if a resource that you allocate in the\ncurrent scope get's freed later in your code, in a different scope.\nThe `create_user()` functions is an example of this. If you think\nclosely about this function, you will notice that this function returns\nthe `user` object as the result.\n\nIn other words, the allocated memory for the `user` object does not get\nfreed inside the `create_user()` function, if it returns successfully.\nSo, if an error does not occur inside this function, the `user` object\nis returned from the function, and probably, the code that runs after\nthis `create_user()` function will be responsible for freeing\nthe memory of the `user` object.\n\nBut what if an error occurs inside the `create_user()` function? What happens then?\nThis would mean that the execution of your code would stop in this `create_user()`\nfunction, and, as a consequence, the code that runs after this `create_user()`\nfunction would simply not run, and, as a result, the memory of the `user` object\nwould not be freed before your program stops.\n\nThis is the perfect scenario for `errdefer`. We use this keyword to guarantee\nthat our program will free the allocated memory for the `user` object,\neven if an error occurs inside the `create_user()` function.\n\nIf you allocate and free some memory for an object inside the same scope, then,\njust use `defer` and be happy, i.e. `errdefer` have no use for you in such situation.\nBut if you allocate some memory in a scope A, but you only free this memory\nlater, in a scope B for example, then, `errdefer` becomes useful to avoid leaking memory\nin sketchy situations.\n\n\n\n## Union type in Zig {#sec-unions}\n\nAn union type defines a set of types that an object can be. It is like a list of\noptions. Each option is a type that an object can assume. Therefore, unions in Zig\nhave the same meaning, or, the same role as unions in C. They are used for the same purpose.\nYou could also say that unions in Zig produces a similar effect to\n[using `typing.Union` in Python](https://docs.python.org/3/library/typing.html#typing.Union)[^pyunion].\n\n[^pyunion]: \n\nFor example, you might be creating an API that sends data to a data lake, hosted\nin some private cloud infrastructure. Suppose you have created different structs in your codebase,\nto store the necessary information that you need, in order to connect to the services of\neach mainstream data lake service (Amazon S3, Azure Blob, etc.).\n\nNow, suppose you also have a function named `send_event()` that receives an event as input,\nand, a target data lake, and it sends the input event to the data lake specified in the\ntarget data lake argument. But this target data lake could be any of the three mainstream data lakes\nservices (Amazon S3, Azure Blob, etc.). Here is where an union can help you.\n\nThe union `LakeTarget` defined below allows the `lake_target` argument of `send_event()`\nto be either an object of type `AzureBlob`, or type `AmazonS3`, or type `GoogleGCP`.\nThis union allows the `send_event()` function to receive an object of any of these three types\nas input in the `lake_target` argument.\n\nRemember that each of these three types (`AmazonS3`, `GoogleGCP` and `AzureBlob`)\nare separate structs that we have defined in our source code. So, at first glance,\nthey are separate data types in our source code. But is the `union` keyword that\nunifies them into a single data type called `LakeTarget`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst LakeTarget = union {\n azure: AzureBlob,\n amazon: AmazonS3,\n google: GoogleGCP,\n};\n\nfn send_event(\n event: Event,\n lake_target: LakeTarget\n) bool {\n // body of the function ...\n}\n```\n:::\n\n\n\n\nAn union definition is composed by a list of data members. Each data member is of a specific data type.\nIn the example above, the `LakeTarget` union have three data members (`azure`, `amazon`, `google`).\nWhen you instantiate an object that uses an union type, you can only use one of its data members\nin this instantiation.\n\nYou could also interpret this as: only one data member of an union type can be activated at a time, the other data\nmembers remain deactivated and unaccessible. For example, if you create a `LakeTarget` object that uses\nthe `azure` data member, you can no longer use or access the data members `google` or `amazon`.\nIt is like if these other data members didn't exist at all in the `LakeTarget` type.\n\nYou can see this logic in the example below. Notice that, we first instantiate the union\nobject using the `azure` data member. As a result, this `target` object contains only\nthe `azure` data member inside of it. Only this data member is active in this object.\nThat is why the last line in this code example is invalid. Because we are trying to instantiate the data member\n`google`, which is currently inactive for this `target` object, and as a result, the program\nenters in panic mode warning us about this mistake through a loud error message.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar target = LakeTarget {\n .azure = AzureBlob.init()\n};\n// Only the `azure` data member exist inside\n// the `target` object, and, as a result, this\n// line below is invalid:\ntarget.google = GoogleGCP.init();\n```\n:::\n\n\n\n\n```\nthread 2177312 panic: access of union field 'google' while\n field 'azure' is active:\n target.google = GoogleGCP.init();\n ^\n```\n\nSo, when you instantiate an union object, you must choose one of the data types (or, one of the data members)\nlisted in the union type. In the example above, I choose to use the `azure` data member, and, as a result,\nall other data members were automatically deactivated,\nand you can no longer use them after you instantiate the object.\n\nYou can activate another data member by completely redefining the entire enum object.\nIn the example below, I initially use the `azure` data member. But then, I redefine the\n`target` object to use a new `LakeTarget` object, which uses the `google` data member.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar target = LakeTarget {\n .azure = AzureBlob.init()\n};\ntarget = LakeTarget {\n .google = GoogleGCP.init()\n};\n```\n:::\n\n\n\n\nA curious fact about union types, is that, at first, you cannot use them in switch statements (which were presented at @sec-switch).\nIn other words, if you have an object of type `LakeTarget` for example, you cannot give this object\nas input to a switch statement.\n\nBut what if you really need to do so? What if you actually need to\nprovide an \"union object\" to a switch statement? The answer to this question relies on another special type in Zig,\nwhich are the *tagged unions*. To create a tagged union, all you have to do is to add\nan enum type into your union declaration.\n\nAs an example of a tagged union in Zig, take the `Registry` type exposed\nbelow. This type comes from the\n[`grammar.zig` module](https://github.com/ziglang/zig/blob/30b4a87db711c368853b3eff8e214ab681810ef9/tools/spirv/grammar.zig)[^grammar]\nfrom the Zig repository. This union type lists different types of registries.\nBut notice this time, the use of `(enum)` after the `union` keyword. This is what makes\nthis union type a tagged union. By being a tagged union, an object of this `Registry` type\ncan be used as input in a switch statement. This is all you have to do. Just add `(enum)`\nto your `union` declaration, and you can use it in switch statements.\n\n[^grammar]: .\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Registry = union(enum) {\n core: CoreRegistry,\n extension: ExtensionRegistry,\n};\n```\n:::\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Error handling and unions {#sec-error-handling}\n\nIn this chapter, I want to discuss how error handling is done in Zig.\nWe already briefly learned about one of the available strategies to handle errors in Zig,\nwhich is the `try` keyword presented at @sec-main-file. But we still haven't learned about\nthe other methods, such as the `catch` keyword.\nI also want to discuss in this chapter how union types are created in Zig.\n\n## Learning more about errors in Zig\n\nBefore we get into how error handling is done, we need to learn more about what errors are in Zig.\nAn error is actually a value in Zig [@zigoverview]. In other words, when an error occurs inside your Zig program,\nit means that somewhere in your Zig codebase, an error value is being generated.\nAn error value is similar to any integer value that you create in your Zig code.\nYou can take an error value and pass it as input to a function,\nand you can also cast (or coerce) it into a different type of an error value.\n\nThis have some similarities with exceptions in C++ and Python.\nBecause in C++ and Python, when an exception happens inside a `try` block,\nyou can use a `catch` block (in C++) or an `except` block (in Python)\nto capture the exception produced in the `try` block,\nand pass it to functions as an input.\n\nHowever, error values in Zig are treated very differently than exceptions.\nFirst, you cannot ignore error values in your Zig code. Meaning that, if an error\nvalue appears somewhere in your source code, this error value must be explicitly handled in some way.\nThis also means that you cannot discard error values by assigning them to an underscore,\nas you could do with normal values and objects.\n\nTake the source code below as an example. Here we are trying to open a file that does not exist\nin my computer, and as a result, an obvious error value of `FileNotFound` is returned from the `openFile()`\nfunction. But because I'm assigning the result of this function to an underscore, I end up\ntrying to discard an error value.\n\nThe `zig` compiler detects this mistake, and raises a compile\nerror telling me that I'm trying to discard an error value.\nIt also adds a note message that suggests the use of `try`,\n`catch` or an if statement to explicitly handle this error value\nThis note is reinforcing that every possible error value must be explicitly handled in Zig.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst dir = std.fs.cwd();\n_ = dir.openFile(\"doesnt_exist.txt\", .{});\n```\n:::\n\n\n\n\n```\nt.zig:8:17: error: error set is discarded\nt.zig:8:17: note: consider using 'try', 'catch', or 'if'\n```\n\n\n### Returning errors from functions\n\nAs we described at @sec-main-file, when we have a function that might return an error\nvalue, this function normally includes an exclamation mark (`!`) in its return type\nannotation. The presence of this exclamation mark indicates that this function might\nreturn an error value as result, and, the `zig` compiler forces you to always handle explicitly\nthe case of this function returning an error value.\n\nTake a look at the `print_name()` function below. This function might return an error in the `stdout.print()` function call,\nand, as a consequence, its return type (`!void`) includes an exclamation mark in it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_name() !void {\n const stdout = std.getStdOut().writer();\n try stdout.print(\"My name is Pedro!\", .{});\n}\n```\n:::\n\n\n\n\nIn the example above, we are using the exclamation mark to tell the `zig` compiler\nthat this function might return some error. But which error exactly is returned from\nthis function? For now, we are not specifying a specific error value. We only\nknown for now that some error value (whatever it is) might be returned.\n\nBut in fact, you can (if you want to) specify clearly which exact error values\nmight be returned from this function. There are lot of examples of\nthis in the Zig Standard Library. Take this `fill()` function from\nthe `http.Client` module as an example. This function returns\neither a error value of type `ReadError`, or `void`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn fill(conn: *Connection) ReadError!void {\n // The body of this function ...\n}\n```\n:::\n\n\n\n\nThis idea of specifying the exact error values that you expect to be returned\nfrom the function is interesting. Because they automatically become some sort of documentation\nof your function, and also, it allows the `zig` compiler to perform some extra checks over\nyour code. Because it can check if there is any other type of error value\nthat is being generated inside your function, and, that it is not being accounted\nfor in this return type annotation.\n\nAnyway, you can list the types of errors that can be returned from the function\nby listing them on the left side of the exclamation mark. While the valid values\nstay on the right side of the exclamation mark. So the syntax format become:\n\n```\n!\n```\n\n\n### Error sets\n\nBut what about when we have a single function that might return different types of errors?\nWhen you have such a function, you can list\nall of these different types of errors that can be returned from this function,\nthrough a structure in Zig that we call of an *error set*.\n\nAn error set is a special case of an union type. It is an union that contains error values in it.\nNot all programming languages have a notion of an \"union object\".\nBut in summary, an union is just a set of data types.\nUnions are used to allow an object to have multiple data types.\nFor example, a union of `x`, `y` and `z`, means that\nan object can be either of type `x`, or type `y` or type `z`.\n\nWe are going to talk in more depth about unions at @sec-unions.\nBut you can write an error set by writing the keyword `error` before\na pair of curly braces, then you list the error values that can be\nreturned from the function inside this pair of curly braces.\n\nTake the `resolvePath()` function below as an example, which comes from the\n`introspect.zig` module of the Zig Standard Library. We can see in its return type annotation, that this\nfunction return either: 1) a valid slice of `u8` values (`[]u8`); or, 2) one of the three different\ntypes of error values listed inside the error set (`OutOfMemory`, `Unexpected`, etc.).\nThis is an usage example of an error set.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn resolvePath(\n ally: mem.Allocator,\n p: []const u8,\n) error{\n OutOfMemory,\n CurrentWorkingDirectoryUnlinked,\n Unexpected,\n}![]u8 {\n // The body of the function ...\n}\n```\n:::\n\n\n\n\n\nThis is a valid way of annotating the return value of a Zig function. But, if you navigate through\nthe modules that composes the Zig Standard Library, you will notice that, for the majority of cases,\nthe programmers prefer to give a descriptive name to this error set, and then, use this name (or this \"label\")\nof the error set in the return type annotation, instead of using the error set directly.\n\nWe can see that in the `ReadError` error set that we showed earlier in the `fill()` function,\nwhich is defined in the `http.Client` module.\nSo yes, I presented the `ReadError` as if it was just a standard and single error value, but in fact,\nit is an error set defined in the `http.Client` module, and therefore, it actually represents\na set of different error values that might happen inside the `fill()` function.\n\n\nTake a look at the `ReadError` definition reproduced below. Notice that we are grouping all of these\ndifferent error values into a single object, and then, we use this object into the return type annotation of the function.\nLike the `fill()` function that we showed earlier, or, the `readvDirect()` function from the same module,\nwhich is reproduced below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const ReadError = error{\n TlsFailure,\n TlsAlert,\n ConnectionTimedOut,\n ConnectionResetByPeer,\n UnexpectedReadFailure,\n EndOfStream,\n};\n// Some lines of code\npub fn readvDirect(\n conn: *Connection,\n buffers: []std.posix.iovec\n ) ReadError!usize {\n // The body of the function ...\n}\n```\n:::\n\n\n\n\nSo, an error set is just a convenient way of grouping a set of\npossible error values into a single object, or a single type of an error value.\n\n\n### Casting error values\n\nLet's suppose you have two different error sets, named `A` and `B`.\nIf error set `A` is a superset of error set `B`, then, you can cast (or coerce)\nerror values from `B` into error values of `A`.\n\nError sets are just a set of error values. So, if the error set `A`\ncontains all error values from the error set `B`, then `A`\nbecomes a superset of `B`. You could also say\nthat the error set `B` is a subset of error set `A`.\n\nThe example below demonstrates this idea. Because `A` contains all\nvalues from `B`, `A` is a superset of `B`.\nIn math notation, we would say that $A \\supset B$.\nAs a consequence, we can give an error value from `B` as input to the `cast()`\nfunction, and, implicitly cast this input into the same error value, but from the `A` set.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst A = error{\n ConnectionTimeoutError,\n DatabaseNotFound,\n OutOfMemory,\n InvalidToken,\n};\nconst B = error {\n OutOfMemory,\n};\n\nfn cast(err: B) A {\n return err;\n}\n\ntest \"coerce error value\" {\n const error_value = cast(B.OutOfMemory);\n try std.testing.expect(\n error_value == A.OutOfMemory\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filea64e1da1167c.test.coerce error value...OKA\n All 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n## How to handle errors\n\nNow that we learned more about what errors are in Zig,\nlet's discuss the available strategies to handle these errors,\nwhich are:\n\n- `try` keyword;\n- `catch` keyword;\n- an if statement;\n- `errdefer` keyword;\n\n\n\n### What `try` means?\n\nAs I described over the previous sections, when we say that an expression might\nreturn an error, we are basically referring to an expression that have\na return type in the format `!T`.\nThe `!` indicates that this expression returns either an error value, or a value of type `T`.\n\nAt @sec-main-file, I presented the `try` keyword and where to use it.\nBut I did not talked about what exactly this keyword does to your code,\nor, in other words, I have not explained yet what `try` means in your code.\n\nIn essence, when you use the `try` keyword in an expression, you are telling\nthe `zig` compiler the following: \"Hey! Execute this expression for me,\nand, if this expression return an error, please, return this error for me\nand stop the execution of my program. But if this expression return a valid\nvalue, then, return this value, and move on\".\n\nIn other words, the `try` keyword is essentially, a strategy to enter in panic mode, and stop\nthe execution of your program in case an error occurs.\nWith the `try` keyword, you are telling the `zig` compiler, that stopping the execution\nof your program is the most reasonable strategy to take if an error occurs\nin that particular expression.\n\n### The `catch` keyword\n\nOk, now that we understand properly what `try` means, let's discuss `catch` now.\nOne important detail here, is that you can use `try` or `catch` to handle your errors,\nbut you **cannot use `try` and `catch` together**. In other words, `try` and `catch`\nare different and completely separate strategies in the Zig language.\n\nThis is uncommon, and different than what happens in other languages. Most\nprogramming languages that adopts the *try catch* pattern (such as C++, R, Python, Javascript, etc.), normally use\nthese two keywords together to form the complete logic to\nproperly handle the errors.\nAnyway, Zig tries a different approach in the *try catch* pattern.\n\nSo, we learned already about what `try` means, and we also known that both\n`try` and `catch` should be used alone, separate from each other. But\nwhat exactly `catch` do in Zig? With `catch`, we can construct a block of\nlogic to handle the error value, in case it happens in the current expression.\n\nLook at the code example below. Once again, we go back to the previous\nexample where we were trying to open a file that doesn't exist in my computer,\nbut this time, I use `catch` to actually implement a logic to handle the error, instead of\njust stopping the execution right away.\n\nMore specifically, in this example, I'm using a logger object to record some logs into\nthe system, before I return the error, and stop the execution of the program. For example,\nthis could be some part of the codebase of a complex system that I do not have full control over,\nand I want to record these logs before the program crashes, so that I can debug it later\n(e.g. maybe I cannot compile the full program, and properly debug it with a debugger. So, these logs might\nbe a valid strategy to surpass this barrier).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst dir = std.fs.cwd();\nconst file = dir.openFile(\n \"doesnt_exist.txt\", .{}\n) catch |err| {\n logger.record_context();\n logger.log_error(err);\n return err;\n};\n```\n:::\n\n\n\n\n\nTherefore, we use `catch` to create a block of expressions that will handle the error.\nI can return the error value from this block of expressions, like I did in the above example,\nwhich, will make the program enter in panic mode, and, stop the execution.\nBut I could also, return a valid value from this block of code, which would\nbe stored in the `file` object.\n\nNotice that, instead of writing the keyword before the expression that might return the error,\nlike we do with `try`, we write `catch` after the expression. We can open the pair of pipes (`|`),\nwhich captures the error value returned by the expression, and makes\nthis error value available in the scope of the `catch` block as the object named `err`.\nIn other words, because I wrote `|err|` in the code, I can access the error value\nreturned by the expression, by using the `err` object.\n\nAlthough this being the most common use of `catch`, you can also use this keyword\nto handle the error in a \"default value\" style. That is, if the expression returns\nan error, we use the default value instead. Otherwise, we use the valid value returned\nby the expression.\n\nThe Zig official language reference, provides a great example of this \"default value\"\nstrategy with `catch`. This example is reproduced below. Notice that we are trying to parse\nsome unsigned integer from a string object named `str`. In other words, this function\nis trying to transform an object of type `[]const u8` (i.e. an array of characters, a string, etc.)\ninto an object of type `u64`.\n\nBut this parsing process done by the function `parseU64()` may fail, resulting in a runtime error.\nThe `catch` keyword used in this example provides an alternative value (13) to be used in case\nthis `parseU64()` function raises an error. So, the expression below essentially means:\n\"Hey! Please, parse this string into a `u64` for me, and store the results into the\nobject `number`. But, if an error occurs, then, use the value `13` instead\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number = parseU64(str, 10) catch 13;\n```\n:::\n\n\n\n\nSo, at the end of this process, the object `number` will contain either a `u64` integer\nthat was parsed successfully from the input string `str`, or, if an error occurs in the\nparsing process, it will contain the `u64` value `13` that was provided by the `catch`\nkeyword as the \"default\", or, the \"alternative\" value.\n\n\n\n### Using if statements\n\nNow, you can also use if statements to handle errors in your Zig code.\nIn the example below, I'm reproducing the previous example, where\nwe try to parse an integer value from an input string with a function\nnamed `parseU64()`.\n\nWe execute the expression inside the \"if\". If this expression returns an\nerror value, the \"if branch\" (or, the \"true branch\") of the if statement is not executed.\nBut if this expression returns a valid value instead, then, this value is unwrapped\ninto the `number` object.\n\nThis means that, if the `parseU64()` expression returns a valid value, this value becomes available\ninside the scope of this \"if branch\" (i.e. the \"true branch\") through the object that we listed inside the pair\nof pipe character (`|`), which is the object `number`.\n\nIf an error occurs, we can use an \"else branch\" (or the \"false branch\") of the if statement\nto handle the error. In the example below, we are using the `else` in the if statement\nto unwrap the error value (that was returned by `parseU64()`) into the `err` object,\nand handle the error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (parseU64(str, 10)) |number| {\n // do something with `number` here\n} else |err| {\n // handle the error value.\n}\n```\n:::\n\n\n\n\nNow, if the expression that you are executing returns different types of error values,\nand you want to take a different action in each of these types of error values, the\n`try` and `catch` keywords, and the if statement strategy, becomes limited.\n\nFor this type of situation, the official documentation of the language suggests\nthe use of a switch statement together with an if statement [@zigdocs].\nThe basic idea is, to use the if statement to execute the expression, and\nuse the \"else branch\" to pass the error value to a switch statement, where\nyou define a different action for each type of error value that might be\nreturned by the expression executed in the if statement.\n\nThe example below demonstrates this idea. We first try to add (or register) a set of\ntasks to a queue. If this \"registration process\" occurs well, we then try\nto distribute these tasks across the workers of our system. But\nif this \"registration process\" returns an error value, we then use a switch\nstatement in the \"else branch\" to handle each possible error value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (add_tasks_to_queue(&queue, tasks)) |_| {\n distribute_tasks(&queue);\n} else |err| switch (err) {\n error.InvalidTaskName => {\n // do something\n },\n error.TimeoutTooBig => {\n // do something\n },\n error.QueueNotFound => {\n // do something\n },\n // and all the other error options ...\n}\n```\n:::\n\n\n\n\n\n### The `errdefer` keyword {#sec-errdefer2}\n\nA common pattern in C programs in general, is to clean resources when an error occurs during\nthe execution of the program. In other words, one common way to handle errors, is to perform\n\"cleanup actions\" before we exit our program. This guarantees that a runtime error does not make\nour program to leak resources of the system.\n\n\nThe `errdefer` keyword is a tool to perform such \"cleanup actions\" in hostile situations.\nThis keyword is commonly used to clean (or to free) allocated resources, before the execution of our program\nget's stopped because of an error value being generated.\n\nThe basic idea is to provide an expression to the `errdefer` keyword. Then,\n`errdefer` executes this expression if, and only if, an error occurs\nduring the execution of the current scope.\nIn the example below, we are using an allocator object (that we have presented at @sec-allocators)\nto create a new `User` object. If we are successful in creating and registering this new user,\nthis `create_user()` function will return this new `User` object as its return value.\n\nHowever, if for some reason, an error value is generated by some expression\nthat is after the `errdefer` line, for example, in the `db.add(user)` expression,\nthe expression registered by `errdefer` get's executed before the error value is returned\nfrom the function, and before the program enters in panic mode and stops the\ncurrent execution.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn create_user(db: Database, allocator: Allocator) !User {\n const user = try allocator.create(User);\n errdefer allocator.destroy(user);\n\n // Register new user in the Database.\n _ = try db.register_user(user);\n return user;\n}\n```\n:::\n\n\n\n\nBy using `errdefer` to destroy the `user` object that we have just created,\nwe guarantee that the memory allocated for this `user` object\nget's freed, before the execution of the program stops.\nBecause if the expression `try db.add(user)` returns an error value,\nthe execution of our program stops, and we lose all references and control over the memory\nthat we have allocated for the `user` object.\nAs a result, if we do not free the memory associated with the `user` object before the program stops,\nwe cannot free this memory anymore. We simply lose our chance to do the right thing.\nThat is why `errdefer` is essential in this situation.\n\nJust to state clearly the differences between `defer` and `errdefer`\n(which I described at @sec-defer and @sec-errdefer1), it might be worth\nto discuss the subject a bit further. You might still have the question\n\"why use `errdefer` if we can use `defer` instead?\" in your mind.\n\nAlthough being similar, the key difference between `errdefer` and `defer` keyword\nis when the provided expression get's executed.\nThe `defer` keyword always execute the provided expression at the end of the\ncurrent scope, no matter how your code exits this scope.\nIn contrast, `errdefer` executes the provided expression only when an error occurs in the\ncurrent scope.\n\nThis becomes important if a resource that you allocate in the\ncurrent scope get's freed later in your code, in a different scope.\nThe `create_user()` functions is an example of this. If you think\nclosely about this function, you will notice that this function returns\nthe `user` object as the result.\n\nIn other words, the allocated memory for the `user` object does not get\nfreed inside the `create_user()` function, if it returns successfully.\nSo, if an error does not occur inside this function, the `user` object\nis returned from the function, and probably, the code that runs after\nthis `create_user()` function will be responsible for freeing\nthe memory of the `user` object.\n\nBut what if an error occurs inside the `create_user()` function? What happens then?\nThis would mean that the execution of your code would stop in this `create_user()`\nfunction, and, as a consequence, the code that runs after this `create_user()`\nfunction would simply not run, and, as a result, the memory of the `user` object\nwould not be freed before your program stops.\n\nThis is the perfect scenario for `errdefer`. We use this keyword to guarantee\nthat our program will free the allocated memory for the `user` object,\neven if an error occurs inside the `create_user()` function.\n\nIf you allocate and free some memory for an object inside the same scope, then,\njust use `defer` and be happy, i.e. `errdefer` have no use for you in such situation.\nBut if you allocate some memory in a scope A, but you only free this memory\nlater, in a scope B for example, then, `errdefer` becomes useful to avoid leaking memory\nin sketchy situations.\n\n\n\n## Union type in Zig {#sec-unions}\n\nAn union type defines a set of types that an object can be. It is like a list of\noptions. Each option is a type that an object can assume. Therefore, unions in Zig\nhave the same meaning, or, the same role as unions in C. They are used for the same purpose.\nYou could also say that unions in Zig produces a similar effect to\n[using `typing.Union` in Python](https://docs.python.org/3/library/typing.html#typing.Union)[^pyunion].\n\n[^pyunion]: \n\nFor example, you might be creating an API that sends data to a data lake, hosted\nin some private cloud infrastructure. Suppose you have created different structs in your codebase,\nto store the necessary information that you need, in order to connect to the services of\neach mainstream data lake service (Amazon S3, Azure Blob, etc.).\n\nNow, suppose you also have a function named `send_event()` that receives an event as input,\nand, a target data lake, and it sends the input event to the data lake specified in the\ntarget data lake argument. But this target data lake could be any of the three mainstream data lakes\nservices (Amazon S3, Azure Blob, etc.). Here is where an union can help you.\n\nThe union `LakeTarget` defined below allows the `lake_target` argument of `send_event()`\nto be either an object of type `AzureBlob`, or type `AmazonS3`, or type `GoogleGCP`.\nThis union allows the `send_event()` function to receive an object of any of these three types\nas input in the `lake_target` argument.\n\nRemember that each of these three types (`AmazonS3`, `GoogleGCP` and `AzureBlob`)\nare separate structs that we have defined in our source code. So, at first glance,\nthey are separate data types in our source code. But is the `union` keyword that\nunifies them into a single data type called `LakeTarget`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst LakeTarget = union {\n azure: AzureBlob,\n amazon: AmazonS3,\n google: GoogleGCP,\n};\n\nfn send_event(\n event: Event,\n lake_target: LakeTarget\n) bool {\n // body of the function ...\n}\n```\n:::\n\n\n\n\nAn union definition is composed by a list of data members. Each data member is of a specific data type.\nIn the example above, the `LakeTarget` union have three data members (`azure`, `amazon`, `google`).\nWhen you instantiate an object that uses an union type, you can only use one of its data members\nin this instantiation.\n\nYou could also interpret this as: only one data member of an union type can be activated at a time, the other data\nmembers remain deactivated and unaccessible. For example, if you create a `LakeTarget` object that uses\nthe `azure` data member, you can no longer use or access the data members `google` or `amazon`.\nIt is like if these other data members didn't exist at all in the `LakeTarget` type.\n\nYou can see this logic in the example below. Notice that, we first instantiate the union\nobject using the `azure` data member. As a result, this `target` object contains only\nthe `azure` data member inside of it. Only this data member is active in this object.\nThat is why the last line in this code example is invalid. Because we are trying to instantiate the data member\n`google`, which is currently inactive for this `target` object, and as a result, the program\nenters in panic mode warning us about this mistake through a loud error message.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar target = LakeTarget {\n .azure = AzureBlob.init()\n};\n// Only the `azure` data member exist inside\n// the `target` object, and, as a result, this\n// line below is invalid:\ntarget.google = GoogleGCP.init();\n```\n:::\n\n\n\n\n```\nthread 2177312 panic: access of union field 'google' while\n field 'azure' is active:\n target.google = GoogleGCP.init();\n ^\n```\n\nSo, when you instantiate an union object, you must choose one of the data types (or, one of the data members)\nlisted in the union type. In the example above, I choose to use the `azure` data member, and, as a result,\nall other data members were automatically deactivated,\nand you can no longer use them after you instantiate the object.\n\nYou can activate another data member by completely redefining the entire enum object.\nIn the example below, I initially use the `azure` data member. But then, I redefine the\n`target` object to use a new `LakeTarget` object, which uses the `google` data member.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar target = LakeTarget {\n .azure = AzureBlob.init()\n};\ntarget = LakeTarget {\n .google = GoogleGCP.init()\n};\n```\n:::\n\n\n\n\nA curious fact about union types, is that, at first, you cannot use them in switch statements (which were presented at @sec-switch).\nIn other words, if you have an object of type `LakeTarget` for example, you cannot give this object\nas input to a switch statement.\n\nBut what if you really need to do so? What if you actually need to\nprovide an \"union object\" to a switch statement? The answer to this question relies on another special type in Zig,\nwhich are the *tagged unions*. To create a tagged union, all you have to do is to add\nan enum type into your union declaration.\n\nAs an example of a tagged union in Zig, take the `Registry` type exposed\nbelow. This type comes from the\n[`grammar.zig` module](https://github.com/ziglang/zig/blob/30b4a87db711c368853b3eff8e214ab681810ef9/tools/spirv/grammar.zig)[^grammar]\nfrom the Zig repository. This union type lists different types of registries.\nBut notice this time, the use of `(enum)` after the `union` keyword. This is what makes\nthis union type a tagged union. By being a tagged union, an object of this `Registry` type\ncan be used as input in a switch statement. This is all you have to do. Just add `(enum)`\nto your `union` declaration, and you can use it in switch statements.\n\n[^grammar]: .\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Registry = union(enum) {\n core: CoreRegistry,\n extension: ExtensionRegistry,\n};\n```\n:::\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/_freeze/Chapters/10-stack-project/execute-results/html.json b/_freeze/Chapters/10-stack-project/execute-results/html.json index 45ec4bce..2bc7f08f 100644 --- a/_freeze/Chapters/10-stack-project/execute-results/html.json +++ b/_freeze/Chapters/10-stack-project/execute-results/html.json @@ -2,10 +2,8 @@ "hash": "0c651ab91f56f6b099ea4bfebc8882dd", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 3 - Building a stack data structure\n\nIn this chapter we are going to implement a stack data structure as our next small project\nin this book. Implementing basic data structures in any language is kind of a\n\"kindergarten task\" (if this term even exist) in computer science (CS), because\nwe normally learn and implement them in the first semesters of CS.\n\nBut this is actually good! Since this should be a very easy task, we don't need much to explain\nwhat a stack is, then, we can concentrate on what is really important here, which is learning\nhow the concept of \"generics\" is implemented in the Zig language, and how one of the key\nfeatures of Zig, which is comptime, works, and use the stack data structure to demonstrate\nthese concepts on the fly.\n\nBut before we get into building the stack data structure, we first need to understand\nwhat the `comptime` keyword does to your code, and after that, we also need to learn about\nhow generics work in Zig.\n\n\n## Understanding `comptime` in Zig {#sec-comptime}\n\nOne of the key features of Zig is `comptime`. This keyword introduces a whole\nnew concept and paradigm, that is tightly connected with the compilation process.\nAt @sec-compile-time we have described the importance and the role that \"compile-time versus runtime\"\nplays into Zig. At that section, we learned that the rules applied to a value/object change\na lot depending on whether this value is known at compile-time, or just at runtime.\n\nThe `comptime` keyword is strongly related to these two spaces in time (compile-time and runtime).\nLet's quickly recap the differences. Compile-time is the period of time when your\nZig source code is being compiled by the `zig` compiler, while the runtime is\nthe period of time when your Zig program is being executed, i.e. when we execute\nthe binary files that were generated by the `zig` compiler.\n\nThere are three ways in which you can apply the `comptime` keyword, which are:\n\n- apply `comptime` on a function argument.\n- apply `comptime` on an object.\n- apply `comptime` on a block of expressions.\n\n\n\n### Applying over a function argument\n\nWhen you apply the `comptime` keyword on a function argument, you are saying to the `zig` compiler\nthat the value assigned to that particular function argument must be known at compile-time.\nWe explained in details at @sec-compile-time what exactly \"value known at compile-time\" means, so,\nin case you have doubts about this idea, come back to that section.\n\nNow let's think about the consequences of this idea. First of all, we are imposing a limit, or, a requirement\nto that particular function argument. If the programmer accidentally tries to give a value to this\nfunction argument that is not known at compile time, the `zig` compiler will notice this problem, and\nas a consequence, it will raise a compilation error saying that it cannot compile your program. Because\nyou are providing a value that is \"runtime known\" to a function argument that must be \"compile-time known\".\n\nTake a look at this very simple example below, where we define a `twice()` function, that simply\ndoubles the input value named `num`. Notice that we use the `comptime` keyword before the name\nof the function argument. This keyword is marking the function argument `num` as a \"comptime argument\".\n\nThat is a function argument whose value must be compile-time known. This is why the expression\n`twice(5678)` is valid, and no compilation errors are raised. Because the value `5678`\nis compile-time known, so this is the expected behaviour for this function.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\ntest \"test comptime\" {\n _ = twice(5678);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file1105a40478a9d.test.test comptime...OKAll 1\n 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\nBut what if we provide a number that is not compile-time known to this function?\nFor example, we might provide a different input value to this function depending\non the target OS of our compilation process. The code example below demonstrates such case.\n\nBecause the value of the object `n` is determined at runtime, we cannot provide this object\nas input to the `twice()` function. The `zig` compiler will not allow it, because we marked\nthe `num` argument as a \"comptime argument\". That is why the `zig` compiler raises\nthe compile-time error exposed below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\ntest \"test comptime\" {\n var n: u32 = undefined;\n if (builtin.target.os.tag == .windows) {\n n = 1234;\n } else {\n n = 5678;\n }\n _ = twice(n);\n}\n```\n:::\n\n\n\n\n```\nt.zig:12:16: error: runtime-known argument passed to comptime parameter \n```\n\nComptime arguments are frequently used on functions that return some sort\nof generic structure. In fact, `comptime` is the essence (or the basis) to make generics in Zig.\nWe are going to talk more about generics at @sec-generics.\n\nFor now, let's take a look at this code example from @karlseguin_generics. You\ncan see that this `IntArray()` function have one argument named `length`.\nThis argument is marked as comptime, and receives a value of type `usize` as input. So the value given to this argument\nmust be compile-time known.\nWe can also see that this function returns an array of `i64` values as output.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn IntArray(comptime length: usize) type {\n return [length]i64;\n}\n```\n:::\n\n\n\n\nNow, the key component of this function is the `length` argument. This argument\nis used to determine the size of the array that is produced by the function. Let's\nthink about the consequences of that. If the size of the array is dependent on\nthe value assigned to the `length` argument, this means that the data type of the\noutput of the function depends on the value of this `length` argument.\n\nLet this statement sink for a bit in your mind. As I described at @sec-root-file,\nZig is a strongly-typed language, especially on function declarations.\nSo every time we write a function in Zig, we have to annotate the data type of\nthe value returned by the function. But how can we do that, if this data type\ndepends on the value given to the argument of the function?\n\nThink about this for a second. If `length` is equal to 3 for example, then, the\nreturn type of the function is `[3]i64`. But if `length` is equal to 40, then,\nthe return type becomes `[40]i64`. At this point the `zig` compiler would be confused,\nand raise a compilation error, saying something like this:\n\n> Hey! You have annotated that this function should return a `[3]i64` value, but I got a `[40]i64` value instead! This doesn't look right!\n\nSo how can you solve this problem? How do we overcome this barrier? This is when\nthe `type` keyword comes in. This `type` keyword is basically saying to the\n`zig` compiler that this function will return some data type as output, but it doesn't know yet\nwhat exactly data type that is. We will talk more about this at @sec-generics.\n\n\n\n### Applying over an expression\n\nWhen you apply the `comptime` keyword over an expression, then, it is guaranteed that the `zig` compiler will\nexecute this expression at compile-time. If for some reason, this expression cannot be executed at compile-time\n(e.g. for example, maybe this expression depends on a value that is only known at runtime), then, the `zig` compiler\nwill raise a compilation error.\n\nTake this example from the official documentation of Zig [@zigdocs]. We\nare executing the same `fibonacci()` function both at runtime, and, at compile-time.\nThe function is by default executed at runtime, but because we use the `comptime`\nkeyword at the second \"try expression\", this expression is executed at compile-time.\n\nThis might be a bit confusing for some people. Yes! When I say that this expression\nis executed at compile-time, I mean that this expression is compiled and executed\nwhile the `zig` compiler is compiling your Zig source code.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci\" {\n // test fibonacci at run-time\n try expect(fibonacci(7) == 13);\n // test fibonacci at compile-time\n try comptime expect(fibonacci(7) == 13);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file1105a31c0f24f.test.fibonacci...OKAll 1 tes\n sts passed.\n```\n\n\n:::\n:::\n\n\n\n\nA lot of your Zig source code might be potentially executed at compile-time,\nbecause the `zig` compiler can figure it out the output of some expressions.\nEspecially if these expressions depends only at compile-time known values.\nWe have talked about this at @sec-compile-time.\n\nBut when you use the `comptime` keyword on an expression, there is no \"it might be executed\nat compile-time\" anymore. With the `comptime` keyword you are ordering the `zig` compiler\nto execute this expression at compile-time. You are imposing this rule, it is guaranteed\nthat the compiler will always execute it at compile-time. Or, at least, the compiler\nwill try to execute it. If the compiler cannot execute the expression for whatever reason,\nthe compiler will raise a compilation error.\n\n\n### Applying over a block\n\nBlocks were described at @sec-blocks. When you apply the `comptime` keyword over a\nblock of expressions, you get essentially the same effect when you apply this keyword to\na single expression. That is, the entire block of expressions is executed at\ncompile-time by the `zig` compiler.\n\nIn the example below, we mark the block labeled of `blk` as a comptime block,\nand, therefore, the expressions inside this block are executed at compile-time.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci in a block\" {\n const x = comptime blk: {\n const n1 = 5;\n const n2 = 2;\n const n3 = n1 + n2;\n try expect(fibonacci(n3) == 13);\n break :blk n3;\n };\n _ = x;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file1105a37ca2b0d.test.fibonacci in a block...\n .OKAll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## Introducing Generics {#sec-generics}\n\nFirst of all, what is a generic? Generic is the idea to allow a type\n(`f64`, `u8`, `u32`, `bool`, and also, user-defined types, like the `User` struct\nthat we defined at @sec-structs-and-oop) to be a parameter to methods, classes and\ninterfaces [@geeks_generics]. In other words, a \"generic\" is a class (or a method) that can work\nwith multiple data types.\n\nFor example, in Java, generics are created through the operator `<>`. With this operator,\na Java class is capable of receiving a data type as input, and therefore, the class can fit\nits features according to this input data type.\nAs another example, generics in C++ are supported through the concept of templates.\nClass templates in C++ are generics.\n\nIn Zig, generics are implemented through `comptime`. The `comptime` keyword\nallows us to collect a data type at compile time, and pass this data type as\ninput to a piece of code.\n\n\n### A generic function {#sec-generic-fun}\n\nTake the `max()` function exposed below as a first example.\nThis function is essentially a \"generic function\".\nIn this function, we have a comptime function argument named `T`.\nNotice that this `T` argument have a data type of `type`. Weird right? This `type` keyword is the\n\"father of all types\", or, \"the type of types\" in Zig.\n\nBecause we have used this `type` keyword in the `T` argument, we are telling\nthe `zig` compiler that this `T` argument will receive some data type as input.\nAlso notice the use of the `comptime` keyword in this argument.\nAs I described at @sec-comptime, every time you use this keyword in a function argument,\nthis means that the value of this argument must be known at compile-time.\nThis makes sense, right? Because there is no data type that is not known at compile-time.\n\nThink about this. Every data type that you will ever write is always\nknown at compile-time. Especially because data types are an essential\ninformation for the compiler to actually compile your source code.\nHaving this in mind, makes sense to mark this argument as a comptime argument.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn max(comptime T: type, a: T, b: T) T {\n return if (a > b) a else b;\n}\n```\n:::\n\n\n\n\nAlso notice that the value of the `T` argument is actually used\nto define the data type of the other arguments in the function, `a` and `b`, and also at the\nreturn type annotation of the function.\nThat is, the data type of these arguments (`a` and `b`), and, the return data type of the function itself,\nare determined by the input value given to the `T` argument.\n\nAs a result, we have a generic function that works with different data types.\nFor example, I can provide `u8` values to this `max()` function, and it will work as expected.\nBut if I provide `f64` values instead, it will also work as expected.\nWithout a generic function, I would have to write a different `max()` function\nfor each one of the data types that I wanted to use.\nThis generic function provides a very useful shortcut for us.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn max(comptime T: type, a: T, b: T) T {\n return if (a > b) a else b;\n}\ntest \"test max\" {\n const n1 = max(u8, 4, 10);\n std.debug.print(\"Max n1: {d}\\n\", .{n1});\n const n2 = max(f64, 89.24, 64.001);\n std.debug.print(\"Max n2: {d}\\n\", .{n2});\n}\n```\n:::\n\n\n\n\n```\nMax n1: 10\nMax n2: 89.24\n```\n\n\n### A generic data structure {#sec-generic-struct}\n\nEvery data structure that you find in the Zig Standard Library (e.g. `ArrayList`, `HashMap`, etc.)\nis essentially a generic data structure.\nThese data structures are generic in the sense that they work with any data type you want.\nYou just say which is the data type of the values that are going to be stored in this data\nstructure, and they just work as expected.\n\nA generic data structure in Zig is how you replicate a generic class from Java,\nor, a class template from C++. But you may quest yourself: how do we build a\ngeneric data structure in Zig?\n\nThe basic idea is to write a generic function that creates the data structure definition\nfor the specific type we want. In other words, this generic function behaves as a \"factory of data structures\".\nThe generic function outputs the `struct` definition that defines this data structure for a\nspecific data type.\n\nTo create such function, we need to add a comptime argument to this function that receives a data type\nas input. We already learned how to do this at the previous section (@sec-generic-fun).\nI think the best way to demonstrate how to create a generic data structure is to actually write one.\nThis where we go into our next small project in this book. This one is a very small project,\nwhich is to write a generic stack data structure.\n\n\n\n\n## What is a stack? {#sec-what-stack}\n\nA stack data structure is a structure that follows a LIFO (*last in, first out*) principle.\nOnly two operations are normally supported in a stack data structure, which are `push` and `pop`.\nThe `push` operation is used to add new values to the stack, while `pop` is used to remove\nvalues from the stack.\n\nWhen people try to explain how the stack data structure works, the most common analogy\nthat they use is a stack of plates. Imagine that you have a stack of plates,\nfor example, a stack of 10 plates in your table. Each plate represents a value that\nis currently stored in this stack.\n\nWe begin with a stack of 10 different values, or 10 different plates. Now, imagine that you want to\nadd a new plate (or a new value) to this stack, which translates to the `push` operation.\nYou would add this plate (or this value) by just putting the new plate\non the top of the stack. Then, you would increase the stack to 11 plates.\n\nBut how would you remove plates (or remove values) from this stack (a.k.a. the `pop` operation) ?\nTo do that, we would have to remove the plate on the top of the stack, and, as a result, we would\nhave, once again, 10 plates in the stack.\n\nThis demonstrates the LIFO concept, because the first plate in the stack, which is the plate\nin the bottom of the stack, is always the last plate to get out of the stack. Think about it. In order\nto remove this specific plate from the stack, we have to remove all plates in the\nstack. So every operation in the stack, either insertion or deletion, is always made at the top of the stack.\nThe @fig-stack below exposes this logic visually:\n\n![A diagram of a stack structure. Source: Wikipedia, the free encyclopedia.](./../Figures/lifo-stack.svg){#fig-stack}\n\n\n\n## Writing the stack data structure\n\nWe are going to write the stack data structure in two steps. First, we are going\nto implement a stack that can only store `u32` values. Then, after that, we are going\nto extend our implementation to make it generic, so that it works with any data type\nwe want.\n\nFirst, we need to decide how the values will be stored inside the stack. There are multiple\nways to implement the storage behind a stack structure. Some people prefer to use a doubly linked list,\nsome others prefer to use a dynamic array, etc. In this example we are going to use an array behind the hood,\nto store the values in the stack, which is the `items` data member of our `Stack` struct definition.\n\nAlso notice in our `Stack` struct that we have three other data members: `capacity`, `length` and `allocator`.\nThe `capacity` member contains the capacity of the underlying array that stores the values in the stack.\nThe `length` contains the number of values that are currently being stored in the stack.\nAnd the `allocator` contains the allocator object that will be used by the stack structure whenever it\nneeds to allocate more space for the values that are being stored.\n\nWe begin by defining an `init()` method of this struct, which is going to be\nresponsible for instantiating a `Stack` object. Notice that, inside this\n`init()` method, we start by allocating an array with the capacity specified\nin the `capacity` argument.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst Stack = struct {\n items: []u32,\n capacity: usize,\n length: usize,\n allocator: Allocator,\n\n pub fn init(allocator: Allocator, capacity: usize) !Stack {\n var buf = try allocator.alloc(u32, capacity);\n return .{\n .items = buf[0..],\n .capacity = capacity,\n .length = 0,\n .allocator = allocator,\n };\n }\n};\n```\n:::\n\n\n\n\n\n### Implementing the `push` operation\n\nNow that we have written the basic logic to create a new `Stack` object,\nwe can start writing the logic responsible for performing a push operation.\nRemember, a push operation in a stack data structure is the operation\nresponsible for adding a new value to the stack.\n\nSo how can we add a new value to the `Stack` object that we have?\nThe `push()` function exposed below is a possible answer to this question.\nRemember from what we discussed at @sec-what-stack that values are always added to the top of the stack.\nThis means that this `push()` function must always find the element in the underlying array\nthat currently represents the top position of the stack, and then, add the input value there.\n\nFirst, we have an if statement in this function. This if statement is\nchecking whether we need to expand the underlying array to store\nthis new value that we are adding to the stack. In other words, maybe\nthe underlying array does not have enough capacity to store this new\nvalue, and, in this case, we need to expand our array to get the capacity that we need.\n\nSo, if the logical test in this if statement returns true, it means that the array\ndoes not have enough capacity, and we need to expand it before we store this new value.\nSo inside this if statement we are executing the necessary expressions to expand the underlying array.\nNotice that we use the allocator object to allocate a new array that is twice as bigger\nthan the current array (`self.capacity * 2`).\n\nAfter that, we use a different built-in function named `@memcpy()`. This built-in function\nis equivalent to the `memcpy()` function from the C Standard Library[^cmemcpy]. It is used to\ncopy the values from one block of memory to another block of memory. In other words,\nyou can use this function to copy the values from one array into another array.\n\n[^cmemcpy]: \n\nWe are using this `@memcpy()` built-in function to copy the values that are currently stored\nin the underlying array of the stack object (`self.items`) into our new and bigger array that\nwe have allocated (`new_buf`). After we execute this function, the `new_buf` contains a copy\nof the values that are present at `self.items`.\n\nNow that we have secured a copy of our current values in the `new_buf` object, we\ncan now free the memory currently allocated at `self.items`. After that, we just need\nto assign our new and bigger array to `self.items`. This is the sequence\nof steps necessary to expand our array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn push(self: *Stack, val: u32) !void {\n if ((self.length + 1) > self.capacity) {\n var new_buf = try self.allocator.alloc(\n u32, self.capacity * 2\n );\n @memcpy(\n new_buf[0..self.capacity], self.items\n );\n self.allocator.free(self.items);\n self.items = new_buf;\n self.capacity = self.capacity * 2;\n }\n\n self.items[self.length] = val;\n self.length += 1;\n}\n```\n:::\n\n\n\n\nAfter we make sure that we have enough room to store this new value\nthat we are adding to the stack, all we have to do is to assign\nthis value to the top element in this stack, and, increase the\nvalue of the `length` attribute by one. We find the top element\nin the stack by using the `length` attribute.\n\n\n\n### Implementing the `pop` operation\n\nNow we can implement the pop operation of our stack object.\nThis is a much easier operation to implement, and the `pop()` method below summarises\nall the logic that is needed.\n\nWe just have to find the element in the underlying array that currently represents the top\nof the stack, and set this element to \"undefined\", to indicate that\nthis element is \"empty\". After that, we also need to decrease\nthe `length` attribute of the stack by one.\n\nIf the current length of the stack is zero, it means that there is\nno values being stored in the stack currently. So, in this case,\nwe could just return from the function and do nothing really.\nThis is what the if statement inside this function is checking for.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn pop(self: *Stack) void {\n if (self.length == 0) return;\n\n self.items[self.length - 1] = undefined;\n self.length -= 1;\n}\n```\n:::\n\n\n\n\n\n\n### Implementing the `deinit` method\n\nWe have implemented the methods responsible for the two main operations\nassociated with the stack data structure, which is `pop()` and `push()`,\nand we also have implemented the method responsible for instantiating\na new `Stack` object, which is the `init()` method.\n\nBut now, we need to implement also the method responsible for destroying\na `Stack` object. In Zig, this task is commonly associated with the method\nnamed `deinit()`. Most struct objects in Zig have such method, and it\nis commonly nicknamed \"the destructor method\".\n\nIn theory, all we have to do to destroy the `Stack` object is to make\nsure that we free the allocated memory for the underlying array, using\nthe allocator object that is stored inside the `Stack` object.\nThis is what the `deinit()` method below is doing.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn deinit(self: *Stack) void {\n self.allocator.free(self.items);\n}\n```\n:::\n\n\n\n\n\n\n\n## Making it generic\n\nNow that we have implemented the basic skeleton of our stack data structure,\nwe can now focus on discussing how can we make it generic. How can we make\nthis basic skeleton to work not only with `u32` values, but also, with any other\ndata type we want?\nFor example, we might need to create a stack object to store `User` values\nin it. How can we make this possible? The answer lies on the use of generics\nand `comptime`.\n\nAs I described at @sec-generic-struct, the basic idea is to write a generic\nfunction that returns a struct definition as output.\nIn theory, we do not need much to transform our `Stack` struct into a generic\ndata structure. All that we need to do is to transform the underlying array\nof the stack into a generic array.\n\nIn other words, this underlying array needs to be a \"chameleon\". It needs to adapt,\nand transform it into an array of any data type that we want. For example, if we need to create\na stack that will store `u8` values, then, this underlying array needs to be\na `u8` array (i.e. `[]u8`). But if we need to store `User` values instead, then,\nthis array needs to be a `User` array (i.e. `[]User`). Etc.\n\nWe do that by using a generic function. Because a generic function can receive a data type\nas input, and we can pass this data type to the struct definition of our `Stack` object.\nTherefore, we can use the generic function to create a `Stack` object that can store\nthe data type we want. If we want to create a stack structure that stores `User` values,\nwe pass the `User` data type to this generic function, and it will create for us\nthe struct definition that describes a `Stack` object that can store `User` values in it.\n\nLook at the code example below. I have omitted some parts of the `Stack` struct definition\nfor brevity reasons. However, if a specific part of our `Stack` struct is not exposed here\nin this example, then it is because this part did not change from the previous example.\nIt remains the same.\n\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn Stack(comptime T: type) type {\n return struct {\n items: []T,\n capacity: usize,\n length: usize,\n allocator: Allocator,\n const Self = @This();\n\n pub fn init(allocator: Allocator,\n capacity: usize) !Stack(T) {\n var buf = try allocator.alloc(T, capacity);\n return .{\n .items = buf[0..],\n .capacity = capacity,\n .length = 0,\n .allocator = allocator,\n };\n }\n\n pub fn push(self: *Self, val: T) !void {\n // Truncate the rest of the struct\n };\n}\n```\n:::\n\n\n\n\nNotice that we have created a function in this example named `Stack()`. This function\ntakes a type as input, and passes this type to the struct definition of our\n`Stack` object. The data member `items` is now, an array of type `T`, which is the\ndata type that we have provided as input to the function. The function argument\n`val` in the `push()` function is now a value of type `T` too.\n\nWe can just provide a data type to this function, and it will create a definition of a\n`Stack` object that can store values of the data type that we have provided. In the example below, we are creating\nthe definition of a\n`Stack` object that can store `u8` values in it. This definition is stored at the `Stacku8` object.\nThis `Stacku8` object becomes our new struct, it is the struct that we are going to use\nto create our `Stack` object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nconst Stacku8 = Stack(u8);\nvar stack = try Stacku8.init(allocator, 10);\ndefer stack.deinit();\ntry stack.push(1);\ntry stack.push(2);\ntry stack.push(3);\ntry stack.push(4);\ntry stack.push(5);\ntry stack.push(6);\n\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstd.debug.print(\"Stack capacity: {d}\\n\", .{stack.capacity});\n\nstack.pop();\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstack.pop();\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstd.debug.print(\n \"Stack state: {any}\\n\",\n .{stack.items[0..stack.length]}\n);\n```\n:::\n\n\n\n\n```\nStack len: 6\nStack capacity: 10\nStack len: 5\nStack len: 4\nStack state: { 1, 2, 3, 4, 0, 0, 0, 0, 0, 0 }\n```\n\nEvery generic data structure in the Zig Standard Library (`ArrayList`, `HashMap`, `SinlyLinkedList`, etc.)\nis implemented through this logic. They use a generic function to create the struct definition that can work\nwith the data type that you provided as input.\n\n\n\n\n## Conclusion\n\nThe full source code of the stack structure discussed in this chapter is freely available at the official\nrepository of this book. Just checkout the [`stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/stack.zig)[^zig-stack]\nfor the `u32` version of our stack,\nand the [`generic_stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/generic_stack.zig)[^zig-stack2]\nfor the generic version, available inside the `ZigExamples` folder of the repository.\n\n\n[^zig-stack]: \n[^zig-stack2]: \n\n", - "supporting": [ - "10-stack-project_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 3 - Building a stack data structure\n\nIn this chapter we are going to implement a stack data structure as our next small project\nin this book. Implementing basic data structures in any language is kind of a\n\"kindergarten task\" (if this term even exist) in computer science (CS), because\nwe normally learn and implement them in the first semesters of CS.\n\nBut this is actually good! Since this should be a very easy task, we don't need much to explain\nwhat a stack is, then, we can concentrate on what is really important here, which is learning\nhow the concept of \"generics\" is implemented in the Zig language, and how one of the key\nfeatures of Zig, which is comptime, works, and use the stack data structure to demonstrate\nthese concepts on the fly.\n\nBut before we get into building the stack data structure, we first need to understand\nwhat the `comptime` keyword does to your code, and after that, we also need to learn about\nhow generics work in Zig.\n\n\n## Understanding `comptime` in Zig {#sec-comptime}\n\nOne of the key features of Zig is `comptime`. This keyword introduces a whole\nnew concept and paradigm, that is tightly connected with the compilation process.\nAt @sec-compile-time we have described the importance and the role that \"compile-time versus runtime\"\nplays into Zig. At that section, we learned that the rules applied to a value/object change\na lot depending on whether this value is known at compile-time, or just at runtime.\n\nThe `comptime` keyword is strongly related to these two spaces in time (compile-time and runtime).\nLet's quickly recap the differences. Compile-time is the period of time when your\nZig source code is being compiled by the `zig` compiler, while the runtime is\nthe period of time when your Zig program is being executed, i.e. when we execute\nthe binary files that were generated by the `zig` compiler.\n\nThere are three ways in which you can apply the `comptime` keyword, which are:\n\n- apply `comptime` on a function argument.\n- apply `comptime` on an object.\n- apply `comptime` on a block of expressions.\n\n\n\n### Applying over a function argument\n\nWhen you apply the `comptime` keyword on a function argument, you are saying to the `zig` compiler\nthat the value assigned to that particular function argument must be known at compile-time.\nWe explained in details at @sec-compile-time what exactly \"value known at compile-time\" means, so,\nin case you have doubts about this idea, come back to that section.\n\nNow let's think about the consequences of this idea. First of all, we are imposing a limit, or, a requirement\nto that particular function argument. If the programmer accidentally tries to give a value to this\nfunction argument that is not known at compile time, the `zig` compiler will notice this problem, and\nas a consequence, it will raise a compilation error saying that it cannot compile your program. Because\nyou are providing a value that is \"runtime known\" to a function argument that must be \"compile-time known\".\n\nTake a look at this very simple example below, where we define a `twice()` function, that simply\ndoubles the input value named `num`. Notice that we use the `comptime` keyword before the name\nof the function argument. This keyword is marking the function argument `num` as a \"comptime argument\".\n\nThat is a function argument whose value must be compile-time known. This is why the expression\n`twice(5678)` is valid, and no compilation errors are raised. Because the value `5678`\nis compile-time known, so this is the expected behaviour for this function.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\ntest \"test comptime\" {\n _ = twice(5678);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filea72d248f97f8.test.test comptime...OKAll 1 \n tests passed.\n```\n\n\n:::\n:::\n\n\n\n\nBut what if we provide a number that is not compile-time known to this function?\nFor example, we might provide a different input value to this function depending\non the target OS of our compilation process. The code example below demonstrates such case.\n\nBecause the value of the object `n` is determined at runtime, we cannot provide this object\nas input to the `twice()` function. The `zig` compiler will not allow it, because we marked\nthe `num` argument as a \"comptime argument\". That is why the `zig` compiler raises\nthe compile-time error exposed below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\ntest \"test comptime\" {\n var n: u32 = undefined;\n if (builtin.target.os.tag == .windows) {\n n = 1234;\n } else {\n n = 5678;\n }\n _ = twice(n);\n}\n```\n:::\n\n\n\n\n```\nt.zig:12:16: error: runtime-known argument passed to comptime parameter \n```\n\nComptime arguments are frequently used on functions that return some sort\nof generic structure. In fact, `comptime` is the essence (or the basis) to make generics in Zig.\nWe are going to talk more about generics at @sec-generics.\n\nFor now, let's take a look at this code example from @karlseguin_generics. You\ncan see that this `IntArray()` function have one argument named `length`.\nThis argument is marked as comptime, and receives a value of type `usize` as input. So the value given to this argument\nmust be compile-time known.\nWe can also see that this function returns an array of `i64` values as output.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn IntArray(comptime length: usize) type {\n return [length]i64;\n}\n```\n:::\n\n\n\n\nNow, the key component of this function is the `length` argument. This argument\nis used to determine the size of the array that is produced by the function. Let's\nthink about the consequences of that. If the size of the array is dependent on\nthe value assigned to the `length` argument, this means that the data type of the\noutput of the function depends on the value of this `length` argument.\n\nLet this statement sink for a bit in your mind. As I described at @sec-root-file,\nZig is a strongly-typed language, especially on function declarations.\nSo every time we write a function in Zig, we have to annotate the data type of\nthe value returned by the function. But how can we do that, if this data type\ndepends on the value given to the argument of the function?\n\nThink about this for a second. If `length` is equal to 3 for example, then, the\nreturn type of the function is `[3]i64`. But if `length` is equal to 40, then,\nthe return type becomes `[40]i64`. At this point the `zig` compiler would be confused,\nand raise a compilation error, saying something like this:\n\n> Hey! You have annotated that this function should return a `[3]i64` value, but I got a `[40]i64` value instead! This doesn't look right!\n\nSo how can you solve this problem? How do we overcome this barrier? This is when\nthe `type` keyword comes in. This `type` keyword is basically saying to the\n`zig` compiler that this function will return some data type as output, but it doesn't know yet\nwhat exactly data type that is. We will talk more about this at @sec-generics.\n\n\n\n### Applying over an expression\n\nWhen you apply the `comptime` keyword over an expression, then, it is guaranteed that the `zig` compiler will\nexecute this expression at compile-time. If for some reason, this expression cannot be executed at compile-time\n(e.g. for example, maybe this expression depends on a value that is only known at runtime), then, the `zig` compiler\nwill raise a compilation error.\n\nTake this example from the official documentation of Zig [@zigdocs]. We\nare executing the same `fibonacci()` function both at runtime, and, at compile-time.\nThe function is by default executed at runtime, but because we use the `comptime`\nkeyword at the second \"try expression\", this expression is executed at compile-time.\n\nThis might be a bit confusing for some people. Yes! When I say that this expression\nis executed at compile-time, I mean that this expression is compiled and executed\nwhile the `zig` compiler is compiling your Zig source code.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci\" {\n // test fibonacci at run-time\n try expect(fibonacci(7) == 13);\n // test fibonacci at compile-time\n try comptime expect(fibonacci(7) == 13);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filea72d3cf7abe2.test.fibonacci...OKAll 1 test\n ts passed.\n```\n\n\n:::\n:::\n\n\n\n\nA lot of your Zig source code might be potentially executed at compile-time,\nbecause the `zig` compiler can figure it out the output of some expressions.\nEspecially if these expressions depends only at compile-time known values.\nWe have talked about this at @sec-compile-time.\n\nBut when you use the `comptime` keyword on an expression, there is no \"it might be executed\nat compile-time\" anymore. With the `comptime` keyword you are ordering the `zig` compiler\nto execute this expression at compile-time. You are imposing this rule, it is guaranteed\nthat the compiler will always execute it at compile-time. Or, at least, the compiler\nwill try to execute it. If the compiler cannot execute the expression for whatever reason,\nthe compiler will raise a compilation error.\n\n\n### Applying over a block\n\nBlocks were described at @sec-blocks. When you apply the `comptime` keyword over a\nblock of expressions, you get essentially the same effect when you apply this keyword to\na single expression. That is, the entire block of expressions is executed at\ncompile-time by the `zig` compiler.\n\nIn the example below, we mark the block labeled of `blk` as a comptime block,\nand, therefore, the expressions inside this block are executed at compile-time.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci in a block\" {\n const x = comptime blk: {\n const n1 = 5;\n const n2 = 2;\n const n3 = n1 + n2;\n try expect(fibonacci(n3) == 13);\n break :blk n3;\n };\n _ = x;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filea72d6353d586.test.fibonacci in a block...O\n OKAll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## Introducing Generics {#sec-generics}\n\nFirst of all, what is a generic? Generic is the idea to allow a type\n(`f64`, `u8`, `u32`, `bool`, and also, user-defined types, like the `User` struct\nthat we defined at @sec-structs-and-oop) to be a parameter to methods, classes and\ninterfaces [@geeks_generics]. In other words, a \"generic\" is a class (or a method) that can work\nwith multiple data types.\n\nFor example, in Java, generics are created through the operator `<>`. With this operator,\na Java class is capable of receiving a data type as input, and therefore, the class can fit\nits features according to this input data type.\nAs another example, generics in C++ are supported through the concept of templates.\nClass templates in C++ are generics.\n\nIn Zig, generics are implemented through `comptime`. The `comptime` keyword\nallows us to collect a data type at compile time, and pass this data type as\ninput to a piece of code.\n\n\n### A generic function {#sec-generic-fun}\n\nTake the `max()` function exposed below as a first example.\nThis function is essentially a \"generic function\".\nIn this function, we have a comptime function argument named `T`.\nNotice that this `T` argument have a data type of `type`. Weird right? This `type` keyword is the\n\"father of all types\", or, \"the type of types\" in Zig.\n\nBecause we have used this `type` keyword in the `T` argument, we are telling\nthe `zig` compiler that this `T` argument will receive some data type as input.\nAlso notice the use of the `comptime` keyword in this argument.\nAs I described at @sec-comptime, every time you use this keyword in a function argument,\nthis means that the value of this argument must be known at compile-time.\nThis makes sense, right? Because there is no data type that is not known at compile-time.\n\nThink about this. Every data type that you will ever write is always\nknown at compile-time. Especially because data types are an essential\ninformation for the compiler to actually compile your source code.\nHaving this in mind, makes sense to mark this argument as a comptime argument.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn max(comptime T: type, a: T, b: T) T {\n return if (a > b) a else b;\n}\n```\n:::\n\n\n\n\nAlso notice that the value of the `T` argument is actually used\nto define the data type of the other arguments in the function, `a` and `b`, and also at the\nreturn type annotation of the function.\nThat is, the data type of these arguments (`a` and `b`), and, the return data type of the function itself,\nare determined by the input value given to the `T` argument.\n\nAs a result, we have a generic function that works with different data types.\nFor example, I can provide `u8` values to this `max()` function, and it will work as expected.\nBut if I provide `f64` values instead, it will also work as expected.\nWithout a generic function, I would have to write a different `max()` function\nfor each one of the data types that I wanted to use.\nThis generic function provides a very useful shortcut for us.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn max(comptime T: type, a: T, b: T) T {\n return if (a > b) a else b;\n}\ntest \"test max\" {\n const n1 = max(u8, 4, 10);\n std.debug.print(\"Max n1: {d}\\n\", .{n1});\n const n2 = max(f64, 89.24, 64.001);\n std.debug.print(\"Max n2: {d}\\n\", .{n2});\n}\n```\n:::\n\n\n\n\n```\nMax n1: 10\nMax n2: 89.24\n```\n\n\n### A generic data structure {#sec-generic-struct}\n\nEvery data structure that you find in the Zig Standard Library (e.g. `ArrayList`, `HashMap`, etc.)\nis essentially a generic data structure.\nThese data structures are generic in the sense that they work with any data type you want.\nYou just say which is the data type of the values that are going to be stored in this data\nstructure, and they just work as expected.\n\nA generic data structure in Zig is how you replicate a generic class from Java,\nor, a class template from C++. But you may quest yourself: how do we build a\ngeneric data structure in Zig?\n\nThe basic idea is to write a generic function that creates the data structure definition\nfor the specific type we want. In other words, this generic function behaves as a \"factory of data structures\".\nThe generic function outputs the `struct` definition that defines this data structure for a\nspecific data type.\n\nTo create such function, we need to add a comptime argument to this function that receives a data type\nas input. We already learned how to do this at the previous section (@sec-generic-fun).\nI think the best way to demonstrate how to create a generic data structure is to actually write one.\nThis where we go into our next small project in this book. This one is a very small project,\nwhich is to write a generic stack data structure.\n\n\n\n\n## What is a stack? {#sec-what-stack}\n\nA stack data structure is a structure that follows a LIFO (*last in, first out*) principle.\nOnly two operations are normally supported in a stack data structure, which are `push` and `pop`.\nThe `push` operation is used to add new values to the stack, while `pop` is used to remove\nvalues from the stack.\n\nWhen people try to explain how the stack data structure works, the most common analogy\nthat they use is a stack of plates. Imagine that you have a stack of plates,\nfor example, a stack of 10 plates in your table. Each plate represents a value that\nis currently stored in this stack.\n\nWe begin with a stack of 10 different values, or 10 different plates. Now, imagine that you want to\nadd a new plate (or a new value) to this stack, which translates to the `push` operation.\nYou would add this plate (or this value) by just putting the new plate\non the top of the stack. Then, you would increase the stack to 11 plates.\n\nBut how would you remove plates (or remove values) from this stack (a.k.a. the `pop` operation) ?\nTo do that, we would have to remove the plate on the top of the stack, and, as a result, we would\nhave, once again, 10 plates in the stack.\n\nThis demonstrates the LIFO concept, because the first plate in the stack, which is the plate\nin the bottom of the stack, is always the last plate to get out of the stack. Think about it. In order\nto remove this specific plate from the stack, we have to remove all plates in the\nstack. So every operation in the stack, either insertion or deletion, is always made at the top of the stack.\nThe @fig-stack below exposes this logic visually:\n\n![A diagram of a stack structure. Source: Wikipedia, the free encyclopedia.](./../Figures/lifo-stack.svg){#fig-stack}\n\n\n\n## Writing the stack data structure\n\nWe are going to write the stack data structure in two steps. First, we are going\nto implement a stack that can only store `u32` values. Then, after that, we are going\nto extend our implementation to make it generic, so that it works with any data type\nwe want.\n\nFirst, we need to decide how the values will be stored inside the stack. There are multiple\nways to implement the storage behind a stack structure. Some people prefer to use a doubly linked list,\nsome others prefer to use a dynamic array, etc. In this example we are going to use an array behind the hood,\nto store the values in the stack, which is the `items` data member of our `Stack` struct definition.\n\nAlso notice in our `Stack` struct that we have three other data members: `capacity`, `length` and `allocator`.\nThe `capacity` member contains the capacity of the underlying array that stores the values in the stack.\nThe `length` contains the number of values that are currently being stored in the stack.\nAnd the `allocator` contains the allocator object that will be used by the stack structure whenever it\nneeds to allocate more space for the values that are being stored.\n\nWe begin by defining an `init()` method of this struct, which is going to be\nresponsible for instantiating a `Stack` object. Notice that, inside this\n`init()` method, we start by allocating an array with the capacity specified\nin the `capacity` argument.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst Stack = struct {\n items: []u32,\n capacity: usize,\n length: usize,\n allocator: Allocator,\n\n pub fn init(allocator: Allocator, capacity: usize) !Stack {\n var buf = try allocator.alloc(u32, capacity);\n return .{\n .items = buf[0..],\n .capacity = capacity,\n .length = 0,\n .allocator = allocator,\n };\n }\n};\n```\n:::\n\n\n\n\n\n### Implementing the `push` operation\n\nNow that we have written the basic logic to create a new `Stack` object,\nwe can start writing the logic responsible for performing a push operation.\nRemember, a push operation in a stack data structure is the operation\nresponsible for adding a new value to the stack.\n\nSo how can we add a new value to the `Stack` object that we have?\nThe `push()` function exposed below is a possible answer to this question.\nRemember from what we discussed at @sec-what-stack that values are always added to the top of the stack.\nThis means that this `push()` function must always find the element in the underlying array\nthat currently represents the top position of the stack, and then, add the input value there.\n\nFirst, we have an if statement in this function. This if statement is\nchecking whether we need to expand the underlying array to store\nthis new value that we are adding to the stack. In other words, maybe\nthe underlying array does not have enough capacity to store this new\nvalue, and, in this case, we need to expand our array to get the capacity that we need.\n\nSo, if the logical test in this if statement returns true, it means that the array\ndoes not have enough capacity, and we need to expand it before we store this new value.\nSo inside this if statement we are executing the necessary expressions to expand the underlying array.\nNotice that we use the allocator object to allocate a new array that is twice as bigger\nthan the current array (`self.capacity * 2`).\n\nAfter that, we use a different built-in function named `@memcpy()`. This built-in function\nis equivalent to the `memcpy()` function from the C Standard Library[^cmemcpy]. It is used to\ncopy the values from one block of memory to another block of memory. In other words,\nyou can use this function to copy the values from one array into another array.\n\n[^cmemcpy]: \n\nWe are using this `@memcpy()` built-in function to copy the values that are currently stored\nin the underlying array of the stack object (`self.items`) into our new and bigger array that\nwe have allocated (`new_buf`). After we execute this function, the `new_buf` contains a copy\nof the values that are present at `self.items`.\n\nNow that we have secured a copy of our current values in the `new_buf` object, we\ncan now free the memory currently allocated at `self.items`. After that, we just need\nto assign our new and bigger array to `self.items`. This is the sequence\nof steps necessary to expand our array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn push(self: *Stack, val: u32) !void {\n if ((self.length + 1) > self.capacity) {\n var new_buf = try self.allocator.alloc(\n u32, self.capacity * 2\n );\n @memcpy(\n new_buf[0..self.capacity], self.items\n );\n self.allocator.free(self.items);\n self.items = new_buf;\n self.capacity = self.capacity * 2;\n }\n\n self.items[self.length] = val;\n self.length += 1;\n}\n```\n:::\n\n\n\n\nAfter we make sure that we have enough room to store this new value\nthat we are adding to the stack, all we have to do is to assign\nthis value to the top element in this stack, and, increase the\nvalue of the `length` attribute by one. We find the top element\nin the stack by using the `length` attribute.\n\n\n\n### Implementing the `pop` operation\n\nNow we can implement the pop operation of our stack object.\nThis is a much easier operation to implement, and the `pop()` method below summarises\nall the logic that is needed.\n\nWe just have to find the element in the underlying array that currently represents the top\nof the stack, and set this element to \"undefined\", to indicate that\nthis element is \"empty\". After that, we also need to decrease\nthe `length` attribute of the stack by one.\n\nIf the current length of the stack is zero, it means that there is\nno values being stored in the stack currently. So, in this case,\nwe could just return from the function and do nothing really.\nThis is what the if statement inside this function is checking for.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn pop(self: *Stack) void {\n if (self.length == 0) return;\n\n self.items[self.length - 1] = undefined;\n self.length -= 1;\n}\n```\n:::\n\n\n\n\n\n\n### Implementing the `deinit` method\n\nWe have implemented the methods responsible for the two main operations\nassociated with the stack data structure, which is `pop()` and `push()`,\nand we also have implemented the method responsible for instantiating\na new `Stack` object, which is the `init()` method.\n\nBut now, we need to implement also the method responsible for destroying\na `Stack` object. In Zig, this task is commonly associated with the method\nnamed `deinit()`. Most struct objects in Zig have such method, and it\nis commonly nicknamed \"the destructor method\".\n\nIn theory, all we have to do to destroy the `Stack` object is to make\nsure that we free the allocated memory for the underlying array, using\nthe allocator object that is stored inside the `Stack` object.\nThis is what the `deinit()` method below is doing.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn deinit(self: *Stack) void {\n self.allocator.free(self.items);\n}\n```\n:::\n\n\n\n\n\n\n\n## Making it generic\n\nNow that we have implemented the basic skeleton of our stack data structure,\nwe can now focus on discussing how can we make it generic. How can we make\nthis basic skeleton to work not only with `u32` values, but also, with any other\ndata type we want?\nFor example, we might need to create a stack object to store `User` values\nin it. How can we make this possible? The answer lies on the use of generics\nand `comptime`.\n\nAs I described at @sec-generic-struct, the basic idea is to write a generic\nfunction that returns a struct definition as output.\nIn theory, we do not need much to transform our `Stack` struct into a generic\ndata structure. All that we need to do is to transform the underlying array\nof the stack into a generic array.\n\nIn other words, this underlying array needs to be a \"chameleon\". It needs to adapt,\nand transform it into an array of any data type that we want. For example, if we need to create\na stack that will store `u8` values, then, this underlying array needs to be\na `u8` array (i.e. `[]u8`). But if we need to store `User` values instead, then,\nthis array needs to be a `User` array (i.e. `[]User`). Etc.\n\nWe do that by using a generic function. Because a generic function can receive a data type\nas input, and we can pass this data type to the struct definition of our `Stack` object.\nTherefore, we can use the generic function to create a `Stack` object that can store\nthe data type we want. If we want to create a stack structure that stores `User` values,\nwe pass the `User` data type to this generic function, and it will create for us\nthe struct definition that describes a `Stack` object that can store `User` values in it.\n\nLook at the code example below. I have omitted some parts of the `Stack` struct definition\nfor brevity reasons. However, if a specific part of our `Stack` struct is not exposed here\nin this example, then it is because this part did not change from the previous example.\nIt remains the same.\n\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn Stack(comptime T: type) type {\n return struct {\n items: []T,\n capacity: usize,\n length: usize,\n allocator: Allocator,\n const Self = @This();\n\n pub fn init(allocator: Allocator,\n capacity: usize) !Stack(T) {\n var buf = try allocator.alloc(T, capacity);\n return .{\n .items = buf[0..],\n .capacity = capacity,\n .length = 0,\n .allocator = allocator,\n };\n }\n\n pub fn push(self: *Self, val: T) !void {\n // Truncate the rest of the struct\n };\n}\n```\n:::\n\n\n\n\nNotice that we have created a function in this example named `Stack()`. This function\ntakes a type as input, and passes this type to the struct definition of our\n`Stack` object. The data member `items` is now, an array of type `T`, which is the\ndata type that we have provided as input to the function. The function argument\n`val` in the `push()` function is now a value of type `T` too.\n\nWe can just provide a data type to this function, and it will create a definition of a\n`Stack` object that can store values of the data type that we have provided. In the example below, we are creating\nthe definition of a\n`Stack` object that can store `u8` values in it. This definition is stored at the `Stacku8` object.\nThis `Stacku8` object becomes our new struct, it is the struct that we are going to use\nto create our `Stack` object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nconst Stacku8 = Stack(u8);\nvar stack = try Stacku8.init(allocator, 10);\ndefer stack.deinit();\ntry stack.push(1);\ntry stack.push(2);\ntry stack.push(3);\ntry stack.push(4);\ntry stack.push(5);\ntry stack.push(6);\n\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstd.debug.print(\"Stack capacity: {d}\\n\", .{stack.capacity});\n\nstack.pop();\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstack.pop();\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstd.debug.print(\n \"Stack state: {any}\\n\",\n .{stack.items[0..stack.length]}\n);\n```\n:::\n\n\n\n\n```\nStack len: 6\nStack capacity: 10\nStack len: 5\nStack len: 4\nStack state: { 1, 2, 3, 4, 0, 0, 0, 0, 0, 0 }\n```\n\nEvery generic data structure in the Zig Standard Library (`ArrayList`, `HashMap`, `SinlyLinkedList`, etc.)\nis implemented through this logic. They use a generic function to create the struct definition that can work\nwith the data type that you provided as input.\n\n\n\n\n## Conclusion\n\nThe full source code of the stack structure discussed in this chapter is freely available at the official\nrepository of this book. Just checkout the [`stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/stack.zig)[^zig-stack]\nfor the `u32` version of our stack,\nand the [`generic_stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/generic_stack.zig)[^zig-stack2]\nfor the generic version, available inside the `ZigExamples` folder of the repository.\n\n\n[^zig-stack]: \n[^zig-stack2]: \n\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/12-file-op/execute-results/html.json b/_freeze/Chapters/12-file-op/execute-results/html.json index d1200279..4bb8d71f 100644 --- a/_freeze/Chapters/12-file-op/execute-results/html.json +++ b/_freeze/Chapters/12-file-op/execute-results/html.json @@ -3,9 +3,7 @@ "result": { "engine": "knitr", "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n\n# Filesystem and Input/Output (IO) {#sec-filesystem}\n\nIn this chapter we are going to discuss how to use the cross-platform structs and functions\nfrom the Zig Standard Library that can execute filesystem operations. Most of these functions and structs\ncomes from the `std.fs` module.\n\nWe are also going to talk about Input/Output (also known as IO) operations in Zig. Most of\nthese operations are made by using the structs and functions from `std.io` module, which defines\nfile descriptors for the *standard channels* of your system (`stdout` and `stdin`), and also,\nfunctions to create and use I/O streams.\n\n\n## Input/Output basics {#sec-io-basics}\n\nIf you have some experience in a high-level language, you have certainly used\nthese input and output functionalities before in this language. In other words, you certainly have\nbeen in a situation where you needed to sent some output to the user, or, to receive an input\nfrom the user.\n\nFor example, in Python we can receive some input from the user by using the `input()` built-in\nfunction. But we can also print (or \"show\") some output to the user by using the `print()`\nbuilt-in function. So yes, if you have programmed before in Python, you certainly have\nused these functions once before.\n\nBut do you know how these functions relate back to your operating system (OS)? How exactly\nthey are interacting with the resources of your OS to receive or sent some input/output.\nIn essence, these input/output functions from high-level languages are just abstractions\nover the *standard output* and *standard input* channels of your operating system.\n\nThis means that we receive an input, or send some output, through the operating system.\nIt is the OS that makes the bridge between the user and your program. Your program\ndoes not have a direct access to the user. It is the OS that intermediates every\nmessage exchanged between your program and the user.\n\nThe *standard output* and *standard input* channels of your OS are commonly known as the\n`stdout` and `stdin` channels of your OS, respectively. In some contexts, they are also\ncalled the *standard output device* and the *standard input device*. As the name suggests,\nthe *standard output* is the channel through which output flows, while the *standard input*\nis the channel in which input flows.\n\nFurthermore, OS's also normally create a dedicated channel for exchanging error messages, which is known as the\n*standard error* channel, or, the `stderr` channel. This is the channel to which error and warning messages\nare usually sent to. These are the messages that are normally displayed in red-like or orange-like colors\ninto your terminal.\n\nNormally, every OS (e.g. Windows, macOS, Linux, etc.) creates a dedicated and separate set of\n*standard output*, *standard error* and *standard input* channels for every single program (or process) that runs in your computer.\nThis means that every program you write have a dedicated `stdin`, `stderr` and `stdout` that are separate\nfrom the `stdin`, `stderr` and `stdout` of other programs and processes that are currently running.\n\nThis is a behaviour from your OS. This does not come from the programming language that you are using.\nBecause as I sad earlier, input and output in programming languages, especially\nin high-level ones, are just a simple abstraction over the `stdin`, `stderr` and `stdout` from your current OS.\nThat is, your OS is the intermediary between every input/output operation made in your program,\nregardless of the programming language that you are using.\n\n\n### The writer and reader pattern {#sec-writer-reader}\n\nIn Zig, there is a pattern around input/output (IO). I (the author of this book) don't know if there\nis an official name for this pattern. But here, in this book, I will call it the \"writer and reader pattern\".\nIn essence, every IO operation in Zig is made through either a `GenericReader` or a `GenericWriter` object[^gen-zig].\n\nThese two data types come from the `std.io` module of the Zig Standard Library. As their names suggests, a\n`GenericReader` is an object that offers tools to read data from \"something\" (or \"somewhere\"), while a `GenericWriter`\noffers tools to write data into this \"something\". This \"something\" might be different things: like a\nfile that exists in your filesystem; or, it might be a network socket in your system[^sock]; or,\na continuous stream of data, like a standard input device from your system, that might be constantly\nreceiving new data from users, or, as another example, a live chat in a game that is constantly\nreceiving and displaying new messages from the players of the game.\n\n[^gen-zig]: Previously, these objects were known as the `Reader` and `Writer` objects.\n[^sock]: The socket objects that we have created at @sec-create-socket, are examples of network sockets.\n\nSo, if you want to **read** data from something, or somewhere, it means that you need to use a `GenericReader` object.\nBut if you need instead, to **write** data into this \"something\", then, you need to use a `GenericWriter` object instead.\nBoth of these objects are normally created from a file descriptor object. More specifically, through the `writer()` and `reader()`\nmethods of this file descriptor object. If you are not familiar with this type of object, go to the next section.\n\nEvery `GenericWriter` object have methods like `print()`, which allows you to write/send a formatted string\n(i.e. this formatted string is like a `f` string in Python, or, similar to the `printf()` C function)\ninto the \"something\" (file, socket, stream, etc.) that you are using. It also have a `writeAll()` method, which allows you to\nwrite a string, or, an array of bytes into the \"something\".\n\nLikewise, every `GenericReader` object have methods like `readAll()`, which allows you to read the\ndata from the \"something\" (file, socket, stream, etc.) until it fills a particular array (i.e. a \"buffer\") object.\nIn other words, if you provide an array object of 300 `u8` values to `readAll()`, then, this method attempts to read 300 bytes\nof data from the \"something\", and it stores them into the array object that you have provided.\n\nWe also have other methods, like the `readAtLeast()` method, which allows you to specify how\nmany bytes exactly you want to read from the \"something\". In more details, if you give the\nnumber $n$ as input to this method, then, it will attempt to read at least $n$ bytes of data\nfrom the \"something\". The \"something\" might have less than $n$ bytes of data available for you\nto read, so, it is not guaranteed that you will get precisely $n$ bytes as result.\n\nAnother useful method is `readUntilDelimiterOrEof()`. In this method, you specify a \"delimiter character\".\nThe idea is that this function will attempt to read as many bytes of data as possible from the \"something\",\nuntil it encounters the end of the stream, or, it encounters the \"delimiter character\" that you have specified.\n\nIf you don't know exactly how many bytes will come from the \"something\", you may find the `readAllAlloc()` method\nuseful. In essence, you provide an allocator object to this method, so that it can allocate more space if needed.\nAs consequence, this method will try to read all bytes of the \"something\", and, if it runs out of space at some point\nduring the \"reading process\", it uses the allocator object to allocate more space to continue reading the bytes.\nAs result, this method returns a slice to the array object containing all the bytes read.\n\nThis is just a quick description of the methods present in these types of objects. But I recommend you\nto read the official docs, both for\n[`GenericWriter`](https://ziglang.org/documentation/master/std/#std.io.GenericWriter)[^gen-write] and\n[`GenericReader`](https://ziglang.org/documentation/master/std/#std.io.GenericReader)[^gen-read].\nI also think it is a good idea to read the source code of the modules in the Zig Standard Library\nthat defines the methods present in these objects, which are the\n[`Reader.zig`](https://github.com/ziglang/zig/blob/master/lib/std/io/Reader.zig)[^mod-read]\nand [`Writer.zig`]()[^mod-write].\n\n[^gen-read]: .\n[^gen-write]: .\n[^mod-read]: .\n[^mod-write]: .\n\n\n\n### Introducing file descriptors {#sec-file-descriptor}\n\nA \"file descriptor\" object is a core component behind every IO operation that is made in any operating system (OS).\nSuch object is an identifier for a particular input/output (IO) resource from your OS [@wiki_file_descriptor].\nIt describes and identifies this particular resource. An IO resource might be:\n\n- an existing file in your filesystem.\n- an existing network socket.\n- other types of stream channels.\n- a pipeline (or just \"pipe\") in your terminal[^pipes].\n\n[^pipes]: A pipeline is a mechanism for inter-process communication, or, inter-process IO. You could also interpret a pipeline as a \"set of processes that are chained together, through the standard input/output devices of the system\". At Linux for example, a pipeline is created inside a terminal, by connecting two or more terminal commands with the \"pipe\" character (`|`).\n\nFrom the bullet points listed above, we know that although the term \"file\" is present,\na \"file descriptor\" might describe something more than just a file.\nThis concept of a \"file descriptor\" comes from the Portable Operating System Interface (POSIX) API,\nwhich is a set of standards that guide how operating systems across the world should be implemented,\nto maintain compatibility between them.\n\nA file descriptor not only identifies the input/output resource that you are using to receive or send some data,\nbut it also describes where this resource is, and also, which IO mode this resource is currently using.\nFor example, this IO resource might be using only the \"read\" IO mode, which means that this resource\nis open to \"read operations\", while \"write operations\" are not authorized.\nThese IO modes are essentially the modes that you provide to the argument `mode`\nfrom the `fopen()` C function, and also, from the `open()` Python built-in function.\n\nIn C, a \"file descriptor\" is a `FILE` pointer, but, in Zig, a file descriptor is a `File` object.\nThis data type (`File`) is described in the `std.fs` module of the Zig Standard Library.\nWe normally don't create a `File` object directly in our Zig code. Instead, we normally get such object as result when we\nopen an IO resource. In other words, we normally ask our OS to open a particular IO resource for us,\nand, if the OS do open successfully this IO resource, the OS normally handles back to us\na file descriptor to this particular IO resource.\n\nSo you usually get a `File` object by using functions and methods from the Zig Standard Library\nthat asks the OS to open some IO resource, like the `openFile()` method that opens a file in the\nfilesystem. The `net.Stream` object that we have created at @sec-create-socket is also a type of\nfile descriptor object.\n\n\n### The *standard output*\n\nYou already saw across this book, how can we access and use specifically the `stdout` in Zig\nto send some output to the user.\nFor that, we use the `getStdOut()` function from the `std.io` module. This function returns\na file descriptor that describes the `stdout` channel of your current OS. Through this file\ndescriptor object, we can read from or write stuff to the `stdout` of our program.\n\nAlthough we can read stuff recorded into the `stdout` channel, we normally only\nwrite to (or \"print\") stuff into this channel. The reason is very similar to what we discussed at\n@sec-read-http-message, when we were discussing what \"reading from\" versus \"writing to\" the connection\nobject from our small HTTP Server project would mean.\n\nWhen we write stuff into a channel, we are essentially sending data to the other end of this channel.\nIn contrast, when we read stuff from this channel, we are essentially reading the data that was sent\nthrough this channel. Since the `stdout` is a channel to send output to the user, the key verb here\nis **send**. We want to send something to someone, and, as consequence, we want to **write** something\ninto some channel.\n\nThat is why, when we use `getStdOut()`, most of the times, we also use the `writer()` method from the `stdout` file descriptor,\nto get access to a writer object that we can use to write stuff into this `stdout` channel.\nMore specifically, this `writer()` method returns a `GenericWriter` object. One of the\nmain methods of this `GenericWriter` object is the `print()` method that we have used\nbefore to write (or \"print\") a formatted string into the `stdout` channel.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n try stdout.writeAll(\n \"This message was written into stdout.\\n\"\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nThis message was written into stdout.\n```\n\n\n:::\n:::\n\n\n\n\n\n\nThis `GenericWriter` object is like any other generic writer object that you would normally get from a file descriptor object.\nSo, the same methods from a generic writer object that you would use while writing files to the filesystem for example, you could also\nuse them here, from the file descriptor object of `stdout`, and vice-versa.\n\n\n### The *standard input*\n\nYou can access the *standard input* (i.e. `stdin`) in Zig by using the `getStdIn()` function from the `std.io` module.\nLike its brother (`getStdOut()`), this function also returns a file descriptor object that describes the `stdin` channel\nof your OS.\n\nBecause we want to receive some input from the user, the key verb here becomes **receive**, and, as consequence,\nwe usually want to **read** data from the `stdin` channel, instead of writing data into it. So, we normally use\nthe `reader()` method of the file descriptor object returned by `getStdIn()`, to get access to a `GenericReader`\nobject that we can use to read data from `stdin`.\n\nIn the example below, we are creating a small buffer capable of holding 20 characters. Then, we try to read\nthe data from the `stdin` with the `readUntilDelimiterOrEof()` method, and save this data into the `buffer` object.\nAlso notice that we are reading the data from the `stdin` until we hit a new line character (`'\\n'`).\n\nIf you execute this program, you will notice that it stops the execution, ands start to wait indefinitely\nfor some input from the user. In other words, you need to type your name into the terminal, and then, you press Enter to\nsend your name to `stdin`. After you send your name to `stdin`, the program reads this input, and continues with the execution,\nby printing the given name to `stdout`. In the example below, I typed my name (Pedro) into the terminal, and then, pressed Enter.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst stdin = std.io.getStdIn().reader();\npub fn main() !void {\n try stdout.writeAll(\"Type your name\\n\");\n var buffer: [20]u8 = undefined;\n @memset(buffer[0..], 0);\n _ = try stdin.readUntilDelimiterOrEof(buffer[0..], '\\n');\n try stdout.print(\"Your name is: {s}\\n\", .{buffer});\n}\n```\n:::\n\n\n\n\n```\nType your name\nYour name is: Pedro\n\n```\n\n\n### The *standard error*\n\nThe *standard error* (a.k.a. the `stderr`) works exactly the same as `stdout` and `stdin`.\nYou just call the `getStdErr()` function from the `std.io` module, and you get the file descriptor to `stderr`.\nIdeally, you should write only error or warning messages to `stderr`, because this is\nthe purpose of this channel.\n\n\n\n\n\n## Buffered IO\n\nAs we described at @sec-io-basics, input/output (IO) operations are made directly by the operating system.\nIt is the OS that manages the IO resource that you want to use for your IO operations.\nThe consequence of this fact is that IO operations are heavily based on system calls (i.e. calling the operating system directly).\n\nJust to be clear, there is nothing particularly wrong with system calls. We use them all the time on\nany serious codebase written in any low-level programming language. However, system calls are\nalways orders of magnitude slower than many different types of operations.\n\nSo is perfectly fine to use a system call once in a while. But when these system calls are used often,\nyou can clearly notice most of the time the loss of performance in your application. So, the good rule of thumbs\nis to use a system call only when it is needed, and also, only in infrequent situations, to reduce\nthe number of system calls performed to a minimum.\n\n\n### Understanding how buffered IO works\n\nBuffered IO is a strategy to achieve better performance. It is used to reduce the number of system calls made by IO operations, and, as\nconsequence, achieve a much higher performance. At @fig-unbuffered-io and @fig-buffered-io you can find two different diagrams\nwhich presents the difference between read operations performed in an unbuffered IO environment versus a buffered IO environment.\n\nTo give a better context to these diagrams, let's suppose that we have a text file that contains the famous Lorem ipsum text[^lorem]\nin our filesystem. Let's also suppose that these diagrams at @fig-unbuffered-io and @fig-buffered-io\nare showing the read operations that we are performing to read the Lorem ipsum text from this text file.\nThe first thing you will notice when looking at these diagrams, is that in an unbuffered environment\nthe read operations leads to many system calls.\nMore precisely, in the diagram exposed at @fig-unbuffered-io we get one system call per each byte that we read from the text file.\nOn the other hand, at @fig-buffered-io we have only one system call at the very beginning.\n\nWhen we use a buffered IO system, at the first read operation we perform, instead of sending one single byte directly\nto our program, the OS first sends a chunk of bytes from the file to a buffer object (i.e. an array).\nThis chunk of bytes are cached/stored inside this buffer object.\n\nTherefore, from now on, for every new read operation that you perform, instead of making a new system call to ask\nfor the next byte in the file to the OS, this read operation is redirected to the buffer object, that have\nthis next byte already cached and ready to go.\n\n\n[^lorem]: .\n\n\n![Unbuffered IO](./../Figures/unbuffered-io.png){#fig-unbuffered-io width=60%}\n\n![Buffered IO](./../Figures/buffered-io.png){#fig-buffered-io}\n\n\n\nThis is the basic logic behind buffered IO systems. The size of the buffer object depends on multiple factors. But it is usually\nequal to the size of a full page of memory (4096 bytes). If we follow this logic, then, the OS reads the first 4096 bytes\nof the file and caches it into the buffer object. As long as your program does not consume all of these 4096 bytes from the buffer,\nyou will not create new system calls.\n\nHowever, as soon as you consume all of these 4096 bytes from the buffer, it means that there is no bytes left in the buffer.\nIn this situation, a new system call is made to ask the OS to send the next 4096 bytes in the file, and once again,\nthese bytes are cached into the buffer object, and the cycle starts once again.\n\n\n### Buffered IO across different languages\n\nIO operations made through a `FILE` pointer in C are buffered\nby default, so, at least in C, you don't need to worry about this subject. But in contrast, IO operations in both Rust and Zig are not\nbuffered depending on which functions from the standard libraries that you are using.\n\nFor example, in Rust, buffered IO is implemented through the `BufReader` and `BufWriter` structs, while in Zig, it is implemented\nthrough the `BufferedReader` and `BufferedWriter` structs.\nSo any IO operation that you perform through the `GenericWriter` and `GenericReader` objects\nthat I presented at @sec-writer-reader are not buffered, which means that these objects\nmight create a lot of system calls depending on the situation.\n\n\n### Using buffered IO in Zig\n\nUsing buffered IO in Zig is actually very easy. All you have to do is to just\ngive the `GenericWriter` object to the `bufferedWriter()` function, or, to give the `GenericReader`\nobject to the `bufferedReader()` function. These functions come from the `std.io` module,\nand they will construct the `BufferedWriter` or `BufferedReader` object for you.\n\nAfter you create this new `BufferedWriter` or `BufferedReader` object, you can call the `writer()`\nor `reader()` method of this new object, to get access to a new (and buffered) generic reader or\ngeneric writer.\n\nLet's describe the process once again. Every time that you have a file descriptor object, you first get the generic writer or generic reader\nobject from it, by calling the `writer()` or `reader()` methods of this file descriptor object.\nThen, you provide this generic writer or generic reader to the `bufferedWriter()` or `bufferedReader()`\nfunction, which creates a new `BufferedWriter` or `BufferedReader` object. Then, you call\nthe `writer()` or `reader()` methods of this buffered writer or buffered reader object,\nwhich gives you access to a generic writer or a generic reader object that is buffered.\n\nTake this program as an example. This program is demonstrating the process exposed at @fig-buffered-io.\nWe are simply opening a text file that contains the Lorem ipsum text, and then, we create a buffered IO reader object\nat `bufreader`, and we use this `bufreader` object to read the contents of this file into a buffer object, then,\nwe end the program by printing this buffer to `stdout`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar file = try std.fs.cwd().openFile(\n \"ZigExamples/file-io/lorem.txt\", .{}\n);\ndefer file.close();\nvar buffered = std.io.bufferedReader(file.reader());\nvar bufreader = buffered.reader();\n\nvar buffer: [1000]u8 = undefined;\n@memset(buffer[0..], 0);\n\n_ = try bufreader.readUntilDelimiterOrEof(\n buffer[0..], '\\n'\n);\ntry stdout.print(\"{s}\\n\", .{buffer});\n```\n:::\n\n\n\n\n```\nLorem ipsum dolor sit amet, consectetur\nadipiscing elit. Sed tincidunt erat sed nulla ornare, nec\naliquet ex laoreet. Ut nec rhoncus nunc. Integer magna metus,\nultrices eleifend porttitor ut, finibus ut tortor. Maecenas\nsapien justo, finibus tincidunt dictum ac, semper et lectus.\nVivamus molestie egestas orci ac viverra. Pellentesque nec\narcu facilisis, euismod eros eu, sodales nisl. Ut egestas\nsagittis arcu, in accumsan sapien rhoncus sit amet. Aenean\nneque lectus, imperdiet ac lobortis a, ullamcorper sed massa.\nNullam porttitor porttitor erat nec dapibus. Ut vel dui nec\nnulla vulputate molestie eget non nunc. Ut commodo luctus ipsum,\nin finibus libero feugiat eget. Etiam vel ante at urna tincidunt\nposuere sit amet ut felis. Maecenas finibus suscipit tristique.\nDonec viverra non sapien id suscipit.\n```\n\nDespite being a buffered IO reader, this `bufreader` object is similar to any other `GenericReader` object,\nand have the exact same methods. So, although these two types of objects perform very different IO operations,\nthey have the same interface, so you, the programmer, can interchangeably use them\nwithout the need to change anything in your source code.\nSo a buffered IO reader or a buffered IO writer objects have the same methods than its generic and unbuffered brothers,\ni.e. the generic reader and generic writer objects that I presented at @sec-writer-reader.\n\n::: {.callout-tip}\nIn general, you should always use a buffered IO reader or a buffered IO writer object to perform\nIO operations in Zig. Because they deliver better performance to your IO operations.\n:::\n\n\n## Filesystem basics\n\nNow that we have discussed the basics around Input/Output operations in Zig, we need to\ntalk about the basics around filesystems, which is another core part of any operating system.\nAlso, filesystems are related to input/output, because the files that we store and create in our\ncomputer are considered an IO resource, as we described at @sec-file-descriptor.\n\n\n### The concept of current working directory (CWD)\n\nThe working directory is the folder on your computer where you are currently rooted at.\nIn other words, it is the folder that your program is currently looking at.\nTherefore, whenever you are executing a program, this program is always working with\na specific folder on your computer. It is always in this folder that the program will initially\nlook for the files you require, and it is also in this folder that the program\nwill initially save all the files you ask it to save.\n\nThe working directory is determined by the folder from which you invoke your program\nin the terminal. In other words, if you are in the terminal of your OS, and you\nexecute a binary file (i.e. a program) from this terminal, the folder to which your terminal\nis pointing at is the current working directory of your program that is being executed.\n\nAt @fig-cwd we have an example of me executing a program from the terminal. We are executing\nthe program outputted by the `zig` compiler by compiling the Zig module named `hello.zig`.\nThe CWD in this case is the `zig-book` folder. In other words, while the `hello.zig` program\nis executing, it will be looking at the `zig-book` folder, and any file operation that we perform\ninside this program, will be using this `zig-book` folder as the \"starting point\", or, as the \"central focus\".\n\n![Executing a program from the terminal](./../Figures/cwd.png){#fig-cwd}\n\nJust because we are rooted inside a particular folder (in the case of @fig-cwd, the `zig-book` folder) of our computer,\nit doesn't mean that we cannot access or write resources in other locations of our computer.\nThe current working directory (CWD) mechanism just defines where your program will look first\nfor the files you ask for. This does not prevent you from accessing files that are located\nelsewhere on your computer. However, to access any file that is in a folder other than your\ncurrent working directory, you must provide a path to that file or folder.\n\n\n### The concept of paths\n\nA path is essentially a location. It points to a location in your filesystem. We use\npaths to describe the location of files and folders in our computer.\nOne important aspect about paths is that they are always written inside strings,\ni.e. they are always provided as text values.\n\nThere are two types of paths that you can provide to any program in any OS: a relative path, or an absolute path.\nAbsolute paths are paths that start at the root of your filesystem, and go all the way to the file name or the specific folder\nthat you are referring to. This type of path is called absolute, because it points to an unique and absolute location on your computer.\nThat is, there is no other existing location on your computer that corresponds to this path. It is an unique identifier.\n\nIn Windows, an absolute path is a path that starts with a hard disk identifier (e.g. `C:/Users/pedro`).\nOn the other hand, absolute paths in Linux and macOS, are paths that start with a forward slash character (e.g. `/usr/local/bin`).\nNotice that a path is composed by \"segments\". Each segment is connected to each other by a slash character (`\\` or `/`).\nOn Windows, the backward slash (`\\`) is normally used to connect the path segments. While on Linux and macOS, the forward\nslash (`/`) is the character used to connect path segments.\n\nA relative path is a path that start at the CWD. In other words, a relative path is\n\"relative to the CWD\". The path used to access the `hello.zig` file at @fig-cwd is an example of a relative path. This path\nis reproduced below. This path begins at the CWD, which in the context of @fig-cwd, is the `zig-book` folder,\nthen, it goes to the `ZigExamples` folder, then, into `zig-basics`, then, to the `hello.zig` file.\n\n```\nZigExamples/zig-basics/hello_world.zig\n```\n\n\n### Path wildcards\n\nWhen providing paths, especially relative paths, you have the option of using a *wildcard*.\nThere are two commonly used *wildcards* in paths, which are \"one period\" (.) and \"two periods\" (..).\nIn other words, these two specific characters have special meanings when used in paths,\nand can be used on any operating system (Mac, Windows, Linux, etc.). That is, they\nare \"cross platform\".\n\nThe \"one period\" represents an alias for the current directory.\nThis means that the relative paths `\"./Course/Data/covid.csv\"` and `\"Course/Data/covid.csv\"` are equivalent.\nOn the other hand, the \"two periods\" refers to the previous directory.\nFor example, the path `\"Course/..\"` is equivalent to the path `\".\"`, that is, the current working directory.\n\nTherefore, the path `\"Course/..\"` refers to the folder before the `Course` folder.\nAs another example, the path `\"src/writexml/../xml.cpp\"` refers to the file `xml.cpp`\nthat is inside the folder before the `writexml` folder, which in this example is the `src` folder.\nTherefore, this path is equivalent to `\"src/xml.cpp\"`.\n\n\n\n\n## The CWD handler\n\nIn Zig, filesystem operations are usually made through a directory handler object.\nA directory handler in Zig is an object of type `Dir`, which is an object that describes\na particular folder in the filesystem of our computer.\nYou normally create a `Dir` object, by calling the `std.fs.cwd()` function.\nThis function returns a `Dir` object that points to (or, that describes) the\ncurrent working directory (CWD).\n\nThrough this `Dir` object, you can create new files, or modify, or read existing ones that are\ninside your CWD. In other words, a `Dir` object is the main entrypoint in Zig to perform\nmultiple types of filesystem operations.\nIn the example below, we are creating this `Dir` object, and storing it\ninside the `cwd` object. Although we are not using this object at this code example,\nwe are going to use it a lot over the next examples.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\n_ = cwd;\n```\n:::\n\n\n\n\n\n\n\n\n\n\n\n## File operations\n\n### Creating files {#sec-creating-files}\n\nWe create new files by using the `createFile()` method from the `Dir` object.\nJust provide the name of the file that you want to create, and this function will\ndo the necessary steps to create such file. You can also provide a relative path to this function,\nand it will create the file by following this path, which is relative to the CWD.\n\nThis function might return an error, so, you should use `try`, `catch`, or any of the other methods presented\nat @sec-error-handling to handle the possible error. But if everything goes well,\nthis `createFile()` method returns a file descriptor object (i.e. a `File` object) as result,\nthrough which you can add content to the file with the IO operations that I presented before.\n\nTake this code example below. In this example, we are creating a new text file\nnamed `foo.txt`. If the function `createFile()` succeeds, the object named `file` will contain a file descriptor\nobject, which we can use to write (or add) new content to the file, like we do in this example, by using\na buffered writer object to write a new line of text to the file.\n\nNow, a quick note, when we create a file descriptor object in C, by using a C function like `fopen()`, we must always close the file\nat the end of our program, or, as soon as we complete all operations that we wanted to perform\non the file. In Zig, this is no different. So everytime we create a new file, this file remains\n\"open\", waiting for some operation to be performed. As soon as we are done with it, we always have\nto close this file, to free the resources associated with it.\nIn Zig, we do this by calling the method `close()` from the file descriptor object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.createFile(\"foo.txt\", .{});\n// Don't forget to close the file at the end.\ndefer file.close();\n// Do things with the file ...\nvar fw = file.writer();\n_ = try fw.writeAll(\n \"Writing this line to the file\\n\"\n);\n```\n:::\n\n\n\n\n\nSo, in this example we not only have created a file into the filesystem,\nbut we also wrote some data into this file, using the file descriptor object\nreturned by `createFile()`. If the file that you are trying to create\nalready exists in your filesystem, this `createFile()` call will\noverwrite the contents of the file, or, in other words, it will\nin erase all the contents of the existing file.\n\nIf you don't want this to happen, meaning, that you don't want to overwrite\nthe contents of the existing file, but you want to write data to this file anyway\n(i.e. you want to append data to the file), you should use the `openFile()`\nmethod from the `Dir` object.\n\nAnother important aspect about `createFile()` is that this method creates a file\nthat is not open to read operations by default. It means that you cannot read this file.\nYou are not allowed to.\nSo for example, you might want to write some stuff into this file at the beginning of the execution\nof your program. Then, at a future point in your program you might need to read what you\nwrote in this file. If you try to read data from this file, you will likely\nget a `NotOpenForReading` error as result.\n\n\nBut how can you overcome this barrier? How can you create a file that is open\nto read operations? All you have to do, is to set the `read` flag to true\nin the second argument of `createFile()`. When you set this flag to true,\nthen the file get's create with \"read permissions\", and, as consequence,\na program like this one below becomes valid:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.createFile(\n \"foo.txt\",\n .{ .read = true }\n);\ndefer file.close();\n\nvar fw = file.writer();\n_ = try fw.writeAll(\"We are going to read this line\\n\");\n\nvar buffer: [300]u8 = undefined;\n@memset(buffer[0..], 0);\ntry file.seekTo(0);\nvar fr = file.reader();\n_ = try fr.readAll(buffer[0..]);\ntry stdout.print(\"{s}\\n\", .{buffer});\n```\n:::\n\n\n\n\n\n```\nWe are going to read this line\n```\n\n\nIf you are not familiar with position indicators, you might not recognize the method\n`seekTo()`. If that is your case, do not worry,\nwe are going to talk more about this method at @sec-indicators. But essentially\nthis method is moving the position indicator back to the beginning of the file,\nso that we can read the contents of the file from the beginning.\n\n\n### Opening files and appending data to it\n\nOpening files is easy. Just use the `openFile()` method instead of `createFile()`.\nIn the first argument of `openFile()` you provide the path to the file that\nyou want to open. Then, on the second argument you provide the flags (or, the options)\nthat dictates how the file is opened.\n\nYou can see the full list of options for `openFile()` by visiting the documentation for\n[`OpenFlags`](https://ziglang.org/documentation/master/std/#std.fs.File.OpenFlags)[^oflags].\nBut the main flag that you will most certainly use is the `mode` flag.\nThis flag specifies the IO mode that the file will be using when it get's opened.\nThere are three IO modes, or, three values that you can provide to this flag, which are:\n\n- `read_only`, allows only read operations on the file. All write operations are blocked.\n- `write_only`, allows only write operations on the file. All read operations are blocked. \n- `read_write`, allows both write and read operations on the file.\n\n[^oflags]: \n\nThese modes are similar to the modes that you provide to the `mode` argument of the\n`open()` Python built-in function[^py-open], or, the `mode` argument of the\n`fopen()` C function[^c-open].\nIn the code example below, we are opening the `foo.txt` text file with a `write_only` mode,\nand appending a new line of text to the end of the file. We use `seekFromEnd()` this time\nto guarantee that we are going to append the text to the end of the file. Once again, methods\nsuch as `seekFromEnd()` are described in more depth at @sec-indicators.\n\n[^py-open]: \n[^c-open]: \n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.openFile(\n \"foo.txt\", .{ .mode = .write_only }\n);\ndefer file.close();\ntry file.seekFromEnd(0);\nvar fw = file.writer();\n_ = try fw.writeAll(\"Some random text to write\\n\");\n```\n:::\n\n\n\n\n\n### Deleting files\n\nSometimes, we just need to delete/remove the files that we have.\nTo do that, we use the `deleteFile()` method. You just provide the path of the\nfile that you want to delete, and this method will try to delete the file located\nat this path.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.deleteFile(\"foo.txt\");\n```\n:::\n\n\n\n\n### Copying files\n\nTo copy existing files, we use the `copyFile()` method. The first argument in this method\nis the path to the file that you want to copy. The second argument is a `Dir` object, i.e. a directory handler,\nmore specifically, a `Dir` object that points to the folder in your computer where you want to\ncopy the file to. The third argument is the new path of the file, or, in other words, the new location\nof the file. The fourth argument is the options (or flags) to be used in the copy operation.\n\nThe `Dir` object that you provide as input to this method will be used to copy the file to\nthe new location. You may create this `Dir` object before calling the `copyFile()` method.\nMaybe you are planning to copy the file to a completely different location in your computer,\nso it might be worth to create a directory handler to that location. But if you are copying the\nfile to a subfolder of your CWD, then, you can just simply pass the CWD handler to this argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.copyFile(\n \"foo.txt\",\n cwd,\n \"ZigExamples/file-io/foo.txt\",\n .{}\n);\n```\n:::\n\n\n\n\n\n### Read the docs!\n\nThere are some other useful methods for file operations available at `Dir` objects,\nsuch as the `writeFile()` method, but I recommend you to read the docs for the\n[`Dir` type](https://ziglang.org/documentation/master/std/#std.fs.Dir)[^zig-dir]\nto explore the other available methods, since I already talked too much about them.\n\n\n[^zig-dir]: \n\n\n\n\n## Position indicators {#sec-indicators}\n\nA position indicator is like a type of cursor, or, an index. This \"index\" identifies the current\nlocation in the file (or, in the data stream) that the file descriptor object that you have\nis currently looking at.\nWhen you create a file descriptor, the position indicator starts at the beginning of the file,\nor, at the beginning of the stream. When you read from or write into the file (or socket, or data stream, etc.)\ndescribed by this file descriptor object, you end up moving the position indicator.\n\nIn other words, any IO operation have a common side effect, which is to move the position indicator.\nFor example, suppose that we have a file of 300 bytes total in size. If you\nread 100 bytes from the file, then, the position indicator moves 100 bytes forward. If you try\nto write 50 bytes into this same file, these 50 bytes will be written from the current\nposition indicated by the position indicator. Since the indicator is at a 100 bytes forward from\nthe beginning of the file, these 50 bytes would be written in the middle of the file.\n\nThis is why we have used the `seekTo()` method at the last code example presented at @sec-creating-files.\nWe have used this method to move the position indicator back to the beginning of the file, which\nwould make sure that we would write the text that we wanted to write from the beginning of the file,\ninstead of writing it from the middle of the file. Because before the write operation, we had\nperformed a read operation, which means that the position indicator was moved in this read operation.\n\nThe position indicators of a file descriptor object can be changed (or altered) by using the\n\"seek\" methods from this file descriptor, which are: `seekTo()`, `seekFromEnd()` and `seekBy()`.\nThese methods have the same effect, or, the same responsibility that the\n[`fseek()`](https://en.cppreference.com/w/c/io/fseek)[^c-fseek] C function.\n\n[^c-fseek]: \n\n\nConsidering that `offset` refers to the index that you provide as input to these \"seek\" methods,\nthe bullet points below summarises what is the effect of each of these methods.\nAs a quick note, in the case of `seekFromEnd()` and `seekBy()`, the `offset` provided can be either a\npositive or a negative index.\n\n- `seekTo()` will move the position indicator to the location that is `offset` bytes from the beginning of the file.\n- `seekFromEnd()` will move the position indicator to the location that is `offset` bytes from the end of the file.\n- `seekBy()` will move the position indicator to the location that is `offset` bytes from the current position in the file.\n\n\n\n\n\n\n\n## Directory operations\n\n### Iterating through the files in a directory\n\nOne of the most classic tasks related to filesystem is to be able\nto iterate through the existing files in a directory. To iterate over the\nfiles in a directory, we need to create an iterator object.\n\nYou can produce such iterator object by using either the `iterate()` or `walk()` methods\nof a `Dir` object. Both methods return an iterator object as output, which you can advance by using the\n`next()` method. The difference between these methods, is that `iterate()` returns a non-recursive iterator,\nwhile `walk()` does. It means that the iterator returned by `walk()` will not only iterate through\nthe files available in the current directory, but also, through the files from any subdirectory found\ninside the current directory.\n\nIn the example below, we are displaying the names of the files stored inside the\ndirectory `ZigExamples/file-io`. Notice that we had to open this directory through\nthe `openDir()` function. Also notice that we provided the flag `iterate` in the\nsecond argument of `openDir()`. This flag is important, because without this flag,\nwe would not be allowed to iterate through the files in this directory.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst dir = try cwd.openDir(\n \"ZigExamples/file-io/\",\n .{ .iterate = true }\n);\nvar it = dir.iterate();\nwhile (try it.next()) |entry| {\n try stdout.print(\n \"File name: {s}\\n\",\n .{entry.name}\n );\n}\n```\n:::\n\n\n\n\n```\nFile name: create_file_and_write_toit.zig\nFile name: create_file.zig\nFile name: lorem.txt\nFile name: iterate.zig\nFile name: delete_file.zig\nFile name: append_to_file.zig\nFile name: user_input.zig\nFile name: foo.txt\nFile name: create_file_and_read.zig\nFile name: buff_io.zig\nFile name: copy_file.zig\n```\n\n\n### Creating new directories\n\nThere are two methods that are important when it comes to\ncreating directories, which are `makeDir()` and `makePath()`.\nThe difference between these two methods is that `makeDir()` can\nonly create one single directory in the current directory in each call,\nwhile `makePath()` is capable of recursively create subdirectories in the same call.\n\n\nThis is why the name of this method is \"make path\". It will create as many\nsubdirectories as necessary to create the path that you provided as input.\nSo, if you provide the path `\"sub1/sub2/sub3\"` as input to this method,\nit will create three different subdirectories, `sub1`, `sub2` and `sub3`,\nwithin the same function call. In contrast, if you provided such path\nas input to `makeDir()`, you would likely get an error as result, since\nthis method can only create a single subdirectory.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.makeDir(\"src\");\ntry cwd.makePath(\"src/decoders/jpg/\");\n```\n:::\n\n\n\n\n### Deleting directories\n\nTo delete a directory, just provide the path to the directory that you want to delete\nas input to the `deleteDir()` method from a `Dir` object. In the example below,\nwe are deleting the `src` directory that we have just created in the previous example.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.deleteDir(\"src\");\n```\n:::\n\n\n\n\n\n## Conclusion\n\nIn this chapter, I have described how to perform in Zig the most common filesystem and IO operations.\nBut you might feel the lack of some other, less common, operation in this chapter, such as: how to rename files,\nor how to open a directory, or how to create symbolic links, or how to use `access()` to test if a particular\npath exists in your computer. But for all of these less common tasks, I recommend you to read\nthe documentation of the [`Dir` type](https://ziglang.org/documentation/master/std/#std.fs.Dir)[^zig-dir]\n, since you can find a good description of these cases there.\n\n\n\n\n", - "supporting": [ - "12-file-op_files" - ], + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/index/execute-results/html.json b/_freeze/index/execute-results/html.json index 94307194..b3df0c6d 100644 --- a/_freeze/index/execute-results/html.json +++ b/_freeze/index/execute-results/html.json @@ -3,9 +3,7 @@ "result": { "engine": "knitr", "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy\nof the book, either at Amazon, or at Leanpub:\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2025,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {February},\n edition = {2},\n year = {2025},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion)\n", - "supporting": [ - "index_files" - ], + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/docs/Chapters/03-structs.html b/docs/Chapters/03-structs.html index 69a800e7..9a0d90ff 100644 --- a/docs/Chapters/03-structs.html +++ b/docs/Chapters/03-structs.html @@ -927,7 +927,8 @@

    try expect(@TypeOf(y) == u32); }

    -
    1/1 file2ed34a8fc96.test_0...OKAll 1 tests passed.
    +
    1/1 file9f8940318094.test_0...OKAll 1 tests passed
    +  d.

    This is the general way to perform type casting in Zig. But remember, @as() works only when casting is unambiguous and safe, and there are situations where these assumptions do not hold. For example, when casting an integer value into a float value, or vice-versa, it is not clear to the compiler how to perform this conversion safely.

    @@ -942,7 +943,7 @@

    try expect(@TypeOf(y) == f32); }
    -
    1/1 file2ed34bfb9fa5.test_0...OKAll 1 tests passed
    +
    1/1 file9f8954828844.test_0...OKAll 1 tests passed
       d.
    @@ -959,7 +960,7 @@

    try expect(@TypeOf(u32_ptr) == *const u32); }
    -
    1/1 file2ed324328e1f.test_0...OKAll 1 tests passed
    +
    1/1 file9f8944ca02e1.test_0...OKAll 1 tests passed
       d.
    diff --git a/docs/Chapters/03-unittests.html b/docs/Chapters/03-unittests.html index e7ddd754..42c0c02b 100644 --- a/docs/Chapters/03-unittests.html +++ b/docs/Chapters/03-unittests.html @@ -323,7 +323,7 @@

    try expect((a + b) == 4); }
    -
    1/1 file153713a3190e.test.testing simple sum...OKA
    +
    1/1 filea5b06c1ec326.test.testing simple sum...OKA
       All 1 tests passed.
    @@ -396,8 +396,8 @@

    try expectError(error.OutOfMemory, alloc_error(allocator)); }
    -
    1/1 file1537546f248.test.testing error...OKAll 1 t
    -  tests passed.
    +
    1/1 filea5b059c00874.test.testing error...OKAll 1 
    +   tests passed.

    @@ -433,7 +433,7 @@

    ); }
    -
    1/1 file15377bbafb73.test.arrays are equal?...OKAl
    +
    1/1 filea5b054e42b80.test.arrays are equal?...OKAl
       ll 1 tests passed.
    diff --git a/docs/Chapters/09-error-handling.html b/docs/Chapters/09-error-handling.html index 597d0a92..e026d192 100644 --- a/docs/Chapters/09-error-handling.html +++ b/docs/Chapters/09-error-handling.html @@ -469,7 +469,7 @@

    ); }
    -
    1/1 file10459ffd0e21.test.coerce error value...OKA
    +
    1/1 filea64e1da1167c.test.coerce error value...OKA
       All 1 tests passed.
    diff --git a/docs/Chapters/10-stack-project.html b/docs/Chapters/10-stack-project.html index b81ac050..bd3e9cbb 100644 --- a/docs/Chapters/10-stack-project.html +++ b/docs/Chapters/10-stack-project.html @@ -370,8 +370,8 @@

    _ = twice(5678); }
    -
    1/1 file1105a40478a9d.test.test comptime...OKAll 1
    -  1 tests passed.
    +
    1/1 filea72d248f97f8.test.test comptime...OKAll 1 
    +   tests passed.

    But what if we provide a number that is not compile-time known to this function? For example, we might provide a different input value to this function depending on the target OS of our compilation process. The code example below demonstrates such case.

    @@ -426,8 +426,8 @@

    try comptime expect(fibonacci(7) == 13); }
    -
    1/1 file1105a31c0f24f.test.fibonacci...OKAll 1 tes
    -  sts passed.
    +
    1/1 filea72d3cf7abe2.test.fibonacci...OKAll 1 test
    +  ts passed.

    A lot of your Zig source code might be potentially executed at compile-time, because the zig compiler can figure it out the output of some expressions. Especially if these expressions depends only at compile-time known values. We have talked about this at Section 3.1.1.

    @@ -455,8 +455,8 @@

    _ = x; }
    -
    1/1 file1105a37ca2b0d.test.fibonacci in a block...
    -  .OKAll 1 tests passed.
    +
    1/1 filea72d6353d586.test.fibonacci in a block...O
    +  OKAll 1 tests passed.

    diff --git a/docs/search.json b/docs/search.json index a0dbe2a7..1d2f1f9f 100644 --- a/docs/search.json +++ b/docs/search.json @@ -274,7 +274,7 @@ "href": "Chapters/03-structs.html#sec-type-cast", "title": "2  Control flow, structs, modules and types", "section": "2.5 Type casting", - "text": "2.5 Type casting\nIn this section, I want to discuss type casting (or, type conversion) with you. We use type casting when we have an object of type “x”, and we want to convert it into an object of type “y”, i.e. we want to change the data type of the object.\nMost languages have a formal way to perform type casting. In Rust for example, we normally use the keyword as, and in C, we normally use the type casting syntax, e.g. (int) x. In Zig, we use the @as() built-in function to cast an object of type “x”, into an object of type “y”.\nThis @as() function is the preferred way to perform type conversion (or type casting) in Zig. Because it is explicit, and, it also performs the casting only if it is unambiguous and safe. To use this function, you just provide the target data type in the first argument, and, the object that you want cast as the second argument.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n\n1/1 file2ed34a8fc96.test_0...OKAll 1 tests passed.\n\n\nThis is the general way to perform type casting in Zig. But remember, @as() works only when casting is unambiguous and safe, and there are situations where these assumptions do not hold. For example, when casting an integer value into a float value, or vice-versa, it is not clear to the compiler how to perform this conversion safely.\nTherefore, we need to use specialized “casting functions” in such situations. For example, if you want to cast an integer value into a float value, then, you should use the @floatFromInt() function. In the inverse scenario, you should use the @intFromFloat() function.\nIn these functions, you just provide the object that you want to cast as input. Then, the target data type of the “type casting operation” is determined by the type annotation of the object where you are saving the results. In the example below, we are casting the object x into a value of type f32, because the object y, which is where we are saving the results, is annotated as an object of type f32.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n\n1/1 file2ed34bfb9fa5.test_0...OKAll 1 tests passed\n d.\n\n\nAnother built-in function that is very useful when performing type casting operations is @ptrCast(). In essence, we use the @as() built-in function when we want to explicit convert (or cast) a Zig value/object from a type “x” to a type “y”, etc. However, pointers (we are going to discuss pointers in more depth in Chapter 6) are a special type of object in Zig, i.e. they are treated differently from “normal objects”.\nEverytime a pointer is involved in some “type casting operation” in Zig, the @ptrCast() function is used. This function works similarly to @floatFromInt(). You just provide the pointer object that you want to cast as input to this function, and the target data type is, once again, determined by the type annotation of the object where the results are being stored.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n\n1/1 file2ed324328e1f.test_0...OKAll 1 tests passed\n d.", + "text": "2.5 Type casting\nIn this section, I want to discuss type casting (or, type conversion) with you. We use type casting when we have an object of type “x”, and we want to convert it into an object of type “y”, i.e. we want to change the data type of the object.\nMost languages have a formal way to perform type casting. In Rust for example, we normally use the keyword as, and in C, we normally use the type casting syntax, e.g. (int) x. In Zig, we use the @as() built-in function to cast an object of type “x”, into an object of type “y”.\nThis @as() function is the preferred way to perform type conversion (or type casting) in Zig. Because it is explicit, and, it also performs the casting only if it is unambiguous and safe. To use this function, you just provide the target data type in the first argument, and, the object that you want cast as the second argument.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n\n1/1 file9f8940318094.test_0...OKAll 1 tests passed\n d.\n\n\nThis is the general way to perform type casting in Zig. But remember, @as() works only when casting is unambiguous and safe, and there are situations where these assumptions do not hold. For example, when casting an integer value into a float value, or vice-versa, it is not clear to the compiler how to perform this conversion safely.\nTherefore, we need to use specialized “casting functions” in such situations. For example, if you want to cast an integer value into a float value, then, you should use the @floatFromInt() function. In the inverse scenario, you should use the @intFromFloat() function.\nIn these functions, you just provide the object that you want to cast as input. Then, the target data type of the “type casting operation” is determined by the type annotation of the object where you are saving the results. In the example below, we are casting the object x into a value of type f32, because the object y, which is where we are saving the results, is annotated as an object of type f32.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n\n1/1 file9f8954828844.test_0...OKAll 1 tests passed\n d.\n\n\nAnother built-in function that is very useful when performing type casting operations is @ptrCast(). In essence, we use the @as() built-in function when we want to explicit convert (or cast) a Zig value/object from a type “x” to a type “y”, etc. However, pointers (we are going to discuss pointers in more depth in Chapter 6) are a special type of object in Zig, i.e. they are treated differently from “normal objects”.\nEverytime a pointer is involved in some “type casting operation” in Zig, the @ptrCast() function is used. This function works similarly to @floatFromInt(). You just provide the pointer object that you want to cast as input to this function, and the target data type is, once again, determined by the type annotation of the object where the results are being stored.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n\n1/1 file9f8944ca02e1.test_0...OKAll 1 tests passed\n d.", "crumbs": [ "2  Control flow, structs, modules and types" ] @@ -634,7 +634,7 @@ "href": "Chapters/03-unittests.html", "title": "8  Unit tests", "section": "", - "text": "8.1 Introducing the test block\nIn Zig, unit tests are written inside a test declaration, or, how I prefer to call it, inside a test block. Every test block is written by using the keyword test. You can optionally use a string literal to write a label, which is responsible for identifying the specific group of unit tests that you are writing inside this specific test block.\nIn the example below, we are testing if the sum of two objects (a and b) is equal to 4. The expect() function from the Zig Standard Library is a function that receives a logical test as input. If this logical test results in true, then, the test passes. But if it results in false, then, the test fails.\nYou can write any Zig code you want inside a test block. Part of this code might be some necessary commands to setup your testing environment, or just initializing some objects that you need to use in your unit tests.\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest \"testing simple sum\" {\n const a: u8 = 2;\n const b: u8 = 2;\n try expect((a + b) == 4);\n}\n\n1/1 file153713a3190e.test.testing simple sum...OKA\n All 1 tests passed.\nYou can have multiple test blocks written on the same Zig module. Also, you can mix test blocks with your source code, with no problems or consequences. If you mix test blocks with your normal source code, when you execute the build, build-exe, build-obj or build-lib commands from the zig compiler that we exposed at Section 1.2.4, these test blocks are automatically ignored by the compiler.\nIn other words, the zig compiler builds and execute your unit tests only when you ask it to. By default, the compiler always ignore test blocks written in your Zig modules. The compiler normally checks only if there are any syntax errors in these test blocks.\nIf you take a look at the source code for most of the files present in the Zig Standard Library1, you can see that the test blocks are written together with the normal source code of the library. You can see this for example, at the array_list module2. So, the standard that the Zig developers decided to adopt is to keep their unit tests together with the source code of the functionality that they are testing.\nEach programmer might have a different opinion on this. Some of them might prefer to keep unit tests separate from the actual source code of their application. If that is your case, you can simply create a separate tests folder in your project, and start writing Zig modules that contains only unit tests (as you would normally do on a Python project with pytest, for example), and everything will work fine. It boils down to which is your preference here.", + "text": "8.1 Introducing the test block\nIn Zig, unit tests are written inside a test declaration, or, how I prefer to call it, inside a test block. Every test block is written by using the keyword test. You can optionally use a string literal to write a label, which is responsible for identifying the specific group of unit tests that you are writing inside this specific test block.\nIn the example below, we are testing if the sum of two objects (a and b) is equal to 4. The expect() function from the Zig Standard Library is a function that receives a logical test as input. If this logical test results in true, then, the test passes. But if it results in false, then, the test fails.\nYou can write any Zig code you want inside a test block. Part of this code might be some necessary commands to setup your testing environment, or just initializing some objects that you need to use in your unit tests.\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest \"testing simple sum\" {\n const a: u8 = 2;\n const b: u8 = 2;\n try expect((a + b) == 4);\n}\n\n1/1 filea5b06c1ec326.test.testing simple sum...OKA\n All 1 tests passed.\nYou can have multiple test blocks written on the same Zig module. Also, you can mix test blocks with your source code, with no problems or consequences. If you mix test blocks with your normal source code, when you execute the build, build-exe, build-obj or build-lib commands from the zig compiler that we exposed at Section 1.2.4, these test blocks are automatically ignored by the compiler.\nIn other words, the zig compiler builds and execute your unit tests only when you ask it to. By default, the compiler always ignore test blocks written in your Zig modules. The compiler normally checks only if there are any syntax errors in these test blocks.\nIf you take a look at the source code for most of the files present in the Zig Standard Library1, you can see that the test blocks are written together with the normal source code of the library. You can see this for example, at the array_list module2. So, the standard that the Zig developers decided to adopt is to keep their unit tests together with the source code of the functionality that they are testing.\nEach programmer might have a different opinion on this. Some of them might prefer to keep unit tests separate from the actual source code of their application. If that is your case, you can simply create a separate tests folder in your project, and start writing Zig modules that contains only unit tests (as you would normally do on a Python project with pytest, for example), and everything will work fine. It boils down to which is your preference here.", "crumbs": [ "8  Unit tests" ] @@ -664,7 +664,7 @@ "href": "Chapters/03-unittests.html#testing-errors", "title": "8  Unit tests", "section": "8.4 Testing errors", - "text": "8.4 Testing errors\nOne common style of unit tests are those that look for specific errors in your functions. In other words, you write a unit test that tries to assert if a specific function call returns any error, or a specific type of error.\nIn C++ you would normally write this style of unit tests using, for example, the functions REQUIRE_THROWS() or CHECK_THROWS() from the Catch2 test framework3. In the case of a Python project, you would probably use the raises() function from pytest4. While in Rust, you would probably use assert_eq!() in conjunction with Err().\nBut in Zig, we use the expectError() function, from the std.testing module. With this function, you can test if a specific function call returns the exact type of error that you expect it to return. To use this function, you first write try expectError(). Then, on the first argument, you provide the type of error that you are expecting from the function call. Then, on the second argument, you write the function call that you expect to fail.\nThe code example below demonstrates such type of unit test in Zig. Notice that, inside the function alloc_error() we are allocating 100 bytes of memory, or, an array of 100 elements, for the object ibuffer. However, in the test block, we are using the FixedBufferAllocator() allocator object, which is limited to 10 bytes of space, because the object buffer, which we provided to the allocator object, have only 10 bytes of space.\nThat is why, the alloc_error() function raises an OutOfMemory error on this case. Because this function is trying to allocate more space than the allocator object allows. So, in essence, we are testing for a specific type of error, which is OutOfMemory. If the alloc_error() function returns any other type of error, then, the expectError() function would make the entire test fail.\n\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst expectError = std.testing.expectError;\nfn alloc_error(allocator: Allocator) !void {\n var ibuffer = try allocator.alloc(u8, 100);\n defer allocator.free(ibuffer);\n ibuffer[0] = 2;\n}\n\ntest \"testing error\" {\n var buffer: [10]u8 = undefined;\n var fba = std.heap.FixedBufferAllocator.init(&buffer);\n const allocator = fba.allocator();\n try expectError(error.OutOfMemory, alloc_error(allocator));\n}\n\n1/1 file1537546f248.test.testing error...OKAll 1 t\n tests passed.", + "text": "8.4 Testing errors\nOne common style of unit tests are those that look for specific errors in your functions. In other words, you write a unit test that tries to assert if a specific function call returns any error, or a specific type of error.\nIn C++ you would normally write this style of unit tests using, for example, the functions REQUIRE_THROWS() or CHECK_THROWS() from the Catch2 test framework3. In the case of a Python project, you would probably use the raises() function from pytest4. While in Rust, you would probably use assert_eq!() in conjunction with Err().\nBut in Zig, we use the expectError() function, from the std.testing module. With this function, you can test if a specific function call returns the exact type of error that you expect it to return. To use this function, you first write try expectError(). Then, on the first argument, you provide the type of error that you are expecting from the function call. Then, on the second argument, you write the function call that you expect to fail.\nThe code example below demonstrates such type of unit test in Zig. Notice that, inside the function alloc_error() we are allocating 100 bytes of memory, or, an array of 100 elements, for the object ibuffer. However, in the test block, we are using the FixedBufferAllocator() allocator object, which is limited to 10 bytes of space, because the object buffer, which we provided to the allocator object, have only 10 bytes of space.\nThat is why, the alloc_error() function raises an OutOfMemory error on this case. Because this function is trying to allocate more space than the allocator object allows. So, in essence, we are testing for a specific type of error, which is OutOfMemory. If the alloc_error() function returns any other type of error, then, the expectError() function would make the entire test fail.\n\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst expectError = std.testing.expectError;\nfn alloc_error(allocator: Allocator) !void {\n var ibuffer = try allocator.alloc(u8, 100);\n defer allocator.free(ibuffer);\n ibuffer[0] = 2;\n}\n\ntest \"testing error\" {\n var buffer: [10]u8 = undefined;\n var fba = std.heap.FixedBufferAllocator.init(&buffer);\n const allocator = fba.allocator();\n try expectError(error.OutOfMemory, alloc_error(allocator));\n}\n\n1/1 filea5b059c00874.test.testing error...OKAll 1 \n tests passed.", "crumbs": [ "8  Unit tests" ] @@ -674,7 +674,7 @@ "href": "Chapters/03-unittests.html#testing-simple-equalities", "title": "8  Unit tests", "section": "8.5 Testing simple equalities", - "text": "8.5 Testing simple equalities\nIn Zig, there are some different ways you can test for an equality. You already saw that we can use expect() with the logical operator == to essentially reproduce an equality test. But we also have some other helper functions that you should know about, especially expectEqual(), expectEqualSlices() and expectEqualStrings().\nThe expectEqual() function, as the name suggests, is a classic test equality function. It receives two objects as input. The first object is the value that you expect to be in the second object. While second object is the object you have, or, the object that your application produced as result. So, with expectEqual() you are essentially testing if the values stored inside these two objects are equal or not.\nYou can see in the example below that, the test performed by expectEqual() failed. Because the objects v1 and v2 contain different values in them.\n\nconst std = @import(\"std\");\ntest \"values are equal?\" {\n const v1 = 15;\n const v2 = 18;\n try std.testing.expectEqual(v1, v2);\n}\n\n1/1 ve.test.values are equal?...\n expected 15, found 18\n FAIL (TestExpectedEqual)\nve.zig:5:5: test.values are equal? (test)\n try std.testing.expectEqual(v1, v2);\n ^\n0 passed; 0 skipped; 1 failed.\nAlthough useful, the expectEqual() function does not work with arrays. For testing if two arrays are equal, you should use the expectEqualSlices() function instead. This function have three arguments. First, you provide the data type contained in both arrays that you are trying to compare. While the second and third arguments corresponds to the array objects that you want to compare.\nIn the example below, we are using this function to test if two array objects (array1 and array2) are equal or not. Since they are in fact equal, the unit test passed with no errors.\n\nconst std = @import(\"std\");\ntest \"arrays are equal?\" {\n const array1 = [3]u32{1, 2, 3};\n const array2 = [3]u32{1, 2, 3};\n try std.testing.expectEqualSlices(\n u32, &array1, &array2\n );\n}\n\n1/1 file15377bbafb73.test.arrays are equal?...OKAl\n ll 1 tests passed.\n\n\nAt last, you might also want to use the expectEqualStrings() function. As the name suggests, you can use this function to test if two strings are equal or not. Just provide the two string objects that you want to compare, as inputs to the function.\nIf the function finds any existing differences between the two strings, then, the function will raise an error, and also, print an error message that shows the exact difference between the two string objects provided, as the example below demonstrates:\n\nconst std = @import(\"std\");\ntest \"strings are equal?\" {\n const str1 = \"hello, world!\";\n const str2 = \"Hello, world!\";\n try std.testing.expectEqualStrings(\n str1, str2\n );\n}\n\n1/1 t.test.strings are equal?... \n====== expected this output: =========\nhello, world!␃\n======== instead found this: =========\nHello, world!␃\n======================================\nFirst difference occurs on line 1:\nexpected:\nhello, world!\n^ ('\\x68')\nfound:\nHello, world!\n^ ('\\x48')", + "text": "8.5 Testing simple equalities\nIn Zig, there are some different ways you can test for an equality. You already saw that we can use expect() with the logical operator == to essentially reproduce an equality test. But we also have some other helper functions that you should know about, especially expectEqual(), expectEqualSlices() and expectEqualStrings().\nThe expectEqual() function, as the name suggests, is a classic test equality function. It receives two objects as input. The first object is the value that you expect to be in the second object. While second object is the object you have, or, the object that your application produced as result. So, with expectEqual() you are essentially testing if the values stored inside these two objects are equal or not.\nYou can see in the example below that, the test performed by expectEqual() failed. Because the objects v1 and v2 contain different values in them.\n\nconst std = @import(\"std\");\ntest \"values are equal?\" {\n const v1 = 15;\n const v2 = 18;\n try std.testing.expectEqual(v1, v2);\n}\n\n1/1 ve.test.values are equal?...\n expected 15, found 18\n FAIL (TestExpectedEqual)\nve.zig:5:5: test.values are equal? (test)\n try std.testing.expectEqual(v1, v2);\n ^\n0 passed; 0 skipped; 1 failed.\nAlthough useful, the expectEqual() function does not work with arrays. For testing if two arrays are equal, you should use the expectEqualSlices() function instead. This function have three arguments. First, you provide the data type contained in both arrays that you are trying to compare. While the second and third arguments corresponds to the array objects that you want to compare.\nIn the example below, we are using this function to test if two array objects (array1 and array2) are equal or not. Since they are in fact equal, the unit test passed with no errors.\n\nconst std = @import(\"std\");\ntest \"arrays are equal?\" {\n const array1 = [3]u32{1, 2, 3};\n const array2 = [3]u32{1, 2, 3};\n try std.testing.expectEqualSlices(\n u32, &array1, &array2\n );\n}\n\n1/1 filea5b054e42b80.test.arrays are equal?...OKAl\n ll 1 tests passed.\n\n\nAt last, you might also want to use the expectEqualStrings() function. As the name suggests, you can use this function to test if two strings are equal or not. Just provide the two string objects that you want to compare, as inputs to the function.\nIf the function finds any existing differences between the two strings, then, the function will raise an error, and also, print an error message that shows the exact difference between the two string objects provided, as the example below demonstrates:\n\nconst std = @import(\"std\");\ntest \"strings are equal?\" {\n const str1 = \"hello, world!\";\n const str2 = \"Hello, world!\";\n try std.testing.expectEqualStrings(\n str1, str2\n );\n}\n\n1/1 t.test.strings are equal?... \n====== expected this output: =========\nhello, world!␃\n======== instead found this: =========\nHello, world!␃\n======================================\nFirst difference occurs on line 1:\nexpected:\nhello, world!\n^ ('\\x68')\nfound:\nHello, world!\n^ ('\\x48')", "crumbs": [ "8  Unit tests" ] @@ -834,7 +834,7 @@ "href": "Chapters/09-error-handling.html#learning-more-about-errors-in-zig", "title": "10  Error handling and unions", "section": "", - "text": "t.zig:8:17: error: error set is discarded\nt.zig:8:17: note: consider using 'try', 'catch', or 'if'\n\n10.1.1 Returning errors from functions\nAs we described at Section 1.2.3, when we have a function that might return an error value, this function normally includes an exclamation mark (!) in its return type annotation. The presence of this exclamation mark indicates that this function might return an error value as result, and, the zig compiler forces you to always handle explicitly the case of this function returning an error value.\nTake a look at the print_name() function below. This function might return an error in the stdout.print() function call, and, as a consequence, its return type (!void) includes an exclamation mark in it.\n\nfn print_name() !void {\n const stdout = std.getStdOut().writer();\n try stdout.print(\"My name is Pedro!\", .{});\n}\n\nIn the example above, we are using the exclamation mark to tell the zig compiler that this function might return some error. But which error exactly is returned from this function? For now, we are not specifying a specific error value. We only known for now that some error value (whatever it is) might be returned.\nBut in fact, you can (if you want to) specify clearly which exact error values might be returned from this function. There are lot of examples of this in the Zig Standard Library. Take this fill() function from the http.Client module as an example. This function returns either a error value of type ReadError, or void.\n\npub fn fill(conn: *Connection) ReadError!void {\n // The body of this function ...\n}\n\nThis idea of specifying the exact error values that you expect to be returned from the function is interesting. Because they automatically become some sort of documentation of your function, and also, it allows the zig compiler to perform some extra checks over your code. Because it can check if there is any other type of error value that is being generated inside your function, and, that it is not being accounted for in this return type annotation.\nAnyway, you can list the types of errors that can be returned from the function by listing them on the left side of the exclamation mark. While the valid values stay on the right side of the exclamation mark. So the syntax format become:\n<error-value>!<valid-value>\n\n\n10.1.2 Error sets\nBut what about when we have a single function that might return different types of errors? When you have such a function, you can list all of these different types of errors that can be returned from this function, through a structure in Zig that we call of an error set.\nAn error set is a special case of an union type. It is an union that contains error values in it. Not all programming languages have a notion of an “union object”. But in summary, an union is just a set of data types. Unions are used to allow an object to have multiple data types. For example, a union of x, y and z, means that an object can be either of type x, or type y or type z.\nWe are going to talk in more depth about unions at Section 10.3. But you can write an error set by writing the keyword error before a pair of curly braces, then you list the error values that can be returned from the function inside this pair of curly braces.\nTake the resolvePath() function below as an example, which comes from the introspect.zig module of the Zig Standard Library. We can see in its return type annotation, that this function return either: 1) a valid slice of u8 values ([]u8); or, 2) one of the three different types of error values listed inside the error set (OutOfMemory, Unexpected, etc.). This is an usage example of an error set.\n\npub fn resolvePath(\n ally: mem.Allocator,\n p: []const u8,\n) error{\n OutOfMemory,\n CurrentWorkingDirectoryUnlinked,\n Unexpected,\n}![]u8 {\n // The body of the function ...\n}\n\nThis is a valid way of annotating the return value of a Zig function. But, if you navigate through the modules that composes the Zig Standard Library, you will notice that, for the majority of cases, the programmers prefer to give a descriptive name to this error set, and then, use this name (or this “label”) of the error set in the return type annotation, instead of using the error set directly.\nWe can see that in the ReadError error set that we showed earlier in the fill() function, which is defined in the http.Client module. So yes, I presented the ReadError as if it was just a standard and single error value, but in fact, it is an error set defined in the http.Client module, and therefore, it actually represents a set of different error values that might happen inside the fill() function.\nTake a look at the ReadError definition reproduced below. Notice that we are grouping all of these different error values into a single object, and then, we use this object into the return type annotation of the function. Like the fill() function that we showed earlier, or, the readvDirect() function from the same module, which is reproduced below.\n\npub const ReadError = error{\n TlsFailure,\n TlsAlert,\n ConnectionTimedOut,\n ConnectionResetByPeer,\n UnexpectedReadFailure,\n EndOfStream,\n};\n// Some lines of code\npub fn readvDirect(\n conn: *Connection,\n buffers: []std.posix.iovec\n ) ReadError!usize {\n // The body of the function ...\n}\n\nSo, an error set is just a convenient way of grouping a set of possible error values into a single object, or a single type of an error value.\n\n\n10.1.3 Casting error values\nLet’s suppose you have two different error sets, named A and B. If error set A is a superset of error set B, then, you can cast (or coerce) error values from B into error values of A.\nError sets are just a set of error values. So, if the error set A contains all error values from the error set B, then A becomes a superset of B. You could also say that the error set B is a subset of error set A.\nThe example below demonstrates this idea. Because A contains all values from B, A is a superset of B. In math notation, we would say that \\(A \\supset B\\). As a consequence, we can give an error value from B as input to the cast() function, and, implicitly cast this input into the same error value, but from the A set.\n\nconst std = @import(\"std\");\nconst A = error{\n ConnectionTimeoutError,\n DatabaseNotFound,\n OutOfMemory,\n InvalidToken,\n};\nconst B = error {\n OutOfMemory,\n};\n\nfn cast(err: B) A {\n return err;\n}\n\ntest \"coerce error value\" {\n const error_value = cast(B.OutOfMemory);\n try std.testing.expect(\n error_value == A.OutOfMemory\n );\n}\n\n1/1 file10459ffd0e21.test.coerce error value...OKA\n All 1 tests passed.", + "text": "t.zig:8:17: error: error set is discarded\nt.zig:8:17: note: consider using 'try', 'catch', or 'if'\n\n10.1.1 Returning errors from functions\nAs we described at Section 1.2.3, when we have a function that might return an error value, this function normally includes an exclamation mark (!) in its return type annotation. The presence of this exclamation mark indicates that this function might return an error value as result, and, the zig compiler forces you to always handle explicitly the case of this function returning an error value.\nTake a look at the print_name() function below. This function might return an error in the stdout.print() function call, and, as a consequence, its return type (!void) includes an exclamation mark in it.\n\nfn print_name() !void {\n const stdout = std.getStdOut().writer();\n try stdout.print(\"My name is Pedro!\", .{});\n}\n\nIn the example above, we are using the exclamation mark to tell the zig compiler that this function might return some error. But which error exactly is returned from this function? For now, we are not specifying a specific error value. We only known for now that some error value (whatever it is) might be returned.\nBut in fact, you can (if you want to) specify clearly which exact error values might be returned from this function. There are lot of examples of this in the Zig Standard Library. Take this fill() function from the http.Client module as an example. This function returns either a error value of type ReadError, or void.\n\npub fn fill(conn: *Connection) ReadError!void {\n // The body of this function ...\n}\n\nThis idea of specifying the exact error values that you expect to be returned from the function is interesting. Because they automatically become some sort of documentation of your function, and also, it allows the zig compiler to perform some extra checks over your code. Because it can check if there is any other type of error value that is being generated inside your function, and, that it is not being accounted for in this return type annotation.\nAnyway, you can list the types of errors that can be returned from the function by listing them on the left side of the exclamation mark. While the valid values stay on the right side of the exclamation mark. So the syntax format become:\n<error-value>!<valid-value>\n\n\n10.1.2 Error sets\nBut what about when we have a single function that might return different types of errors? When you have such a function, you can list all of these different types of errors that can be returned from this function, through a structure in Zig that we call of an error set.\nAn error set is a special case of an union type. It is an union that contains error values in it. Not all programming languages have a notion of an “union object”. But in summary, an union is just a set of data types. Unions are used to allow an object to have multiple data types. For example, a union of x, y and z, means that an object can be either of type x, or type y or type z.\nWe are going to talk in more depth about unions at Section 10.3. But you can write an error set by writing the keyword error before a pair of curly braces, then you list the error values that can be returned from the function inside this pair of curly braces.\nTake the resolvePath() function below as an example, which comes from the introspect.zig module of the Zig Standard Library. We can see in its return type annotation, that this function return either: 1) a valid slice of u8 values ([]u8); or, 2) one of the three different types of error values listed inside the error set (OutOfMemory, Unexpected, etc.). This is an usage example of an error set.\n\npub fn resolvePath(\n ally: mem.Allocator,\n p: []const u8,\n) error{\n OutOfMemory,\n CurrentWorkingDirectoryUnlinked,\n Unexpected,\n}![]u8 {\n // The body of the function ...\n}\n\nThis is a valid way of annotating the return value of a Zig function. But, if you navigate through the modules that composes the Zig Standard Library, you will notice that, for the majority of cases, the programmers prefer to give a descriptive name to this error set, and then, use this name (or this “label”) of the error set in the return type annotation, instead of using the error set directly.\nWe can see that in the ReadError error set that we showed earlier in the fill() function, which is defined in the http.Client module. So yes, I presented the ReadError as if it was just a standard and single error value, but in fact, it is an error set defined in the http.Client module, and therefore, it actually represents a set of different error values that might happen inside the fill() function.\nTake a look at the ReadError definition reproduced below. Notice that we are grouping all of these different error values into a single object, and then, we use this object into the return type annotation of the function. Like the fill() function that we showed earlier, or, the readvDirect() function from the same module, which is reproduced below.\n\npub const ReadError = error{\n TlsFailure,\n TlsAlert,\n ConnectionTimedOut,\n ConnectionResetByPeer,\n UnexpectedReadFailure,\n EndOfStream,\n};\n// Some lines of code\npub fn readvDirect(\n conn: *Connection,\n buffers: []std.posix.iovec\n ) ReadError!usize {\n // The body of the function ...\n}\n\nSo, an error set is just a convenient way of grouping a set of possible error values into a single object, or a single type of an error value.\n\n\n10.1.3 Casting error values\nLet’s suppose you have two different error sets, named A and B. If error set A is a superset of error set B, then, you can cast (or coerce) error values from B into error values of A.\nError sets are just a set of error values. So, if the error set A contains all error values from the error set B, then A becomes a superset of B. You could also say that the error set B is a subset of error set A.\nThe example below demonstrates this idea. Because A contains all values from B, A is a superset of B. In math notation, we would say that \\(A \\supset B\\). As a consequence, we can give an error value from B as input to the cast() function, and, implicitly cast this input into the same error value, but from the A set.\n\nconst std = @import(\"std\");\nconst A = error{\n ConnectionTimeoutError,\n DatabaseNotFound,\n OutOfMemory,\n InvalidToken,\n};\nconst B = error {\n OutOfMemory,\n};\n\nfn cast(err: B) A {\n return err;\n}\n\ntest \"coerce error value\" {\n const error_value = cast(B.OutOfMemory);\n try std.testing.expect(\n error_value == A.OutOfMemory\n );\n}\n\n1/1 filea64e1da1167c.test.coerce error value...OKA\n All 1 tests passed.", "crumbs": [ "10  Error handling and unions" ] @@ -954,7 +954,7 @@ "href": "Chapters/10-stack-project.html#sec-comptime", "title": "12  Project 3 - Building a stack data structure", "section": "", - "text": "apply comptime on a function argument.\napply comptime on an object.\napply comptime on a block of expressions.\n\n\n12.1.1 Applying over a function argument\nWhen you apply the comptime keyword on a function argument, you are saying to the zig compiler that the value assigned to that particular function argument must be known at compile-time. We explained in details at Section 3.1.1 what exactly “value known at compile-time” means, so, in case you have doubts about this idea, come back to that section.\nNow let’s think about the consequences of this idea. First of all, we are imposing a limit, or, a requirement to that particular function argument. If the programmer accidentally tries to give a value to this function argument that is not known at compile time, the zig compiler will notice this problem, and as a consequence, it will raise a compilation error saying that it cannot compile your program. Because you are providing a value that is “runtime known” to a function argument that must be “compile-time known”.\nTake a look at this very simple example below, where we define a twice() function, that simply doubles the input value named num. Notice that we use the comptime keyword before the name of the function argument. This keyword is marking the function argument num as a “comptime argument”.\nThat is a function argument whose value must be compile-time known. This is why the expression twice(5678) is valid, and no compilation errors are raised. Because the value 5678 is compile-time known, so this is the expected behaviour for this function.\n\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\ntest \"test comptime\" {\n _ = twice(5678);\n}\n\n1/1 file1105a40478a9d.test.test comptime...OKAll 1\n 1 tests passed.\n\n\nBut what if we provide a number that is not compile-time known to this function? For example, we might provide a different input value to this function depending on the target OS of our compilation process. The code example below demonstrates such case.\nBecause the value of the object n is determined at runtime, we cannot provide this object as input to the twice() function. The zig compiler will not allow it, because we marked the num argument as a “comptime argument”. That is why the zig compiler raises the compile-time error exposed below:\n\nconst builtin = @import(\"builtin\");\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\ntest \"test comptime\" {\n var n: u32 = undefined;\n if (builtin.target.os.tag == .windows) {\n n = 1234;\n } else {\n n = 5678;\n }\n _ = twice(n);\n}\n\nt.zig:12:16: error: runtime-known argument passed to comptime parameter \nComptime arguments are frequently used on functions that return some sort of generic structure. In fact, comptime is the essence (or the basis) to make generics in Zig. We are going to talk more about generics at Section 12.2.\nFor now, let’s take a look at this code example from Seguin (2024). You can see that this IntArray() function have one argument named length. This argument is marked as comptime, and receives a value of type usize as input. So the value given to this argument must be compile-time known. We can also see that this function returns an array of i64 values as output.\n\nfn IntArray(comptime length: usize) type {\n return [length]i64;\n}\n\nNow, the key component of this function is the length argument. This argument is used to determine the size of the array that is produced by the function. Let’s think about the consequences of that. If the size of the array is dependent on the value assigned to the length argument, this means that the data type of the output of the function depends on the value of this length argument.\nLet this statement sink for a bit in your mind. As I described at Section 1.2.2, Zig is a strongly-typed language, especially on function declarations. So every time we write a function in Zig, we have to annotate the data type of the value returned by the function. But how can we do that, if this data type depends on the value given to the argument of the function?\nThink about this for a second. If length is equal to 3 for example, then, the return type of the function is [3]i64. But if length is equal to 40, then, the return type becomes [40]i64. At this point the zig compiler would be confused, and raise a compilation error, saying something like this:\n\nHey! You have annotated that this function should return a [3]i64 value, but I got a [40]i64 value instead! This doesn’t look right!\n\nSo how can you solve this problem? How do we overcome this barrier? This is when the type keyword comes in. This type keyword is basically saying to the zig compiler that this function will return some data type as output, but it doesn’t know yet what exactly data type that is. We will talk more about this at Section 12.2.\n\n\n12.1.2 Applying over an expression\nWhen you apply the comptime keyword over an expression, then, it is guaranteed that the zig compiler will execute this expression at compile-time. If for some reason, this expression cannot be executed at compile-time (e.g. for example, maybe this expression depends on a value that is only known at runtime), then, the zig compiler will raise a compilation error.\nTake this example from the official documentation of Zig (Zig Software Foundation 2024). We are executing the same fibonacci() function both at runtime, and, at compile-time. The function is by default executed at runtime, but because we use the comptime keyword at the second “try expression”, this expression is executed at compile-time.\nThis might be a bit confusing for some people. Yes! When I say that this expression is executed at compile-time, I mean that this expression is compiled and executed while the zig compiler is compiling your Zig source code.\n\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci\" {\n // test fibonacci at run-time\n try expect(fibonacci(7) == 13);\n // test fibonacci at compile-time\n try comptime expect(fibonacci(7) == 13);\n}\n\n1/1 file1105a31c0f24f.test.fibonacci...OKAll 1 tes\n sts passed.\n\n\nA lot of your Zig source code might be potentially executed at compile-time, because the zig compiler can figure it out the output of some expressions. Especially if these expressions depends only at compile-time known values. We have talked about this at Section 3.1.1.\nBut when you use the comptime keyword on an expression, there is no “it might be executed at compile-time” anymore. With the comptime keyword you are ordering the zig compiler to execute this expression at compile-time. You are imposing this rule, it is guaranteed that the compiler will always execute it at compile-time. Or, at least, the compiler will try to execute it. If the compiler cannot execute the expression for whatever reason, the compiler will raise a compilation error.\n\n\n12.1.3 Applying over a block\nBlocks were described at Section 1.7. When you apply the comptime keyword over a block of expressions, you get essentially the same effect when you apply this keyword to a single expression. That is, the entire block of expressions is executed at compile-time by the zig compiler.\nIn the example below, we mark the block labeled of blk as a comptime block, and, therefore, the expressions inside this block are executed at compile-time.\n\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci in a block\" {\n const x = comptime blk: {\n const n1 = 5;\n const n2 = 2;\n const n3 = n1 + n2;\n try expect(fibonacci(n3) == 13);\n break :blk n3;\n };\n _ = x;\n}\n\n1/1 file1105a37ca2b0d.test.fibonacci in a block...\n .OKAll 1 tests passed.", + "text": "apply comptime on a function argument.\napply comptime on an object.\napply comptime on a block of expressions.\n\n\n12.1.1 Applying over a function argument\nWhen you apply the comptime keyword on a function argument, you are saying to the zig compiler that the value assigned to that particular function argument must be known at compile-time. We explained in details at Section 3.1.1 what exactly “value known at compile-time” means, so, in case you have doubts about this idea, come back to that section.\nNow let’s think about the consequences of this idea. First of all, we are imposing a limit, or, a requirement to that particular function argument. If the programmer accidentally tries to give a value to this function argument that is not known at compile time, the zig compiler will notice this problem, and as a consequence, it will raise a compilation error saying that it cannot compile your program. Because you are providing a value that is “runtime known” to a function argument that must be “compile-time known”.\nTake a look at this very simple example below, where we define a twice() function, that simply doubles the input value named num. Notice that we use the comptime keyword before the name of the function argument. This keyword is marking the function argument num as a “comptime argument”.\nThat is a function argument whose value must be compile-time known. This is why the expression twice(5678) is valid, and no compilation errors are raised. Because the value 5678 is compile-time known, so this is the expected behaviour for this function.\n\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\ntest \"test comptime\" {\n _ = twice(5678);\n}\n\n1/1 filea72d248f97f8.test.test comptime...OKAll 1 \n tests passed.\n\n\nBut what if we provide a number that is not compile-time known to this function? For example, we might provide a different input value to this function depending on the target OS of our compilation process. The code example below demonstrates such case.\nBecause the value of the object n is determined at runtime, we cannot provide this object as input to the twice() function. The zig compiler will not allow it, because we marked the num argument as a “comptime argument”. That is why the zig compiler raises the compile-time error exposed below:\n\nconst builtin = @import(\"builtin\");\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\ntest \"test comptime\" {\n var n: u32 = undefined;\n if (builtin.target.os.tag == .windows) {\n n = 1234;\n } else {\n n = 5678;\n }\n _ = twice(n);\n}\n\nt.zig:12:16: error: runtime-known argument passed to comptime parameter \nComptime arguments are frequently used on functions that return some sort of generic structure. In fact, comptime is the essence (or the basis) to make generics in Zig. We are going to talk more about generics at Section 12.2.\nFor now, let’s take a look at this code example from Seguin (2024). You can see that this IntArray() function have one argument named length. This argument is marked as comptime, and receives a value of type usize as input. So the value given to this argument must be compile-time known. We can also see that this function returns an array of i64 values as output.\n\nfn IntArray(comptime length: usize) type {\n return [length]i64;\n}\n\nNow, the key component of this function is the length argument. This argument is used to determine the size of the array that is produced by the function. Let’s think about the consequences of that. If the size of the array is dependent on the value assigned to the length argument, this means that the data type of the output of the function depends on the value of this length argument.\nLet this statement sink for a bit in your mind. As I described at Section 1.2.2, Zig is a strongly-typed language, especially on function declarations. So every time we write a function in Zig, we have to annotate the data type of the value returned by the function. But how can we do that, if this data type depends on the value given to the argument of the function?\nThink about this for a second. If length is equal to 3 for example, then, the return type of the function is [3]i64. But if length is equal to 40, then, the return type becomes [40]i64. At this point the zig compiler would be confused, and raise a compilation error, saying something like this:\n\nHey! You have annotated that this function should return a [3]i64 value, but I got a [40]i64 value instead! This doesn’t look right!\n\nSo how can you solve this problem? How do we overcome this barrier? This is when the type keyword comes in. This type keyword is basically saying to the zig compiler that this function will return some data type as output, but it doesn’t know yet what exactly data type that is. We will talk more about this at Section 12.2.\n\n\n12.1.2 Applying over an expression\nWhen you apply the comptime keyword over an expression, then, it is guaranteed that the zig compiler will execute this expression at compile-time. If for some reason, this expression cannot be executed at compile-time (e.g. for example, maybe this expression depends on a value that is only known at runtime), then, the zig compiler will raise a compilation error.\nTake this example from the official documentation of Zig (Zig Software Foundation 2024). We are executing the same fibonacci() function both at runtime, and, at compile-time. The function is by default executed at runtime, but because we use the comptime keyword at the second “try expression”, this expression is executed at compile-time.\nThis might be a bit confusing for some people. Yes! When I say that this expression is executed at compile-time, I mean that this expression is compiled and executed while the zig compiler is compiling your Zig source code.\n\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci\" {\n // test fibonacci at run-time\n try expect(fibonacci(7) == 13);\n // test fibonacci at compile-time\n try comptime expect(fibonacci(7) == 13);\n}\n\n1/1 filea72d3cf7abe2.test.fibonacci...OKAll 1 test\n ts passed.\n\n\nA lot of your Zig source code might be potentially executed at compile-time, because the zig compiler can figure it out the output of some expressions. Especially if these expressions depends only at compile-time known values. We have talked about this at Section 3.1.1.\nBut when you use the comptime keyword on an expression, there is no “it might be executed at compile-time” anymore. With the comptime keyword you are ordering the zig compiler to execute this expression at compile-time. You are imposing this rule, it is guaranteed that the compiler will always execute it at compile-time. Or, at least, the compiler will try to execute it. If the compiler cannot execute the expression for whatever reason, the compiler will raise a compilation error.\n\n\n12.1.3 Applying over a block\nBlocks were described at Section 1.7. When you apply the comptime keyword over a block of expressions, you get essentially the same effect when you apply this keyword to a single expression. That is, the entire block of expressions is executed at compile-time by the zig compiler.\nIn the example below, we mark the block labeled of blk as a comptime block, and, therefore, the expressions inside this block are executed at compile-time.\n\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci in a block\" {\n const x = comptime blk: {\n const n1 = 5;\n const n2 = 2;\n const n3 = n1 + n2;\n try expect(fibonacci(n3) == 13);\n break :blk n3;\n };\n _ = x;\n}\n\n1/1 filea72d6353d586.test.fibonacci in a block...O\n OKAll 1 tests passed.", "crumbs": [ "12  Project 3 - Building a stack data structure" ] From ffd11313d2ab5387ca44a0a66b551a8db11e09f6 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 16 Feb 2025 17:54:40 -0300 Subject: [PATCH 071/151] Change cover --- _quarto.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_quarto.yml b/_quarto.yml index b3066403..0bcbbafc 100644 --- a/_quarto.yml +++ b/_quarto.yml @@ -6,10 +6,10 @@ book: title: "Introduction to Zig" subtitle: "a project-based book" author: "Pedro Duarte Faria" - edition: 2 + edition: 1 date: "today" google-analytics: "G-6CHJXK4CEV" - cover-image: "Cover/cover-artv4.png" + cover-image: "Cover/cover-artv3.png" chapters: - index.qmd - Chapters/01-zig-weird.qmd From 7e889edc9e7922f87bfd665d53c2558151779641 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 16 Feb 2025 17:55:47 -0300 Subject: [PATCH 072/151] Recompile entire book --- docs/Cover/cover-artv3.png | Bin 0 -> 1030663 bytes docs/Cover/cover-artv4.png | Bin 577665 -> 0 bytes docs/index.html | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 docs/Cover/cover-artv3.png delete mode 100644 docs/Cover/cover-artv4.png diff --git a/docs/Cover/cover-artv3.png b/docs/Cover/cover-artv3.png new file mode 100644 index 0000000000000000000000000000000000000000..c9f280288cc1592df80159b50c7a6bca22f2131b GIT binary patch literal 1030663 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 S&EF9PQ?EUfQ0=Y2iZ%!UB*hB0?yAP98pG?l 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%0DD$AQOn=>-gMg;D5ctO$bz%f<2#2`-aGnVzpn# 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

    0aJt>2u=OxppJm%!C;IqpmuZ4hn`{!X?x1Z9WV7 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%0DAR@qKS#7Q3ov$z))c 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

    5F^t=Y}cW0yD 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

    KpsDuc1V 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 z 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%0DrybHM`B+VS! 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

    v&UT!iLA2ED7e|hoh!;|hU>MG?MkK~zd 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

    Ezz1joNGADU&mq-J6nr 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

    op6=YrFP4Hhn`*O62Wwq$y7nsR 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ℜI5&# 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≪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

    BYl2Y+bz?I$}Yhi}V+_`YmoQ4%?Ek#rD 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%0A6;pMGnD6T&ItlRx9T+8m`rhp#jR{ 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

    y zdU!@pH2PGbFmo8T3XoMvJ+&K>V-t}D%~g{zJF?!u&me{lA^Tij*3T`;bWOrOpy#yh zKI!XO0!rbhabl8%t)Ui4X0waOsh>NEfJ z?7d8`*4R!xDNdy}>}nLfc?3zMm)$dy4& z`6%V9nUuSigeLrl6LJ0$G5N?wk>U8}$Bn1Z+x0EE2WL?&V?&p1&$qXzxFK(FM*coo z@^z((i*@cX9N&%EUU{NW>vEWiv`v3)XkSCK|Mq~S`pVANj<2iMQjO6GZZnHKh;pR8 zVGc^|x5wvBS}Y3h8iRo~zUbS?M;MK}=W5N?m?`Lw(h*A^p&0~5Ofsk(qX!o~DNhEH z*ZYngczU~?p;1K!tQ(UV34Aq}EP14s>GKO1>I#j0J^ellbIs~#2Lh(AQ&rxdd{;w{ z8hMCB()_mQ-Abs5;K?8nc3XtQn*JJWF6m?rO?vW;4=$XN6)3ST9?+?cO1kx*Ma>ZB zIeZ8~&6%paCisJcD~2SF^=Z5GUw=B?B+Z2@j@5t&bNV%kb>eb}E8bKxiBr;rl>5<| zw~TZwFH*;dOuQ$iLg`aUm+4x~UKmTNgU$-R&e;-Mb*5KC<_$@Mqu>|MbnLfHo(6~Z z%EPDU=4|D~R2~r8rk^3)F`o=5Wvz;=akWu3a_1!)yK2(B3b9XaU^*)jo=nY9Ke(+Rh5#;jA1vQ6 z<~XSP9a1T)Qq_0O(MXSN_|9w{tUFpCQkh6;Sp}guSeOg$ZPe^&6Vio+`!&PfKLkwT z!$xnNj5ILj>fVSocLj8ks3Sx^5_P#re=o(?a-w7|i|CkCC$EBl&9KQ+ZHluinQACJ z-D`(>ewsuB*RmR!#)m{w!kFQZzr_&#{~iG=?5F7|{A?+$2CR$_25DkjL91}f$N&lu zEma*Bl6aF*oKziF5OJ3+8q2%9U_&c0iZN8jvw#4xa-pIHSv|`MQxmPj10IU>H!>9`Ylh%H6~bm4K$2clMo?F zV$B8UD5YTZ273YlktMV9mru*h`PN@lt^8NcHL)7E8%{b;E}4lo0`Elb^@DP?4S!O- z`HSF_%N#JtY8KM9@oif=Zwv9xE03Fail?8W7udwZMz<- zXlnEt#0UW&I4aZ*<#ComT>K)IW*~K9xuXhdkqWl_3ZB?6ceAv^xVZq`QTFfMV+E!E z!>C4kxumg{xitSC01Z_DPD6w>7M}~ejznOe__7=}R*EFQaU`oO%574O)mk_%m2-ny zI7^d_P6_9CJXUjtrWil|+F6&Y^eL&-sA4nrax)9D&Hdl8GGnmBx&+P%3SJLnVlRv&u z56dMm%8`(5L-R-E^_G5YPVbObbD~``+i2ZVp`v0SAfCr?U>%kML-s^cY`VZCO*J~btDxo91GOI(M1BN;VLp-GnXM`LQ7mrBF_3mQ|!z8 z_-XWc6iq*|6?7%-bK|VuUU*|;gYn?^wR9}%f0yz9UGjuVd z!o6Xq%dST1X~=~iW#|fqiLJZ)e#>k^$CkUmggi@#oa1z!+>fR^*FMl{yFDW2rp zoC7bzJ5JtC>W1}!X!?x^mKF*E1iXImu?vfiZMrKpr<|FHty5%?jb8i*-P}?EK7==U zpZ*#?+g3PwcSFb=5Gh8TMX+;HDF)}s{e^$X>VHsg4H~OB+CF6e5n83ig}1vH8_d0J zq5!|U7#I=?;G-a9w|nulNlLx(Se9M-j|O>N?yv=g>%Unm7+wu!$Y8zsi4!pCy$fN} ze8v!!=;|9PG*vuhh8m>?;VsAM4yKVerh}YTQI;EF?=!wRB-G2u>G`*PT8j7&sH^{v zxX8zf52jc~`kCIBX07zDb{E-*n383$s7kLdW=+=`J~igX_Cl7R4=h&~$QqJo!`sQ! zu;1fSKOeBvaAL*#?p49O@alq}C=E-cO0Fcc*E)FKFV1YK3PLubAw*E}?&6)ya-1q_ zm!`D6Q6aDh-Cj9r9Gfluz$>%GrkT1KSdn$~!8m@26;uMs{Hrrhf_8D<{fLEjp+sZ5 z-Z7&d&eYN}*wO=;zMHTWZ6#U2SgoLXYsQ0070F5^pti&n3~vq7YgIc&%V^l@1pfZ8 zXmJCeAfVaN{I*uO!;AF3;AqeXO__^vxZj_lW(b)xqM%58uMfNW}&}om$8?_FZH{yP;gFiiE+WMsWA@hi4iaF{pjx{V=D{}TFd_FHy zd|#j%`RmDVJkVPc5U0WLbz2ZAE( z-~V5JdCXxbgukkfVM#qbQ+HH-tT(kpO(4ElIWy%up$ zpOQ|?@k{YIN1$6`uIW;F00ev62Qt9dW6$yfKFu6QX1=j0&JJVEWFJ&Q0kW6#e|D6iWifg_b@r%qk_;?)-lt8^^NumS4-$FYH_rv9ms8R6inLXlC--RHC zLKTUVzU#V#I40&^ipAT4L{Lr9<=jvvk$%?ARO2_5r9LGI6q(?k;KGN7IcL$MSGkZG z7hA$RdhC2SX}v~*9pruKM+Q)jyhIQ{{DOF2|2J6Rp%~W{pH~0^r^=aciaAWIl({F}s3gP9Pg#yZmmK`dyn+^r3S8V3Wa708G=@?am0ZwkWwfAn- zY=cRylzsImEbYS}{y-v#y+++?_BX5}YhA)@Ty5ATzJiw*sn2{dp}d$dBA=DSmuL9a ze-2S9i23`+FN95$jnDDcZCJii)>^S08}O(kh;>=w;z z0}GMxM#@!z6@I~p>Qs?j-#;ep=Nhd^6E{Chjub>!;JG=`+gD40hwr_=D&vevU#r#zg=<4d&NA$sW2&MwYZaFxu!?%C?`Ll_BA2Y5#XDvZL zNPjl{08bW#Qh%hoj|L|M1=21S4OQfLrWgLxBAE2-=E2GVLeP+OF5Iv%!(mUlYueDuJXV|p4ft{{}Z(I4t2UhhGAwKKYapztilxU^hxN)C+FaB(A)nz40 zAH#aPNVH{6Cx=S52xcG?<7GaHu_Ekm&r?Hve?>A!IlVgyW3Kw!G4>FMomQY=DUQDc zFP#`~+oxySUh~cQEUJ_BU#2l4{a+nUh>Kefu&3T<)Ob%kWj#%Uh13nn!VdcNE}CQ` z;*Bl}7iMq}sZ@AZpupQO1(Y4!qmcQY$IR)DnQ;X*Oa<%WY{IE-Jh8I{o?uc`ht_nN z%(>TvD#GDrb5VtVqzY519OjDyA}>G;13X_rtavmdZ|K5lk{PskqCe$A?mg3*^3e7S zlA0v=eci1I00;EfLO;fBY~y8WCDV&fUhlfwEgckHkHmP+NnrMFWbi+zwlq!rh*@1W zC$LeXwHK zQ8z~NT)XobgOzFSScVc-p)Q?cUYZQU6Vx-8* zdC;?A9VP^qSiDWYHoq)VDH#sei>=G`nrf1wiC!-`snbgsIXG=xGQ+}bqSR(UeZ$t% z(Oj5+X2Z3O2Qa2RabDmb{8E6S&c0ed9bJy8hlV~}d5|`p^yGn(IFpvq$qaiv`{{mJ zpJ1@7{wR!9mS&TU_Gh1Y?&`8c!h8r5*8x>h?AJ2pXi()-sVwgGW&$e&{I|(Ywa!pF zq(qTe@3ZS158W4c6Bk)ic-g~$IpY7-7$6jSqWyT%`kIhsNm>Hz<*kb~1zQs@Rpwb` zcgB6<5VUHct<9K=o3CVUyL5weXZ`!ESe>deXPF0nwWI(L_BRO}68+9V{dz1dP6}mX z*p=h)fuT#oV8gN#rD*}j7Xg@y8c1VViK@s_&R#kBlv>9e#JYTK{`oKtl|xpA{Ir41 z)mCLSBO}hiDoOfkoyTCM%Yl4ZR|?JQ_NgW0h~zLc3|+}Z>x40?ljV%^D?gifXRNRN z`UZQdIL%zr-(W(qZp9cm=q*<021p7iQ>u$nKF9RJAA`C;gE@k$ZZ@oEC%-xQHS-_n z@@DC>?TvA0p5FVKpeJI?k6~!3n$m#w@NY@D{Z!SsGX(sz9vT7u^E89TQhK023~ROrld8?-=FK3T2Ivt~Y(XvL;T3dH;CteI zBs>1mXoNlE$&aOKi0UKz#1&Gv?94{8-@-=Lyh}d7MmU9`#m%)J`#uxS%C%Y;M_v*5 zE!|nem>xg{Q!JWe7T%*SqT44^+i@{3rF=7=im-kX=xWAXu_6(OfoXa^kZvxrpWwXN zK*lU89|o=_`|ed|qJ8!2i8r6s<#PV&lPfNXyim!{N-ABSW2KYHFT!+ql!a)si7X;Q z2$!9skH^vGi_(h^^E}_gixqh+aLLRUZ1j5)ew6njN(uIZBZKP-9e$RF?YcdTWXlx1 zF5s5^s&kyX1^%;O7i2Fo*ngn)>nVqzix`G|f8Gq0Nyqlk9Df*H$o8_RL(k!|2}Ozr%?OdV)BJWU7c ziK#lmX8HFC(|eMT+r>GNzLnNuP=Kjl3f}m5_PXGj4~m7w){!2OR1||XOL#i3LsOvE zx}k)u*EplA%+fi2)A24gsS-nj;rr}F$_mfS`GA#f$+Ee>r(h{$n$QEkX zmew6hJ{W8QH3C$yPSSYMVitg=u3HRfH-k!l&b!`mLe8Iega1-${r&~sa}ijCjSP?5 zEeX5q7W4HZq+B1?F`EV8V({F#Oef;}Ec4NDd2G&%htQQ7i8_a!!pbZdhE@Hb8|7c3 z%27yGJL>;*Sfps&PGx&lx@7XMJ~79^hLp+u+L!sR!~H;)$Gn?UV$30J%DMj)J` zCY3EGe>d#4JYF!$jxt%3rn;$e3&zflzP_oERK2E(DZIs6GeC6>u($&DfddsR! z6g2;coX;}<*LXVQ{YwgXmp>8T7g(gT0yP5f1H8fgAH=rjdo&CFjeYw7yXVb`vxl{N zs-o$yZ-7;Q4AubBj#@A(@zArRJ{m?YeInEs)!drN*yecRtEwiYPi41G@VIWZ_(QDi<23nnwdGpbHC`Q{M5 zc4znO85H^BTt;!D_xWLRQt509auz4eqOwgXfN>5Z5XB6TZUWlW?73Vir&gO8?wCC~^}q{J0=6BXvttAmg*FggP6_`Y(*PxCpY)oW@w)PS?Y z|KrYr0PbwVTnxx3@4kPHrzr2SnmM$8c1YJV1r79@KSkal_`*DW{UQm9XPB_OZ2On@D7TNEoyjbM-Y^8;XHQ?vj^3mNy?A6e`u}hg(f{ab zT1o{x@g~aSi!z2BIhD}mcS42sH=oHnAFp-hk8aL*Uj#90Bm7B?gadN;g`k#PgLA$c zlB0XVLY^I=NhpIfg|SsTz~&+~>+Z-J8w46-H2qJ?GRoH7U+0`=Ev7luPZRfCJ$AEC zoGAOA-|EibIJsH(%AEj&awmzYr>QCq-E;8t@5P`aP^5-J@{itJJ zN&MYb6xYuFJTwmv+O1}ZEw2U!PZEURJ~5pgzh-d|+?^FJl@Na)qQ%wQ(;}kR8dm?e$TAk|Pn&-xoOG$cc&7AaE-X)Q*CsJ2& zU+^?f5Rr3b!ZmZhJ$!n*Sz%Y)o?FgY24am$s~i@l-I0j6iVff-xoOrkF%RNno97lD zEzP&2qPYy5Hm4f5KTNJQNLs#k_tgKgaN zt5RutoelJg|Isr7Kq=PlzXaVtJNt-TeM8o~MZe>n1Wa;&7m&iTePxvb++>jr0t+g3 z?ro626bjzPzKm6d4H=J|wQ=il06&_?9;HVtSI`*FR0y^N;|W%&7Bib*e>lNytzA

    )hkWjfdir(1AZjo$AcPFvPk6w;kMYENq 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

    >lvsl_vIQuKFeEd`GK+g-3Q^x5E! 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 to Zig

    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

    -

    Welcome

    +

    Welcome

    Welcome! This is the initial page for the “Open Access” HTML version of the book “Introduction to Zig: a project-based book”, written by Pedro Duarte Faria. This is an open book that provides an introduction to the Zig programming language, which is a new general-purpose, and low-level language for building robust and optimal software.

    Support the project!

    From c91b691c85651d17d40f43aaf1e5b49c4264e04a Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 16 Feb 2025 18:01:24 -0300 Subject: [PATCH 073/151] Update index --- _freeze/index/execute-results/html.json | 4 ++-- docs/index.html | 8 ++++---- docs/search.json | 2 +- index.qmd | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/_freeze/index/execute-results/html.json b/_freeze/index/execute-results/html.json index b3df0c6d..df53cb9c 100644 --- a/_freeze/index/execute-results/html.json +++ b/_freeze/index/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "9747d27d8e8f5fadf3da395f3899d9d8", + "hash": "b59fabe5a5ffda4f02945f654dba67de", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy\nof the book, either at Amazon, or at Leanpub:\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2025,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {February},\n edition = {2},\n year = {2025},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion)\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy\nof the book, either at Amazon, or at Leanpub:\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion)\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/docs/index.html b/docs/index.html index 3fe26f1d..6012b60d 100644 --- a/docs/index.html +++ b/docs/index.html @@ -434,13 +434,13 @@

    Book

    Book citation

    You can use the following BibTex entry to cite this book:

    -
    @book{pedro2025,
    +
    @book{pedro2024,
         author = {Pedro Duarte Faria},
         title = {Introduction to Zig},
         subtitle = {a project-based book},
    -    month = {February},
    -    edition = {2},
    -    year = {2025},
    +    month = {October},
    +    edition = {1},
    +    year = {2024},
         address = {Belo Horizonte},
         url = {https://github.com/pedropark99/zig-book}
     }
    diff --git a/docs/search.json b/docs/search.json index 1d2f1f9f..0a1da144 100644 --- a/docs/search.json +++ b/docs/search.json @@ -64,7 +64,7 @@ "href": "index.html#book-citation", "title": "Introduction to Zig", "section": "Book citation", - "text": "Book citation\nYou can use the following BibTex entry to cite this book:\n@book{pedro2025,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {February},\n edition = {2},\n year = {2025},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}", + "text": "Book citation\nYou can use the following BibTex entry to cite this book:\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}", "crumbs": [ "Welcome" ] diff --git a/index.qmd b/index.qmd index cbe7ef75..f7e81492 100644 --- a/index.qmd +++ b/index.qmd @@ -143,13 +143,13 @@ source("./Scripts/zig-quarto-versions.R") You can use the following BibTex entry to cite this book: ``` -@book{pedro2025, +@book{pedro2024, author = {Pedro Duarte Faria}, title = {Introduction to Zig}, subtitle = {a project-based book}, - month = {February}, - edition = {2}, - year = {2025}, + month = {October}, + edition = {1}, + year = {2024}, address = {Belo Horizonte}, url = {https://github.com/pedropark99/zig-book} } From a18e77edba6d5c4e2f721a878795e4c63b5dd432 Mon Sep 17 00:00:00 2001 From: Lyall Jonathan Di Trapani Date: Mon, 17 Feb 2025 14:08:59 -0500 Subject: [PATCH 074/151] Chapter 03-unittests grammer corrections - Subject is you, so verb is are not is. - Also, it does, not it do. --- Chapters/03-unittests.qmd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Chapters/03-unittests.qmd b/Chapters/03-unittests.qmd index 56cfb051..72f8efd6 100644 --- a/Chapters/03-unittests.qmd +++ b/Chapters/03-unittests.qmd @@ -109,8 +109,8 @@ that help us, programmers, to avoid (but also detect) memory problems, such as memory leaks and double-frees. The `defer` keyword is especially helpful in this regard. -When developing your source code, you, the programmer, is responsible for making -sure that your code do not produce such problems. However, +When developing your source code, you, the programmer, are responsible for making +sure that your code does not produce such problems. However, you can also use a special type of an allocator object in Zig that is capable of automatically detecting such problems for you. This is the `std.testing.allocator` object. From 8b90851de221b72cedef68a0ea019d4ff3a2177d Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Wed, 19 Feb 2025 18:05:03 -0400 Subject: [PATCH 075/151] fix: typos and improve flow --- Chapters/10-stack-project.qmd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Chapters/10-stack-project.qmd b/Chapters/10-stack-project.qmd index ada7535d..ed37847f 100644 --- a/Chapters/10-stack-project.qmd +++ b/Chapters/10-stack-project.qmd @@ -37,8 +37,8 @@ how generics work in Zig. One of the key features of Zig is `comptime`. This keyword introduces a whole new concept and paradigm, that is tightly connected with the compilation process. -At @sec-compile-time we have described the importance and the role that "compile-time versus runtime" -plays into Zig. At that section, we learned that the rules applied to a value/object change +In @sec-compile-time we have described the importance and the role that "compile-time versus runtime" +plays into Zig. In that section, we learned that the rules applied to a value/object changes a lot depending on whether this value is known at compile-time, or just at runtime. The `comptime` keyword is strongly related to these two spaces in time (compile-time and runtime). @@ -59,8 +59,8 @@ There are three ways in which you can apply the `comptime` keyword, which are: When you apply the `comptime` keyword on a function argument, you are saying to the `zig` compiler that the value assigned to that particular function argument must be known at compile-time. -We explained in details at @sec-compile-time what exactly "value known at compile-time" means, so, -in case you have doubts about this idea, come back to that section. +We explained in detail in @sec-compile-time what exactly "value known at compile-time" means. So, +if you have any doubts about this idea, refer back to that section. Now let's think about the consequences of this idea. First of all, we are imposing a limit, or, a requirement to that particular function argument. If the programmer accidentally tries to give a value to this From 203528b3036f120f3bb9ee28ad7e2e5db429d0f0 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Wed, 19 Feb 2025 18:19:01 -0400 Subject: [PATCH 076/151] fix remaining typos in 12.1 --- Chapters/10-stack-project.qmd | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Chapters/10-stack-project.qmd b/Chapters/10-stack-project.qmd index ed37847f..31521cb5 100644 --- a/Chapters/10-stack-project.qmd +++ b/Chapters/10-stack-project.qmd @@ -119,10 +119,10 @@ t.zig:12:16: error: runtime-known argument passed to comptime parameter Comptime arguments are frequently used on functions that return some sort of generic structure. In fact, `comptime` is the essence (or the basis) to make generics in Zig. -We are going to talk more about generics at @sec-generics. +We are going to talk more about generics in @sec-generics. For now, let's take a look at this code example from @karlseguin_generics. You -can see that this `IntArray()` function have one argument named `length`. +can see that this `IntArray()` function has one argument named `length`. This argument is marked as comptime, and receives a value of type `usize` as input. So the value given to this argument must be compile-time known. We can also see that this function returns an array of `i64` values as output. @@ -140,7 +140,7 @@ think about the consequences of that. If the size of the array is dependent on the value assigned to the `length` argument, this means that the data type of the output of the function depends on the value of this `length` argument. -Let this statement sink for a bit in your mind. As I described at @sec-root-file, +Let this statement sink for a bit in your mind. As I described in @sec-root-file, Zig is a strongly-typed language, especially on function declarations. So every time we write a function in Zig, we have to annotate the data type of the value returned by the function. But how can we do that, if this data type @@ -169,8 +169,8 @@ will raise a compilation error. Take this example from the official documentation of Zig [@zigdocs]. We are executing the same `fibonacci()` function both at runtime, and, at compile-time. -The function is by default executed at runtime, but because we use the `comptime` -keyword at the second "try expression", this expression is executed at compile-time. +The function is executed by default at runtime, but because we use the `comptime` +keyword in the second "try expression", this expression is executed at compile-time. This might be a bit confusing for some people. Yes! When I say that this expression is executed at compile-time, I mean that this expression is compiled and executed @@ -195,9 +195,9 @@ test "fibonacci" { ``` A lot of your Zig source code might be potentially executed at compile-time, -because the `zig` compiler can figure it out the output of some expressions. -Especially if these expressions depends only at compile-time known values. -We have talked about this at @sec-compile-time. +because the `zig` compiler can figure the output of some expressions. +Especially if these expressions depend only on compile-time known values. +We have talked about this in @sec-compile-time. But when you use the `comptime` keyword on an expression, there is no "it might be executed at compile-time" anymore. With the `comptime` keyword you are ordering the `zig` compiler @@ -209,8 +209,8 @@ the compiler will raise a compilation error. ### Applying over a block -Blocks were described at @sec-blocks. When you apply the `comptime` keyword over a -block of expressions, you get essentially the same effect when you apply this keyword to +Blocks were described in @sec-blocks. When you apply the `comptime` keyword to a +block of expressions, you get essentially the same effect as when you apply this keyword to a single expression. That is, the entire block of expressions is executed at compile-time by the `zig` compiler. From ac187274880f7a6e7f46080582a89681790dd54f Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Wed, 19 Feb 2025 19:51:53 -0400 Subject: [PATCH 077/151] fix typos and improve flow --- Chapters/10-stack-project.qmd | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Chapters/10-stack-project.qmd b/Chapters/10-stack-project.qmd index 31521cb5..5640b5e0 100644 --- a/Chapters/10-stack-project.qmd +++ b/Chapters/10-stack-project.qmd @@ -266,13 +266,13 @@ input to a piece of code. Take the `max()` function exposed below as a first example. This function is essentially a "generic function". In this function, we have a comptime function argument named `T`. -Notice that this `T` argument have a data type of `type`. Weird right? This `type` keyword is the +Notice that this `T` argument has a data type of `type`. Weird right? This `type` keyword is the "father of all types", or, "the type of types" in Zig. Because we have used this `type` keyword in the `T` argument, we are telling the `zig` compiler that this `T` argument will receive some data type as input. Also notice the use of the `comptime` keyword in this argument. -As I described at @sec-comptime, every time you use this keyword in a function argument, +As I described in @sec-comptime, every time you use this keyword in a function argument, this means that the value of this argument must be known at compile-time. This makes sense, right? Because there is no data type that is not known at compile-time. @@ -300,7 +300,7 @@ As a result, we have a generic function that works with different data types. For example, I can provide `u8` values to this `max()` function, and it will work as expected. But if I provide `f64` values instead, it will also work as expected. Without a generic function, I would have to write a different `max()` function -for each one of the data types that I wanted to use. +for each data type I wanted to use. This generic function provides a very useful shortcut for us. ```{zig} @@ -333,7 +333,7 @@ You just say which is the data type of the values that are going to be stored in structure, and they just work as expected. A generic data structure in Zig is how you replicate a generic class from Java, -or, a class template from C++. But you may quest yourself: how do we build a +or, a class template from C++. But you may ask yourself: how do we build a generic data structure in Zig? The basic idea is to write a generic function that creates the data structure definition @@ -342,7 +342,7 @@ The generic function outputs the `struct` definition that defines this data stru specific data type. To create such function, we need to add a comptime argument to this function that receives a data type -as input. We already learned how to do this at the previous section (@sec-generic-fun). +as input. We already learned how to do this in the previous section (@sec-generic-fun). I think the best way to demonstrate how to create a generic data structure is to actually write one. This where we go into our next small project in this book. This one is a very small project, which is to write a generic stack data structure. From 8fd3dd9ae1b231f2420ed5f69c500fb06a41215f Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Wed, 19 Feb 2025 20:17:35 -0400 Subject: [PATCH 078/151] fix remaining typos and improve flow --- Chapters/10-stack-project.qmd | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Chapters/10-stack-project.qmd b/Chapters/10-stack-project.qmd index 5640b5e0..f3c27502 100644 --- a/Chapters/10-stack-project.qmd +++ b/Chapters/10-stack-project.qmd @@ -390,7 +390,7 @@ we want. First, we need to decide how the values will be stored inside the stack. There are multiple ways to implement the storage behind a stack structure. Some people prefer to use a doubly linked list, -some others prefer to use a dynamic array, etc. In this example we are going to use an array behind the hood, +others prefer to use a dynamic array, etc. In this example we are going to use an array behind the hood, to store the values in the stack, which is the `items` data member of our `Stack` struct definition. Also notice in our `Stack` struct that we have three other data members: `capacity`, `length` and `allocator`. @@ -438,7 +438,7 @@ responsible for adding a new value to the stack. So how can we add a new value to the `Stack` object that we have? The `push()` function exposed below is a possible answer to this question. -Remember from what we discussed at @sec-what-stack that values are always added to the top of the stack. +Remember from what we discussed in @sec-what-stack that values are always added to the top of the stack. This means that this `push()` function must always find the element in the underlying array that currently represents the top position of the stack, and then, add the input value there. @@ -558,14 +558,14 @@ pub fn deinit(self: *Stack) void { ## Making it generic Now that we have implemented the basic skeleton of our stack data structure, -we can now focus on discussing how can we make it generic. How can we make -this basic skeleton to work not only with `u32` values, but also, with any other +we can now focus on discussing how we can make it generic. How can we make +this basic skeleton to work not only with `u32` values, but also with any other data type we want? For example, we might need to create a stack object to store `User` values -in it. How can we make this possible? The answer lies on the use of generics +in it. How can we make this possible? The answer lies in the use of generics and `comptime`. -As I described at @sec-generic-struct, the basic idea is to write a generic +As I described in @sec-generic-struct, the basic idea is to write a generic function that returns a struct definition as output. In theory, we do not need much to transform our `Stack` struct into a generic data structure. All that we need to do is to transform the underlying array @@ -573,7 +573,7 @@ of the stack into a generic array. In other words, this underlying array needs to be a "chameleon". It needs to adapt, and transform it into an array of any data type that we want. For example, if we need to create -a stack that will store `u8` values, then, this underlying array needs to be +a stack that will store `u8` values, then this underlying array needs to be a `u8` array (i.e. `[]u8`). But if we need to store `User` values instead, then, this array needs to be a `User` array (i.e. `[]User`). Etc. @@ -585,7 +585,7 @@ we pass the `User` data type to this generic function, and it will create for us the struct definition that describes a `Stack` object that can store `User` values in it. Look at the code example below. I have omitted some parts of the `Stack` struct definition -for brevity reasons. However, if a specific part of our `Stack` struct is not exposed here +for brevity. However, if a specific part of our `Stack` struct is not exposed here in this example, then it is because this part did not change from the previous example. It remains the same. @@ -677,7 +677,7 @@ with the data type that you provided as input. ## Conclusion -The full source code of the stack structure discussed in this chapter is freely available at the official +The full source code of the stack structure discussed in this chapter is freely available in the official repository of this book. Just checkout the [`stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/stack.zig)[^zig-stack] for the `u32` version of our stack, and the [`generic_stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/generic_stack.zig)[^zig-stack2] From 6421a9625ac0caf372b08f5be9b9aaeb7d39590b Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Wed, 19 Feb 2025 20:18:13 -0400 Subject: [PATCH 079/151] change 'at' to 'in' --- Chapters/10-stack-project.qmd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Chapters/10-stack-project.qmd b/Chapters/10-stack-project.qmd index f3c27502..40e95dbf 100644 --- a/Chapters/10-stack-project.qmd +++ b/Chapters/10-stack-project.qmd @@ -156,7 +156,7 @@ and raise a compilation error, saying something like this: So how can you solve this problem? How do we overcome this barrier? This is when the `type` keyword comes in. This `type` keyword is basically saying to the `zig` compiler that this function will return some data type as output, but it doesn't know yet -what exactly data type that is. We will talk more about this at @sec-generics. +what exactly data type that is. We will talk more about this in @sec-generics. @@ -246,7 +246,7 @@ test "fibonacci in a block" { First of all, what is a generic? Generic is the idea to allow a type (`f64`, `u8`, `u32`, `bool`, and also, user-defined types, like the `User` struct -that we defined at @sec-structs-and-oop) to be a parameter to methods, classes and +that we defined in @sec-structs-and-oop) to be a parameter to methods, classes and interfaces [@geeks_generics]. In other words, a "generic" is a class (or a method) that can work with multiple data types. From a36e065eb4d99b3a8ae8cec60987aba4577440f7 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Thu, 20 Feb 2025 11:32:45 -0400 Subject: [PATCH 080/151] fix: typos in 17.1 --- Chapters/15-vectors.qmd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Chapters/15-vectors.qmd b/Chapters/15-vectors.qmd index 94019c19..c5c490f9 100644 --- a/Chapters/15-vectors.qmd +++ b/Chapters/15-vectors.qmd @@ -32,10 +32,10 @@ was only used on "supercomputer models". Most modern CPU models (from AMD, Intel, etc.) these days (either in a desktop or in a notebook model) have support for SIMD operations. So, if you have a very old CPU model installed in your -computer, then, is possible that you have no support for SIMD operations in your computer. +computer, then, it is possible that you have no support for SIMD operations in your computer. -Why people have started using SIMD on their software? The answer is performance. -But what SIMD precisely do to achieve better performance? Well, in essence, SIMD operations are a different +Why have people started using SIMD in their software? The answer is performance. +But what does SIMD precisely do to achieve better performance? Well, in essence, SIMD operations are a different strategy to get parallel computing in your program, and therefore, make faster calculations. The basic idea behind SIMD is to have a single instruction that operates over multiple data From d76969afd70b6bdde283fc0092cec5fcb3f5aafd Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Thu, 20 Feb 2025 13:04:03 -0400 Subject: [PATCH 081/151] fix typos in 12.2 --- Chapters/15-vectors.qmd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Chapters/15-vectors.qmd b/Chapters/15-vectors.qmd index c5c490f9..c22c745b 100644 --- a/Chapters/15-vectors.qmd +++ b/Chapters/15-vectors.qmd @@ -61,7 +61,7 @@ always operate over a special type of object, which are called "vectors". So, in order to use SIMD, you have to create a "vector object". A vector object is usually a fixed-sized block of 128 bits (16 bytes). -As consequence, most vectors that you find in the wild are essentially arrays that contains 2 values of 8 bytes each, +As a consequence, most vectors that you find in the wild are essentially arrays that contains 2 values of 8 bytes each, or, 4 values of 4 bytes each, or, 8 values of 2 bytes each, etc. However, different CPU models may have different extensions (or, "implementations") of SIMD, which may offer more types of vector objects that are bigger in size (256 bits or 512 bits) @@ -154,12 +154,12 @@ try stdout.print("{any}\n", .{v1}); ### Careful with vectors that are too big -As I described at @sec-what-vectors, each vector object is usually a small block of 128, 256 or 512 bits. +As I described in @sec-what-vectors, each vector object is usually a small block of 128, 256 or 512 bits. This means that a vector object is usually small in size, and when you try to go in the opposite direction, by creating a vector object that is very big in size (i.e. sizes that are close to $2^{20}$), you usually end up with crashes and loud errors from the compiler. -For example, if you try to compile the program below, you will likely face segmentation faults, or, LLVM errors during +For example, if you try to compile the program below, you will likely face segmentation faults, or LLVM errors during the build process. Just be careful to not create vector objects that are too big in size. ```{zig} From f4e9a8e66c0d175e961a00a13654c838080725ac Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Thu, 20 Feb 2025 13:22:46 -0400 Subject: [PATCH 082/151] fix typos and improve flow in 16.1 --- Chapters/14-threads.qmd | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 8ddbc00a..001ecf7a 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -36,31 +36,31 @@ parallelism. And when we don't have parallelism, the commands are executed seque only one command is executed at a time, one after another. By creating multiple threads inside our program, we start to execute multiple commands at the same time. -Programs that create multiple threads are very common on the wild. Because many different types +Programs that create multiple threads are very common in the wild. Because many different types of applications are well suited for parallelism. Good examples are video and photo-editing applications (e.g. Adobe Photoshop or DaVinci Resolve), games (e.g. The Witcher 3), and also web browsers (e.g. Google Chrome, Firefox, Microsoft Edge, etc). For example, in web browsers, threads are normally used to implement tabs. The tabs in a web browsers usually run as separate threads in the main process of -the web browser. That is, each new tab that you open in your web browser, +the web browser. That is, each new tab that you open in your web browser usually runs on a separate thread of execution. By running each tab in a separate thread, we allow all open tabs in the browser to run at the same time, -and independently from each other. For example, you might have YouTube, or Spotify, currently opened in -a tab, and you are listening to some podcast in that tab, while, at the same time, -you are working in another tab, writing an essay on Google Docs. Even if you are not looking +and independently from each other. For example, you might have YouTube or Spotify currently open in +a tab, and you are listening to some podcast in that tab while at the same time +working in another tab, writing an essay on Google Docs. Even if you are not looking into the YouTube tab, you can still hear the podcast only because this YouTube tab is running in parallel with the other tab where Google Docs is running. Without threads, the other alternative would be to run each tab as a completely separate -process in your computer. But that would be a bad choice, because just a few tabs would already consume -too much power and resources from your computer. In other words, is very expensive to create a completely new process, +process in your computer. But that would be a bad choice because just a few tabs would already consume +too much power and resources from your computer. In other words, it is very expensive to create a completely new process, compared to creating a new thread of execution. Also, the chances of you experiencing lag and overhead while using the browser would be significant. Threads are faster to create, and they also consume much, much less resources from the computer, especially because they share some resources with the main process. -Therefore, is the use of threads in modern web browsers that allows you to hear the podcast +Therefore, it is the use of threads in modern web browsers that allow you to hear the podcast at the same time while you are writing something on Google Docs. Without threads, a web browser would probably be limited to just one single tab. @@ -78,9 +78,9 @@ the following steps: If you think about the bullet points above, you will notice that one big moment of waiting time is present in this whole process, which is while the food is being cooked inside the kitchen. While the food is being prepped, both the waiter and the client -itself are waiting for the food to be ready and delivered. +themselves are waiting for the food to be ready and delivered. -If we write a program to represent this restaurant, more specifically, a single-threaded program, then, +If we write a program to represent this restaurant, more specifically, a single-threaded program, then this program would be very inefficient. Because the program would stay in idle, waiting for a considerable amount of time on the "check if food is ready" step. Consider the code snippet exposed below that could potentially represent such program. From dfcd1036567af8993bac3366b049d68ddbaf0d85 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Thu, 20 Feb 2025 13:31:00 -0400 Subject: [PATCH 083/151] fix: change 'have' to 'has' in 16.2 --- Chapters/14-threads.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 001ecf7a..ee9c6634 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -186,7 +186,7 @@ is on the heap, then, the other threads can potentially access this object. Therefore, objects that are stored in the stack are local to the thread where they were created. But objects that are stored on the heap are potentially accessible to other threads. All of this means that, -each thread have its own separate stack frame, but, at the same time, all threads share +each thread has its own separate stack frame, but, at the same time, all threads share the same heap, the same standard file descriptors (which means that they share the same `stdout`, `stdin`, `stderr`), and the same global data section in the program. From bc381754ff9b16076a4b561aec67e94e6c7fff06 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Thu, 20 Feb 2025 13:34:18 -0400 Subject: [PATCH 084/151] remove extra commas --- Chapters/14-threads.qmd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index ee9c6634..a2de242f 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -194,9 +194,9 @@ and the same global data section in the program. ## Creating a thread -We create new threads in Zig, by first, importing the `Thread` struct into -our current Zig module, and then, calling the `spawn()` method of this struct, -which creates (or, "spawns") a new thread of execution from our current process. +We create new threads in Zig by first importing the `Thread` struct into +our current Zig module and then calling the `spawn()` method of this struct, +which creates (or "spawns") a new thread of execution from our current process. This method have three arguments, which are, respectively: 1. a `SpawnConfig` object, which contains configurations for the spawn process. From fe9e6505f4a0d5b3959ec8a1904e7037ad41b86c Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Thu, 20 Feb 2025 14:05:15 -0400 Subject: [PATCH 085/151] fix typos --- Chapters/14-threads.qmd | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index a2de242f..4a4e011c 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -197,17 +197,17 @@ and the same global data section in the program. We create new threads in Zig by first importing the `Thread` struct into our current Zig module and then calling the `spawn()` method of this struct, which creates (or "spawns") a new thread of execution from our current process. -This method have three arguments, which are, respectively: +This method has three arguments, which are, respectively: 1. a `SpawnConfig` object, which contains configurations for the spawn process. -1. the name of the function that is going to be executed (or, that is going to be "called") inside this new thread. +1. the name of the function that is going to be executed (or that is going to be "called") inside this new thread. 1. a list of arguments (or inputs) to be passed to the function provided in the second argument. -With these three arguments, you can control how the thread get's created, and also, specify which +With these three arguments, you can control how the thread gets created, and also, specify which work (or "tasks") will be performed inside this new thread. A thread is just a separate context of execution, -and we usually create new threads in our code, because we want to perform some work inside this -new context of execution. And we specify which exact work, or, which exact steps that are going to be -performed inside this context, by providing the name of a function on the second argument of the `spawn()` method. +and we usually create new threads in our code because we want to perform some work inside this +new context of execution. And we specify which exact work, or which exact steps that are going to be +performed inside this context by providing the name of a function as the second argument of the `spawn()` method. Thus, when this new thread get's created, this function that you provided as input to the `spawn()` method get's called, or, get's executed inside this new thread. You can control the From 5c9555c421a98bb922eeafc329319fb90845b5e3 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Thu, 20 Feb 2025 14:39:57 -0400 Subject: [PATCH 086/151] fix typos and improve flow in 16.3 --- Chapters/14-threads.qmd | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 4a4e011c..b2c19155 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -209,9 +209,9 @@ and we usually create new threads in our code because we want to perform some wo new context of execution. And we specify which exact work, or which exact steps that are going to be performed inside this context by providing the name of a function as the second argument of the `spawn()` method. -Thus, when this new thread get's created, this function that you provided as input to the `spawn()` -method get's called, or, get's executed inside this new thread. You can control the -arguments, or, the inputs that are passed to this function when it get's called, by providing +Thus, when this new thread gets created, this function that you provided as input to the `spawn()` +method gets called, or gets executed inside this new thread. You can control the +arguments, or the inputs that are passed to this function when it gets called by providing a list of arguments (or a list of inputs) on the third argument of the `spawn()` method. These arguments are passed to the function in the same order that they are provided to `spawn()`. @@ -219,13 +219,13 @@ provided to `spawn()`. Furthermore, the `SpawnConfig` is a struct object with only two possible fields, or, two possible members, that you can set to tailor the spawn behaviour. These fields are: -- `stack_size`: you can provide an `usize` value to specify the size (in bytes) of the thread's stack frame. By default, this value is: $16 \times 1024 \times 1024$. +- `stack_size`: you can provide a `usize` value to specify the size (in bytes) of the thread's stack frame. By default, this value is: $16 \times 1024 \times 1024$. - `allocator`: you can provide an allocator object to be used when allocating memory for the thread. -To use one of these two fields (or, "configs") you just have to create a new object of type `SpawnConfig`, +To use one of these two fields (or "configs"), you just have to create a new object of type `SpawnConfig`, and provide this object as input to the `spawn()` method. But, if you are not interested in using one of these configs, and you are ok with using just the defaults, you can just provide an anonymous -struct literal (`.{}`) in the place of this `SpawnConfig` argument. +struct literal (`.{}`) in place of this `SpawnConfig` argument. As our first, and very simple example, consider the code exposed below. Inside the same program, you can create multiple threads of execution if you want to. @@ -234,8 +234,8 @@ we call `spawn()` only once. Also, notice in this example that we are executing the function `do_some_work()` inside the new thread. Since this function receives no inputs, because it has -no arguments, we have passed an empty list in this instance, or, more precisely, -an empty and anonymous struct (`.{}`) in the third argument of `spawn()`. +no arguments, we have passed an empty list in this instance, or more precisely, +an empty, anonymous struct (`.{}`) in the third argument of `spawn()`. ```{zig} @@ -264,13 +264,13 @@ But, if the new thread is successfully created, the `spawn()` method returns a h object (which is just an object of type `Thread`) to this new thread. You can use this handler object to effectively control all aspects of the thread. -When the thread get's created, the function that you provided as input to `spawn()` -get's invoked (i.e. get's called) to start the execution on this new thread. -In other words, everytime you call `spawn()`, not only a new thread get's created, -but also, the "start work button" of this thread get's automatically pressed. -So the work being performed in this thread starts at the moment that the thread is created. +When the thread gets created, the function that you provided as input to `spawn()` +gets invoked (i.e. gets called) to start the execution on this new thread. +In other words, every time you call `spawn()`, not only is a new thread created, +but the "start work button" of this thread is also automatically pressed. +So the work being performed in this thread starts as soon as the thread is created. This is similar to how `pthread_create()` from the `pthreads` library in C works, -which also starts the execution at the moment that the thread get's created. +which also starts the execution as soon as the thread is created. ## Returning from a thread From d3d5fbb0b3e8827dc0f9c3858403019ab698449d Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Thu, 20 Feb 2025 15:04:38 -0400 Subject: [PATCH 087/151] fix typos and improve flow in 16.4.1 --- Chapters/14-threads.qmd | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index b2c19155..2e42ae05 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -275,15 +275,15 @@ which also starts the execution as soon as the thread is created. ## Returning from a thread -We have learned on the previous section that the execution of the thread starts at the moment -that the thread get's created. Now, we will learn how to "join" or "detach" a thread in Zig. +We have learned in the previous section that the execution of the thread starts as soon as +the thread is created. Now, we will learn how to "join" or "detach" a thread in Zig. "Join" and "detach" are operations that control how the thread returns to -the main thread, or, to the main process in our program. +the main thread, or to the main process in our program. We perform these operations by using the methods `join()` and `detach()` from the thread handler object. Every thread that you create can be marked as either *joinable* or *detached* [@linux_pthread_create]. You can turn a thread into a *detached* thread by calling the `detach()` method -from the thread handler object. But if you call the `join()` method instead, then, this thread +from the thread handler object. But if you call the `join()` method instead, then this thread becomes a *joinable* thread. A thread cannot be both *joinable* and *detached*. Which in general means @@ -291,7 +291,7 @@ that you cannot call both `join()` and `detach()` on the same thread. But a thread must be one of the two, meaning that, you should always call either `join()` or `detach()` over a thread. If you don't call one of these two methods over your thread, you introduce undefined behaviour into your program, -which is described at @sec-not-call-join-detach. +which is described in @sec-not-call-join-detach. Now, let's describe what each of these two methods do to your thread. @@ -299,13 +299,13 @@ Now, let's describe what each of these two methods do to your thread. ### Joining a thread When you join a thread, you are essentially saying: "Hey! Could you please wait for the thread to finish, -before you continue with your execution?". For example, if we comeback to our first and simpliest example -of a thread in Zig, in that example we have created a single thread inside the `main()` function of our program, -and just called `join()` over this thread at the end. This section of the code example is reproduced below. +before you continue with your execution?". For example, if we come back to our first and simplest example +of a thread in Zig, we created a single thread inside the `main()` function of our program +and just called `join()` on this thread at the end. This section of the code example is reproduced below. Because we are joining this new thread inside the `main()`'s scope, it means that the execution of the `main()` function is temporarily stopped, to wait for the execution of the thread -to finish. That is, the execution of `main()` stops temporarily at the line where `join()` get's called, +to finish. That is, the execution of `main()` stops temporarily at the line where `join()` gets called, and it will continue only after the thread has finished its tasks. ```{zig} @@ -332,11 +332,11 @@ we wait for two whole seconds, then, at last, we join the second thread. The idea behind this example is that the last `join()` call is executed only after the first thread finishes its task (i.e. the first `join()` call), -and also, after the two seconds of delay. If you compile and run this +and the two-second delay. If you compile and run this example, you will notice that most messages are quickly printed to `stdout`, i.e. they appear almost instantly on your screen. However, the last message ("Joining thread 2") takes around 2 seconds to appear -in the screen. +on the screen. ```{zig} @@ -369,7 +369,7 @@ Joining thread 2 This demonstrates that both threads finish their work (i.e. printing the IDs) very fast, before the two seconds of delay end. Because of that, the last `join()` call returns pretty much instantly. Because when this last `join()` call happens, the second -thread have already finished its task. +thread has already finished its task. Now, if you compile and run this example, you will also notice that, in some cases, the messages intertwine with each other. In other words, you might see @@ -379,12 +379,12 @@ or vice-versa. This happens because: - the threads are executing basically at the same time as the main process of the program (i.e. the `main()` function). - the threads share the same `stdout` from the main process of the program, which means that the messages that the threads produce are sent to exact same place as the messages produced by the main process. -Both of these points were described previously at @sec-what-thread. +Both of these points were described previously in @sec-what-thread. So the messages might get intertwined because they are being produced and sent to the same `stdout` roughly at the same time. Anyway, when you call `join()` over a thread, the current process will wait -for the thread to finish before it continues, and, when the thread does finishes its -task, the resources associated with this thread are automatically freed, and, +for the thread to finish before it continues, and, when the thread finishes its +task, the resources associated with this thread are automatically freed, and the current process continues with its execution. From 38aa394cf23ae284bd91661b22e7f82d0bd2d13f Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Thu, 20 Feb 2025 15:14:28 -0400 Subject: [PATCH 088/151] fix typos in 16.4.2 --- Chapters/14-threads.qmd | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 2e42ae05..0491c3b1 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -393,11 +393,11 @@ the current process continues with its execution. When you detach a thread, the resources associated with this thread are automatically released back to the system, without the need for another thread to join with this terminated thread. -In other words, when you call `detach()` over a thread it's like when your children becomes adults, -i.e. they become independent from you. A detached thread frees itself, and when this thread finishes its +In other words, when you call `detach()` on a thread it's like when your children become adults, +i.e., they become independent from you. A detached thread frees itself, and when this thread finishes its tasks, it does not report the results back to you. Thus, you normally mark a thread as *detached* -when you don't need to use the return value of the thread, or, when you don't care about -when exactly the thread finishes its job, i.e. the thread solves everything by itself. +when you don't need to use the return value of the thread, or when you don't care about +when exactly the thread finishes its job, i.e., the thread solves everything by itself. Take the code example below. We create a new thread, detach it, and then, we just print a final message before we end our program. We use the same `print_id()` @@ -425,10 +425,10 @@ Finish main Now, if you look closely at the output of this code example, you will notice that only the final message in main was printed to the console. The message that was supposed to be printed by `print_id()` did not appear in the console. -Why? Is because the main process of our program has finished first, +Why? It is because the main process of our program has finished first, before the thread was able to say anything. -And that is perfectly ok behaviour, because the thread was detached, so, it was +And that is perfectly ok behaviour, because the thread was detached, so it was able to free itself, without the need to wait for the main process. If you ask main to sleep (or "wait") for some extra nanoseconds, before it ends, you will likely see the message printed by `print_id()`, because you give enough time for the thread to From d72671f95d6e57cda94cb2307edf9422f1a8ecf2 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Sat, 22 Feb 2025 04:09:47 -0400 Subject: [PATCH 089/151] fix typos in 16.5 --- Chapters/14-threads.qmd | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 0491c3b1..60267be6 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -438,8 +438,8 @@ finish before the main process ends. ## Thread pools Thread pools is a very popular programming pattern, which is used especially on servers and daemons processes. -A thread pool is just a set of threads, or, a "pool" of threads. Many programmers like to use this pattern, because it makes -easier to manage and use multiple threads in your program, instead of manually creating the threads when you need them. +A thread pool is just a set of threads, or a "pool" of threads. Many programmers like to use this pattern because it makes +it easier to manage and use multiple threads in your program, instead of manually creating the threads when you need them. Also, using thread pools might increase performance as well in your program, especially if your program is constantly creating threads to perform short-lived tasks. @@ -449,7 +449,7 @@ in this constant process of creating and destroying threads. The main idea behind a thread pool is to have a set of threads already created and ready to perform tasks at all times. You create a set of threads at the moment that your program starts, and keep -these threads alive while your program runs. Each of these threads will be either performing a task, or, +these threads alive while your program runs. Each of these threads will be either performing a task, or waiting for a task to be assigned. Every time a new task emerges in your program, this task is added to a "queue of tasks", and the moment that a thread becomes available and ready to perform a new task, @@ -503,17 +503,17 @@ To assign a task to be performed by a thread, we need to call the `spawn()` meth from the thread pool object. This `spawn()` method works identical to the `spawn()` method from the -`Thread` object. The method have almost the same arguments as the previous one, +`Thread` object. The method has almost the same arguments as the previous one, more precisely, we don't have to provide a `SpawnConfig` object in this case. But instead of creating a new thread, this `spawn()` method from -the thread pool object just register a new task in the internal "queue of tasks" to be performed, +the thread pool object just registers a new task in the internal "queue of tasks" to be performed, and any available thread in the pool will get this task, and it will simply perform the task. In the example below, we are using our previous `print_id()` function once again. But you may notice that the `print_id()` function is a little different this time, because now we are using `catch` instead of `try` in the `print()` call. Currently, the `Pool` struct only supports functions that don't return errors -as tasks. Thus, when assigning tasks to threads in a thread pool, is essential to use functions +as tasks. Thus, when assigning tasks to threads in a thread pool, it is essential to use functions that don't return errors. That is why we are using `catch` here, so that the `print_id()` function don't return an error. From 3dcc938ed4cf779cb2bf95d195bcc145207a746d Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Sat, 22 Feb 2025 04:18:54 -0400 Subject: [PATCH 090/151] void return type does not need to be discarded explicitly --- Chapters/14-threads.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 60267be6..4a6735a3 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -492,7 +492,7 @@ pub fn main() !void { .allocator = allocator, }; var pool: Pool = undefined; - _ = try pool.init(opt); + try pool.init(opt); defer pool.deinit(); } ``` From 134a3e2b9d2af98d4047c250c2d6ec81ef42e704 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Sat, 22 Feb 2025 04:29:20 -0400 Subject: [PATCH 091/151] fix typos and improve flow in 16.6 intro --- Chapters/14-threads.qmd | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 4a6735a3..37243b9f 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -552,17 +552,17 @@ and, therefore, major bugs and undefined behaviour that are usually difficult to The main idea behind a mutex is to help us to control the execution of a particular section of the code, and to prevent two or more threads from executing this particular section of the code at the same time. -Many programmers like to compare a mutex to a bathroom door (which usually have a lock). -When a thread locks its own mutex object, it is like if the bathroom door was locked, -and, therefore, the other people (in this case, the other threads) that wants to use the same bathroom at the same time -have to be patient, and simply wait for the other person (or the other thread) to unlock the door and get out of the bathroom. +Many programmers like to compare a mutex to a bathroom door (which typically has a lock). +When a thread locks its own mutex object, it is like if the bathroom door was locked. +Therefore, other people (in this case, other threads) who want to use the same bathroom at the same time +must be patient and simply wait for the current occupant (or thread) to unlock the door and get out of the bathroom. Some other programmers also like to explain mutexes by using the analogy of "each person will have their turn to speak". This is the analogy used on the [*Multithreading Code* video from the Computerphile project](https://www.youtube.com/watch?v=7ENFeb-J75k&ab_channel=Computerphile)[^computerphile]. Imagine if you are in a conversation circle. There is a moderator in this circle, which is the person that decides who -have the right to speak at that particular moment. The moderator gives a green card (or some sort of an authorization card) to the person that +has the right to speak at that particular moment. The moderator gives a green card (or some sort of an authorization card) to the person that is going to speak, and, as a result, everyone else must be silent and hear this person that has the green card. -When the person finishes talking, it gives the green card back to the moderator, and the moderator decides +When the person finishes talking, they give the green card back to the moderator, and the moderator decides who is going to talk next, and delivers the green card to that person. And the cycle goes on like this. [^computerphile]: @@ -572,7 +572,7 @@ A mutex acts like the moderator in this conversation circle. The mutex authorize and it also blocks the other threads from executing this same section of the code. If these other threads want to execute this same piece of the code, they are forced to wait for the the authorized thread to finish first. When the authorized thread finishes executing this code, the mutex authorizes the next thread to execute this code, -and the other threads are still blocked. Therefore, a mutex is like a moderator that does a "each +while the remaining threads remain blocked. Therefore, a mutex is like a moderator that does a "each thread will have their turn to execute this section of the code" type of control. @@ -584,7 +584,7 @@ When a thread tries to run this code that is locked by a mutex, this thread stop and patiently waits for this section of the codebase to be unlocked to continue. Notice that mutexes are normally used to lock areas of the codebase that access/modify data that is **shared** with all threads, -i.e. objects that are either stored in the global data section, or, in the heap space of your program. +i.e., objects that are either stored in the global data section, or in the heap space of your program. So mutexes are not normally used on areas of the codebase that access/modify objects that are local to the thread. From 2aac3469343277a03bbce53af8de88cbbdbe802c Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Sat, 22 Feb 2025 04:37:25 -0400 Subject: [PATCH 092/151] fix typos and improve flow in 16.6.3 --- Chapters/14-threads.qmd | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 37243b9f..8d022f50 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -611,27 +611,27 @@ and they summarise well the role that a critical section plays in the thread syn ### Atomic operations {#sec-atomic-operation} You will also see the term "atomic operation" a lot when reading about threads, race conditions and mutexes. -In summary, an operation is categorized as "atomic", when there is no way to happen a context switch in -the middle of this operation. In other words, this operation is always done from beginning to end, without interruptions +In summary, an operation is categorized as "atomic" when a context switch cannot occur in +the middle of the operation. In other words, this operation is always done from beginning to end, without interruptions of another process or operation in the middle of its execution phase. -Not many operations today are atomic. But why atomic operations matters here? Is because data races +Not many operations today are atomic. But why do atomic operations matter here? It is because data races (which is a type of a race condition) cannot happen on operations that are atomic. -So if a particular line in your code performs an atomic operation, then, this line will never +So if a particular line in your code performs an atomic operation, then this line will never suffer from a data race problem. Therefore, programmers sometimes use an atomic operation to protect themselves from data race problems in their code. When you have an operation that is compiled into just one single assembly instruction, this operation might be atomic, because it is just one assembly instruction. But this is not guaranteed. This is usually true for old CPU architectures -(such as `x86`). But nowadays, most assembly instructions in modern CPU architectures turn into multiple micro-tasks, -which inherently makes the operation not atomic anymore, even though it has just one single assembly instruction. +(such as `x86`). But nowadays, most assembly instructions in modern CPU architectures are broken down into multiple micro-tasks, +which inherently makes the operation non-atomic, even if it consists of a single assembly instruction. -The Zig Standard Library offers some atomic functionality at the `std.atomic` module. +The Zig Standard Library offers some atomic functionality in the `std.atomic` module. In this module, you will find a public and generic function called `Value()`. With this function we create an "atomic object", which is a value that contains some native atomic operations, most notably, a `load()` and a `fetchAdd()` operation. If you have experience with multithreading in C++, you probably have recognized this pattern. So yes, this generic "atomic object" in Zig is essentially identical to the template struct `std::atomic` from the C++ Standard Library. -Is important to emphasize that only primitive data types (i.e. the types presented at @sec-primitive-data-types) +It is important to emphasize that only primitive data types (i.e. the types presented in @sec-primitive-data-types) are supported by these atomic operations in Zig. From eb1b694182dc70dc309b1394c61d9ee8b56c4711 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Sat, 22 Feb 2025 04:52:19 -0400 Subject: [PATCH 093/151] fix typos and improve flow in 16.6.3 --- Chapters/14-threads.qmd | 44 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 8d022f50..878a916a 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -641,21 +641,21 @@ are supported by these atomic operations in Zig. ### Data races and race conditions To understand why mutexes are used, we need to understand better the problem that they seek -to solve, which can be summarized into data races problems. A data race problem is a type of a race condition, +to solve, which can be summarized into data race problems. A data race problem is a type of a race condition, which happens when one thread is accessing a particular memory location (i.e. a particular shared object) at the same time that another thread is trying to write/save new data into this same memory location (i.e. the same shared object). We can simply define a race condition as any type of bug in your program that is based -on a "who get's there first" problem. A data race problem is a type of a race condition, because it occurs when two or more parties +on a "who gets there first" problem. A data race problem is a type of a race condition, because it occurs when two or more parties are trying to read and write into the same memory location at the same time, and, therefore, the end result of this operation -depends completely on who get's to this memory location first. -As consequence, a program that have a data race problem will likely produce a different result each time that we execute it. +depends completely on who gets to this memory location first. +As a consequence, a program that has a data race problem will likely produce a different result each time that we execute it. Thus, race conditions produce undefined behaviour and unpredictability because the program produces -a different answer in each time that a different person get's to the target location first than the others. -And we have no easy way to either predict or control who is getting to this target location first. -In other words, in each execution of your program, you get a different answer, because a different person, -or, a different function, or, a different part of the code is finishing its tasks first than the others. +a different answer each time a different person gets to the target location before the others. +And, we have no easy way to either predict or control who is getting to this target location first. +In other words, each time your program runs, you may get a different answer because a different person, +function, or part of the code finishes its tasks before the others. As an example, consider the code snippet exposed below. In this example, we create a global counter variable, and we also create an `increment()` function, whose job is to just increment this global counter @@ -668,8 +668,8 @@ to print 2 hundred thousand at the end, but in practice, every time that I execu I get a different answer. In the example exposed below, you can see that this time the end -result was 117254, instead of the expected 200000. The second time I have executed this program, -I got the number 108592 as result. So the end result of this program is varying, but it never gets +result was 117254, instead of the expected 200000. The second time I executed this program, +I got the number 108592 as the result. So the end result of this program is varying, but it never gets to the expected 200000 that we want. @@ -701,13 +701,13 @@ Couter value: 117254 Why this is happening? The answer is: because this program contains a data race problem. -This program would print the correct number 200000, if, and only if the first thread finishes +This program would print the correct number 200000, if and only if, the first thread finishes its tasks before the second thread starts to execute. But that is very unlikely to happen. -Because the process of creating the thread is too fast, and therefore, both threads starts to execute roughly +Because the process of creating the thread is too fast, and therefore, both threads start to execute roughly at the same time. If you change this code to add some nanoseconds of sleep between the first and the second calls to `spawn()`, you will increase the chances of the program producing the "correct result". -So the data race problem happens, because both threads are reading and writing to the same +So the data race problem happens because both threads are reading and writing to the same memory location at roughly the same time. In this example, each thread is essentially performing three basic operations at each iteration of the for loop, which are: @@ -717,16 +717,16 @@ three basic operations at each iteration of the for loop, which are: Ideally, a thread B should read the value of `count`, only after the other thread A has finished writing the incremented value back into the `count` object. Therefore, in the ideal scenario, which is demonstrated -at @tbl-data-race-ideal, the threads should work in sync with each other. But the reality is that these +in @tbl-data-race-ideal, the threads should work in sync with each other. But the reality is that these threads are out of sync, and because of that, they suffer from a data race problem, which is demonstrated -at @tbl-data-race-not. +in @tbl-data-race-not. Notice that, in the data race scenario (@tbl-data-race-not), the read performed by a thread B happens before the write operation of thread A, and that ultimately leads to wrong results at the end of the program. -Because when the thread B reads the value from the `count` variable, the thread A is still processing -the initial value from `count`, and it did not write the new and incremented value into `count` yet. So what -happens is that thread B ends up reading the same initial value (the "old" value) from `count`, instead of -reading the new and incremented version of this value that would be calculated by thread A. +Because when thread B reads the value of the `count` variable, thread A is still processing +the initial value from `count`, and has not yet written the new, incremented value back to `count`. As a result, +thread B ends up reading the same initial (or "old") value from `count` instead of +the updated, incremented value that thread A would have written. ::: {#tbl-data-race-ideal} @@ -759,16 +759,16 @@ reading the new and incremented version of this value that would be calculated b If you think about these diagrams exposed in form of tables, you will notice that they relate back to our discussion of atomic operations -at @sec-atomic-operation. Remember, atomic operations are operations that the CPU executes +in @sec-atomic-operation. Remember, atomic operations are operations that the CPU executes from beginning to end, without interruptions from other threads or processes. So, -the scenario exposed at @tbl-data-race-ideal do not suffer from a data race, because +the scenario exposed in @tbl-data-race-ideal does not suffer from a data race, because the operations performed by thread A are not interrupted in the middle by the operations from thread B. If we also think about the discussion of critical section from @sec-critical-section, we can identify the section that representes the critical section of the program, which is the section that is vulnerable to data race conditions. In this example, the critical section of the program is the line where we increment -the `counter` variable (`counter += 1`). So, ideally, we want to use a mutex, and lock right before this line, and then, +the `counter` variable (`counter += 1`). So, ideally, we want to use a mutex, and lock right before this line, and then unlock right after this line. From 0e1ac6e7d37a0050901e110be465745bce81183b Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Sat, 22 Feb 2025 04:58:35 -0400 Subject: [PATCH 094/151] fix typo in 16.6.4 --- Chapters/14-threads.qmd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 878a916a..ec25ae56 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -778,10 +778,10 @@ unlock right after this line. Now that we know the problem that mutexes seek to solve, we can learn how to use them in Zig. Mutexes in Zig are available through the `std.Thread.Mutex` struct from the Zig Standard Library. -If we take the same code example from the previous example, and improve it with mutexes, to solve -our data race problem, we get the code example exposed below. +If we take the same code from the previous example, and improve it with mutexes, to solve +our data race problem, we get the code example below. -Notice that we had this time to alter the `increment()` function to receive a pointer to +Notice that this time, we had to alter the `increment()` function to receive a pointer to the `Mutex` object as input. All that we need to do, to make this program safe against data race problems, is to call the `lock()` method at the beginning of the critical section, and then, call `unlock()` at the end of the critical section. From 32feb515ea5bc026ad791343ba58c43ca1cf1ff4 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Sat, 22 Feb 2025 05:04:32 -0400 Subject: [PATCH 095/151] fix typos in 16.7 intro --- Chapters/14-threads.qmd | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index ec25ae56..f3c8311a 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -817,28 +817,28 @@ pub fn main() !void { ## Read/Write locks -Mutexes are normally used when is always not safe to have two or more threads running the same +Mutexes are normally used when it is not always safe for two or more threads running the same piece of code at the same time. In contrast, read/write locks are normally used in situations -where you have a mixture of scenarios, i.e. there are some pieces of the codebase that are safe +where you have a mixture of scenarios, i.e., there are some pieces of the codebase that are safe to run in parallel, and other pieces that are not safe. -For example, suppose that you have multiple threads that uses the same shared file in the filesystem to store some configurations, or, +For example, suppose that you have multiple threads that uses the same shared file in the filesystem to store some configurations, or statistics. If two or more threads try to read the data from this same file at the same time, nothing bad happens. So this part of the codebase is perfectly safe to be executed in parallel, with multiple threads reading the same file at the same time. -However, if two or more threads try to write data into this same file at the same time, then, we cause some race conditions +However, if two or more threads try to write data into this same file at the same time, then we cause some race condition problems. So this other part of the codebase is not safe to be executed in parallel. More specifically, a thread might end up writing data in the middle of the data written by the other thread. -This process of two or more threads writing to the same location, might lead to data corruption. -This specific situation is usually called of a *torn write*. +This process of two or more threads writing to the same location might lead to data corruption. +This specific situation is usually called a *torn write*. -Thus, what we can extract from this example is that there is certain types of operations that causes -a race condition, but there are also, other types of operations that do not cause a race condition problem. -You could also say that, there are types of operations that are susceptible to race condition problems, +Thus, what we can extract from this example is that there are certain types of operations that cause +a race condition, but there are also other types of operations that do not cause a race condition problem. +You could also say that there are types of operations that are susceptible to race condition problems, and there are other types of operations that are not. -A read/write lock is a type of lock that acknowledges the existance of this specific scenario, and you can -use this type of lock to control which parts of the codebase are safe to run in parallel, and which parts are not safe. +A read/write lock is a type of lock that acknowledges the existence of this specific scenario, and you can +use this type of lock to control which parts of the codebase are safe to run in parallel and which parts are not. From d8dca8b8bd124598c42a50b36aa4166bd2de550e Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Sat, 22 Feb 2025 05:16:08 -0400 Subject: [PATCH 096/151] fix typos --- Chapters/14-threads.qmd | 46 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index f3c8311a..4de23adc 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -258,14 +258,14 @@ pub fn main() !void { Notice the use of `try` when calling the `spawn()` method. This means that this method can return an error in some circumstances. One circumstance in particular is when you attempt to create a new thread, when you have already -created too much (i.e. you have exceeded the quota of concurrent threads in your system). +created too much (i.e., you have exceeded the quota of concurrent threads in your system). But, if the new thread is successfully created, the `spawn()` method returns a handler object (which is just an object of type `Thread`) to this new thread. You can use this handler object to effectively control all aspects of the thread. When the thread gets created, the function that you provided as input to `spawn()` -gets invoked (i.e. gets called) to start the execution on this new thread. +gets invoked (i.e., gets called) to start the execution on this new thread. In other words, every time you call `spawn()`, not only is a new thread created, but the "start work button" of this thread is also automatically pressed. So the work being performed in this thread starts as soon as the thread is created. @@ -331,7 +331,7 @@ new threads, one after another. Then, we join the first thread, then, we wait for two whole seconds, then, at last, we join the second thread. The idea behind this example is that the last `join()` call is executed -only after the first thread finishes its task (i.e. the first `join()` call), +only after the first thread finishes its task (i.e., the first `join()` call), and the two-second delay. If you compile and run this example, you will notice that most messages are quickly printed to `stdout`, i.e. they appear almost instantly on your screen. @@ -366,7 +366,7 @@ Thread ID: 2 Joining thread 2 ``` -This demonstrates that both threads finish their work (i.e. printing the IDs) +This demonstrates that both threads finish their work (i.e., printing the IDs) very fast, before the two seconds of delay end. Because of that, the last `join()` call returns pretty much instantly. Because when this last `join()` call happens, the second thread has already finished its task. @@ -376,7 +376,7 @@ the messages intertwine with each other. In other words, you might see the message "Joining thread 1" inserted in the middle of the message "Thread 1", or vice-versa. This happens because: -- the threads are executing basically at the same time as the main process of the program (i.e. the `main()` function). +- the threads are executing basically at the same time as the main process of the program (i.e., the `main()` function). - the threads share the same `stdout` from the main process of the program, which means that the messages that the threads produce are sent to exact same place as the messages produced by the main process. Both of these points were described previously in @sec-what-thread. @@ -593,7 +593,7 @@ So mutexes are not normally used on areas of the codebase that access/modify obj Critical section is a concept commonly associated with mutexes and thread synchronization. In essence, a critical section is the section of the program that a thread access/modify a shared resource -(i.e. an object, a file descriptor, something that all threads have access to). In other words, +(i.e., an object, a file descriptor, something that all threads have access to). In other words, a critical section is the section of the program where race conditions might happen, and, therefore, where undefined behaviour can be introduced into the program. @@ -631,7 +631,7 @@ In this module, you will find a public and generic function called `Value()`. Wi a value that contains some native atomic operations, most notably, a `load()` and a `fetchAdd()` operation. If you have experience with multithreading in C++, you probably have recognized this pattern. So yes, this generic "atomic object" in Zig is essentially identical to the template struct `std::atomic` from the C++ Standard Library. -It is important to emphasize that only primitive data types (i.e. the types presented in @sec-primitive-data-types) +It is important to emphasize that only primitive data types (i.e., the types presented in @sec-primitive-data-types) are supported by these atomic operations in Zig. @@ -642,8 +642,8 @@ are supported by these atomic operations in Zig. To understand why mutexes are used, we need to understand better the problem that they seek to solve, which can be summarized into data race problems. A data race problem is a type of a race condition, -which happens when one thread is accessing a particular memory location (i.e. a particular shared object) at the same -time that another thread is trying to write/save new data into this same memory location (i.e. the same shared object). +which happens when one thread is accessing a particular memory location (i.e., a particular shared object) at the same +time that another thread is trying to write/save new data into this same memory location (i.e., the same shared object). We can simply define a race condition as any type of bug in your program that is based on a "who gets there first" problem. A data race problem is a type of a race condition, because it occurs when two or more parties @@ -846,7 +846,7 @@ use this type of lock to control which parts of the codebase are safe to run in Therefore, a read/write lock is a little different from a mutex. Because a mutex is always an *exclusive lock*, meaning that, only one thread is allowed to execute at all times. With an exclusive lock, the other threads are always "excluded", -i.e. they are always blocked from executing. But in a read/write lock, the other threads might be authorized +i.e., they are always blocked from executing. But in a read/write lock, the other threads might be authorized to run at the same time, depending on the type of lock that they acquire. We have two types of locks in a read/write lock, which are: an exclusive lock and a shared lock. An exclusive lock works exactly the same @@ -860,28 +860,28 @@ this C struct, you can create: The terminology might be a little different compared to Zig. But the meaning is still the same. Therefore, just remember this relationship, write locks are exclusive locks, while read locks are shared locks. -When a thread tries to acquire a read lock (i.e. a shared lock), this thread get's the shared lock -if, and only if another thread does not currently holds a write lock (i.e. an exclusive lock), and also, -if there are no other threads that are already in the queue, -waiting for their turn to acquire a write lock. In other words, the thread in the queue have attempted +When a thread tries to acquire a read lock (i.e., a shared lock), this thread gets the shared lock +if and only if another thread does not currently holds a write lock (i.e., an exclusive lock), and also +if there are no other threads already in the queue, +waiting for their turn to acquire a write lock. In other words, the thread in the queue has attempted to get a write lock earlier, but this thread was blocked -because there was another thread running that already had a write lock. As consequence, this thread is on the queue to get a write lock, +because there was another thread running that already had a write lock. As a consequence, this thread is in the queue to get a write lock, and it's currently waiting for the other thread with a write lock to finish its execution. When a thread tries to acquire a read lock, but it fails in acquiring this read lock, either because there is -a thread with a write lock already running, or, because there is a thread in the queue to get a write lock, -the execution of this thread is instantly blocked, i.e. paused. This thread will indefinitely attempt to get the +a thread with a write lock already running, or because there is a thread in the queue to get a write lock, +the execution of this thread is instantly blocked, i.e., paused. This thread will indefinitely attempt to get the read lock, and its execution will be unblocked (or unpaused) only after this thread successfully acquires the read lock. If you think deeply about this dynamic between read locks versus write locks, you might notice that a read lock is basically a safety mechanism. More specifically, it is a way for us to -allow a particular thread to run together with the other threads, only when it's safe to. In other words, if there is currently -a thread with a write lock running, then, it is very likely not safe for the thread that is trying to acquire the read lock to run now. -As consequence, the read lock protects this thread from running into dangerous waters, and patiently waits for the +allow a particular thread to run together with the other threads only when it's safe to. In other words, if there is currently +a thread with a write lock running, then it is very likely not safe for the thread that is trying to acquire the read lock to run now. +As a consequence, the read lock protects this thread from running into dangerous waters, and patiently waits for the "write lock" thread to finishes its tasks before it continues. -On the other hand, if there are only "read lock" (i.e. "shared lock") threads currently running -(i.e. not a single "write lock" thread currently exists), then, +On the other hand, if there are only "read lock" (i.e., "shared lock") threads currently running +(i.e., not a single "write lock" thread currently exists), then it is perfectly safe for this thread that is acquiring the read lock to run in parallel with the other threads. As a result, the read lock just allows for this thread to run together with the other threads. @@ -1054,7 +1054,7 @@ nobody becomes responsible for clearing (or freeing) the resources associated wi You don't want to be in this situation, so remember to always use `join()` or `detach()` on the threads that you create. When you don't use one of these methods, we lose control over the thread, and its resources are never freed -(i.e. you have leaked resources in the system). +(i.e., you have leaked resources in the system). ### Cancelling or killing a particular thread From d99c6eedd95142df9719f1bcd78d5cdd4540d813 Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Sat, 22 Feb 2025 10:34:49 -0400 Subject: [PATCH 097/151] fix typos in 16.7.2 --- Chapters/14-threads.qmd | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 4de23adc..bb2988e4 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -896,9 +896,9 @@ of our multithreaded code is safe to have parallelism, and which sections are no ### Using read/write locks in Zig The Zig Standard Library supports read/write locks through the `std.Thread.RwLock` module. -If you want to a particular thread to acquire a shared lock (i.e. a read lock), you should -call the `lockShared()` method from the `RwLock` object. But, if you want for this thread -to acquire an exclusive lock (i.e. a write lock) instead, then, you should call the +If you want a particular thread to acquire a shared lock (i.e., a read lock), you should +call the `lockShared()` method from the `RwLock` object. But, if you want this thread +to acquire an exclusive lock (i.e., a write lock) instead, then you should call the `lock()` method from the `RwLock` object. As with mutexes, we also have to unlock the shared or exclusive locks that we acquire through a read/write lock object, @@ -906,8 +906,8 @@ once we are at the end of our "critical section". If you have acquired an exclus this exclusive lock by calling the `unlock()` method from the read/write lock object. In contrast, if you have acquired a shared lock instead, then, call `unlockShared()` to unlock this shared lock. -As a simple example, the snippet exposed below creates three separate threads responsible for reading the -current value in a `counter` object, and it also creates another thread, responsible for writing +As a simple example, the snippet below creates three separate threads responsible for reading the +current value in a `counter` object, and it also creates another thread responsible for writing new data into the `counter` object (incrementing it, more specifically). ```{zig} From 31ab59c17a68661c3df0a0129ee902e037849c6f Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Sat, 22 Feb 2025 10:47:27 -0400 Subject: [PATCH 098/151] fix typos in 16.8 --- Chapters/14-threads.qmd | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index bb2988e4..90bbfad0 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -950,7 +950,7 @@ pub fn main() !void { The `Thread` struct supports yielding through the `yield()` method. Yielding a thread means that the execution of the thread is temporarily stopped, -and the thread comes back to the end of the queue of priority of the scheduler from +and it moves to the end of the priority queue managed by the scheduler of your operating system. That is, when you yield a thread, you are essentially saying the following to your OS: @@ -960,12 +960,12 @@ to focus on doing other things instead?". So this yield operation is also a way for you to stop a particular thread, so that you can work and prioritize other threads instead. -Is important to say that, yielding a thread is a "not so common" thread operation these days. -In other words, not many programmers use yielding in production, simply because is hard to use +It is important to say that, yielding a thread is a "not so common" thread operation these days. +In other words, not many programmers use yielding in production, simply because it is hard to use this operation and make it work properly, and also, there are better alternatives. Most programmers prefer to use `join()` instead. -In fact, most of the times, when you see somebody using this "yield" operation in some code example, -they are mostly using it to help them debug race conditions in their applications. +In fact, most of the time, when you see someone using this "yield" operation in some code example, +they are usually doing so to help debug race conditions in their applications. That is, this "yield" operation is mostly used as a debug tool nowadays. Anyway, if you want to yield a thread, just call the `yield()` method from it, like this: From 4d30a4d2d54d693c5eaeec593ed74933867c44ea Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Sat, 22 Feb 2025 10:53:26 -0400 Subject: [PATCH 099/151] fix typos in 16.9 --- Chapters/14-threads.qmd | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 90bbfad0..66be59b5 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -1002,14 +1002,14 @@ After that, the function sleeps for 1 second, to simulate some type of work, and then, the function tries to acquire the `mut2` lock. On the other hand, when we look into the second thread, which executes the `work2()` function, -we can see that this function acquires the `mut2` lock first. Because when this thread get's created and it tries +we can see that this function acquires the `mut2` lock first. Because when this thread gets created and it tries to acquire this `mut2` lock, the first thread is still sleeping on that "sleep 1 second" line. After acquiring `mut2`, the `work2()` function also sleeps for 1 second, to -simulate some type of work, and then, the function tries to acquire the `mut1` lock. +simulate some type of work, and then the function tries to acquire the `mut1` lock. This creates a deadlock situation, because after the "sleep for 1 second" line in both threads, -the thread 1 is trying to acquire the `mut2` lock, but this lock is currently being used by thread 2. -However, at this moment, the thread 2 is also trying to acquire the `mut1` lock, which is currently +thread 1 is trying to acquire the `mut2` lock, but this lock is currently being used by thread 2. +However, at this moment, thread 2 is also trying to acquire the `mut1` lock, which is currently being used by thread 1. Therefore, both threads end up waiting for ever. Waiting for their peer to free the lock that they want to acquire. @@ -1044,7 +1044,7 @@ pub fn main() !void { ### Not calling `join()` or `detach()` {#sec-not-call-join-detach} -When you do not call either `join()` or `detach()` over a thread, then, this thread becomes a "zombie thread", +When you do not call either `join()` or `detach()` over a thread, then this thread becomes a "zombie thread", because it does not have a clear "return point". You could also interpret this as: "nobody is properly responsible for managing the thread". When we don't establish if a thread is either *joinable* or *detached*, @@ -1061,21 +1061,21 @@ control over the thread, and its resources are never freed When we think about the `pthreads` C library, there is a possible way to asynchronously kill or cancel a thread, which is by sending a `SIGTERM` signal to the thread through the `pthread_kill()` function. -But canceling a thread like this is bad. Is dangerously bad. As consequence, the Zig implementation +But canceling a thread like this is bad. It is dangerously bad. As a consequence, the Zig implementation of threads does not have a similar function, or, a similar way to asynchronously cancel or kill a thread. Therefore, if you want to cancel a thread in the middle of its execution in Zig, -then, one good strategy that you can take is to use control flow in conjunction with `join()`. -More specifically, you can design your thread around a while loop, that is constantly +then one good strategy that you can take is to use control flow in conjunction with `join()`. +More specifically, you can design your thread around a while loop that is constantly checking if the thread should continue running. -If is time to cancel the thread, we could make the while loop break, and join the thread with the main thread +If is time to cancel the thread, we could make the while loop break and join the thread with the main thread by calling `join()`. The code example below demonstrates to some extent this strategy. Here, we are using control flow to break the while loop, and exit the thread earlier than what we have initially planned to. This example also demonstrates how can we use -atomic objects in Zig with the `Value()` generic function that we have mentioned at @sec-atomic-operation. +atomic objects in Zig with the `Value()` generic function that we have mentioned in @sec-atomic-operation. ```{zig} From ad64b0f04e9652bce0f5a92f127cd6c282f04c7d Mon Sep 17 00:00:00 2001 From: hamza wahed Date: Sat, 22 Feb 2025 11:01:22 -0400 Subject: [PATCH 100/151] remove commas around 'if and only if' --- Chapters/14-threads.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 66be59b5..232fee95 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -701,7 +701,7 @@ Couter value: 117254 Why this is happening? The answer is: because this program contains a data race problem. -This program would print the correct number 200000, if and only if, the first thread finishes +This program would print the correct number 200000 if and only if the first thread finishes its tasks before the second thread starts to execute. But that is very unlikely to happen. Because the process of creating the thread is too fast, and therefore, both threads start to execute roughly at the same time. If you change this code to add some nanoseconds of sleep between the first and the second calls to `spawn()`, From 2d2528d238ef4ff3c91553ed8f58f59f9ce1f44f Mon Sep 17 00:00:00 2001 From: Glystik Date: Tue, 25 Feb 2025 16:40:47 +0100 Subject: [PATCH 101/151] fixing typos and grammar --- Chapters/01-base64.qmd | 56 +++++++++---------- Chapters/01-memory.qmd | 21 +++---- Chapters/01-zig-weird.qmd | 99 ++++++++++++++++----------------- Chapters/02-debugging.qmd | 7 +-- Chapters/03-structs.qmd | 13 ++--- Chapters/03-unittests.qmd | 9 ++- Chapters/04-http-server.qmd | 25 ++++----- Chapters/05-pointers.qmd | 10 ++-- Chapters/07-build-system.qmd | 33 ++++++----- Chapters/09-data-structures.qmd | 38 ++++++------- Chapters/09-error-handling.qmd | 25 ++++----- Chapters/10-stack-project.qmd | 25 ++++----- Chapters/12-file-op.qmd | 44 +++++++-------- Chapters/13-image-filter.qmd | 26 ++++----- Chapters/14-threads.qmd | 61 ++++++++++---------- Chapters/14-zig-c-interop.qmd | 25 ++++----- Chapters/15-vectors.qmd | 8 +-- README.md | 4 +- zig_engine.R | 2 +- 19 files changed, 246 insertions(+), 285 deletions(-) diff --git a/Chapters/01-base64.qmd b/Chapters/01-base64.qmd index 962f63bb..0d9a22f5 100644 --- a/Chapters/01-base64.qmd +++ b/Chapters/01-base64.qmd @@ -155,11 +155,11 @@ into 4 characters from the base64 scale. It keeps iterating through the input st per iteration. It keeps iterating, and producing these "new characters" until it hits the end of the input string. -Now, you may think, what if you have a particular string that have a number of bytes -that is not divisible by 3? What happens? For example, if you have a string -that contains only two characters/bytes, such as "Hi". How the -algorithm would behave in such situation? You find the answer at @fig-base64-algo1. -You can see at @fig-base64-algo1 that the string "Hi", when converted to base64, +Now you may think, what if you have a particular string that has a number of bytes +that is not divisible by 3 - what happens? For example, if you have a string +that contains only two characters/bytes, such as "Hi". How would the algorithm +behave in such situation? You find the answer in @fig-base64-algo1. +You can see in @fig-base64-algo1 that the string "Hi", when converted to base64, becomes the string "SGk=": ![The logic behind a base64 encoder](./../Figures/base64-encoder-flow.png){#fig-base64-algo1} @@ -171,7 +171,7 @@ the algorithm does, is to check how to divide the input bytes into groups of 6 b If the algorithm notices that there is a group of 6 bits that, have some bits in it, but, at the same time, it is not full (in other words, $0 < nbits < 6$, being $nbits$ the number of bits), meaning that, it lacks some bits to fill the 6-bits requirement, the algorithm simply add extra zeros in this group -to fill the space that it needs. That is why at @fig-base64-algo1, on the third group after the 6-bit transformation, +to fill the space that it needs. That is why in @fig-base64-algo1, on the third group after the 6-bit transformation, 2 extra zeros were added to fill the gap in this group. When we have a 6-bit group that is not completely full, like the third group, extra zeros @@ -190,7 +190,7 @@ of meaningful characters in the sequence. Hence, everytime that the algorithm pr As another example, if you give the string "0" as input to a base64 encoder, this string is translated into the base64 sequence "MA==". The character "0" is, in binary, the sequence `00110000`[^zero-note]. So, with the 6-bit transformation -exposed at @fig-base64-algo1, this single character would produce these two 6-bit groups: `001100`, `000000`. +exposed in @fig-base64-algo1, this single character would produce these two 6-bit groups: `001100`, `000000`. The remaining two 6-bit groups become "padding groups". That is why the last two characters in the output sequence (MA==) are `==`. @@ -211,7 +211,7 @@ by the base64 encoder. Each byte in the input string (the base64 encoded string) normally contributes to re-create two different bytes in the output (the original binary data). In other words, each byte that comes out of a base64 decoder is created by transforming merging two different -bytes in the input together. You can visualize this relationship at @fig-base64-algo2: +bytes in the input together. You can visualize this relationship in @fig-base64-algo2: ![The logic behind a base64 decoder](./../Figures/base64-decoder-flow.png){#fig-base64-algo2} @@ -220,7 +220,7 @@ into the bytes of the output, are a bit tricky to visualize in a figure like thi summarized these transformations as "Some bit shifting and additions ..." in the figure. These transformations will be described in depth later. -Besides that, if you look again at @fig-base64-algo2, you will notice that the character `=` was completely +Besides that, if you look again in @fig-base64-algo2, you will notice that the character `=` was completely ignored by the algorithm. Remember, this is just a special character that marks the end of meaningful characters in the base64 sequence. So, every `=` character in a base64 encoded sequence should be ignored by a base64 decoder. @@ -283,13 +283,13 @@ fn _calc_encode_length(input: []const u8) !usize { Also, you might have notice that, if the input length is less than 3 bytes, then, the output length of the encoder is -always 4 bytes. This is the case for every input with less than 3 bytes, because, as I described at @sec-base64-encoder-algo, +always 4 bytes. This is the case for every input with less than 3 bytes, because, as I described in @sec-base64-encoder-algo, the algorithm always produces enough "padding-groups" in the end result, to complete the 4 bytes window. Now, for the decoder, we just need to apply the inverse logic: for each 4 bytes in the input, 3 bytes will be produced in the output of the decoder. I mean, this is roughly true, because we also need to -take the `=` character into account, which is always ignored by the decoder, as we described at @sec-base64-decoder-algo, and, -at @fig-base64-algo2. But we can ignore this fact for now, just to keep things simple. +take the `=` character into account, which is always ignored by the decoder, as we described in @sec-base64-decoder-algo, and, +in @fig-base64-algo2. But we can ignore this fact for now, just to keep things simple. The function `_calc_decode_length()` exposed below summarizes this logic that we described. It is very similar to the function `_calc_encode_length()`. Only the division part is twisted, and also, in the special @@ -329,7 +329,7 @@ this book[^zig-base64-algo]. ### The 6-bit transformation {#sec-6bit-transf} -The 6-bit transformation presented at @fig-base64-algo1 is the core part of the base64 encoder algorithm. +The 6-bit transformation presented in @fig-base64-algo1 is the core part of the base64 encoder algorithm. By understanding how this transformation is made in code, the rest of the algorithm becomes much simpler to comprehend. @@ -425,13 +425,13 @@ you have, and change them in some way. This ultimately also changes the value itself, because the binary representation of this value changes. -We have already seen at @fig-encoder-bitshift the effect produced by a bit-shift. +We have already seen in @fig-encoder-bitshift the effect produced by a bit-shift. But let's use the first byte in the output of the base64 encoder as another example of what bit-shifting means. This is the easiest byte of the 4 bytes in the output to build. Because we only need to move the bits from the first byte in the input two positions to the right, with the *bit shift to the right* (`>>`) operator. -If we take the string "Hi" that we used at @fig-base64-algo1 as an example, the first byte in +If we take the string "Hi" that we used in @fig-base64-algo1 as an example, the first byte in this string is "H", which is the sequence `01001000` in binary. If we move the bits of this byte, two places to the right, we get the sequence `00010010` as result. This binary sequence is the value `18` in decimal, and also, the value `0x12` in hexadecimal. @@ -512,7 +512,7 @@ pub fn main() !void { ### Allocating space for the output -As I described at @sec-stack, to store an object in the stack, +As I described in @sec-stack, to store an object in the stack, this object needs to have a known and fixed length at compile-time. This is an important limitation for our base64 encoder/decoder case. Because the size of the output (from both the encoder and decoder) depends @@ -525,7 +525,7 @@ this means that we cannot store the output for both the encoder and decoder in the stack. Consequently, we need to store this output on the heap, -and, as I commented at @sec-heap, we can only +and, as I commented in @sec-heap, we can only store objects in the heap by using allocator objects. So, one the arguments to both the `encode()` and `decode()` functions, needs to be an allocator object, because @@ -544,8 +544,8 @@ the type `std.mem.Allocator` from the Zig Standard Library. Now that we have a basic understanding on how the bitwise operators work, and how exactly they help us to achieve the result we want to achieve. We can now encapsulate -all the logic that we have described at @fig-base64-algo1 and @tbl-transf-6bit into a nice -function that we can add to our `Base64` struct definition, that we started at @sec-base64-table. +all the logic that we have described in @fig-base64-algo1 and @tbl-transf-6bit into a nice +function that we can add to our `Base64` struct definition, that we started in @sec-base64-table. You can find the `encode()` function below. Notice that the first argument of this function, is the `Base64` struct itself. Therefore, this argument clearly signals @@ -561,7 +561,7 @@ Furthermore, this `encode()` function has two other arguments: 1. `input` is the input sequence of characters that you want to encode in base64; 1. `allocator` is an allocator object to use in the necessary memory allocations. -I described everything you need to know about allocator objects at @sec-allocators. +I described everything you need to know about allocator objects in @sec-allocators. So, if you are not familiar with them, I highly recommend you to comeback to that section, and read it. By looking at the `encode()` function, you will see that we use this @@ -644,7 +644,7 @@ pub fn encode(self: Base64, Now, we can focus on writing the base64 decoder logic. Remember from @fig-base64-algo2 that, a base64 decoder does the inverse process of an encoder. So, all we need to do, is to -write a `decode()` function that performs the inverse process that I exposed at @sec-encoder-logic. +write a `decode()` function that performs the inverse process that I exposed in @sec-encoder-logic. ### Mapping base64 characters to their indexes {#sec-map-base64-index} @@ -667,7 +667,7 @@ If these characters match, then, we return the index of this character in the base64 scale as the result. Notice that, if the input character is `'='`, the function returns the index 64, which is -"out of range" in the scale. But, as I described at @sec-base64-scale, +"out of range" in the scale. But, as I described in @sec-base64-scale, the character `'='` does not belong to the base64 scale itself. It is a special and meaningless character in base64. @@ -724,12 +724,12 @@ So, the steps to produce the 3 bytes in the output are: Before we continue, let's try to visualize how these transformations make the original bytes that we had -before the encoding process. First, think back to the 6-bit transformation performed by the encoder exposed at @sec-encoder-logic. +before the encoding process. First, think back to the 6-bit transformation performed by the encoder exposed in @sec-encoder-logic. The first byte in the output of the encoder is produced by moving the bits in the first byte of the input two positions to the right. If for example the first byte in the input of the encoder was the sequence `ABCDEFGH`, then, the first byte in the output of the encoder would be `00ABCDEF` (this sequence would be the first byte in the input of the decoder). Now, if the second byte in the input of the encoder was the sequence -`IJKLMNOP`, then, the second byte in the encoder output would be `00GHIJKL` (as we demonstrated at @fig-encoder-bitshift). +`IJKLMNOP`, then, the second byte in the encoder output would be `00GHIJKL` (as we demonstrated in @fig-encoder-bitshift). Hence, if the sequences `00ABCDEF` and `00GHIJKL` are the first and second bytes, respectively, in the input of the decoder, the @fig-decoder-bitshift demonstrates visually how these two bytes are transformed into the first byte of the output of the decoder. @@ -834,8 +834,8 @@ var fba = std.heap.FixedBufferAllocator.init( ); const allocator = fba.allocator(); -const text = "Testing some more stuff"; -const etext = "VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY="; +const text = "Testing some more stuff"; +const etext = "VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY="; const base64 = Base64.init(); const encoded_text = try base64.encode( allocator, text @@ -852,8 +852,8 @@ try stdout.print( ``` ``` -Encoded text: VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY= -Decoded text: Testing some more stuff +Encoded text: VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY= +Decoded text: Testing some more stuff ``` You can also see the full source code at once, by visiting the official repository of this book[^repo]. diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index 3d7aa0a8..c08ce5d9 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -359,7 +359,7 @@ how much memory is allocated, and where this memory is freed. > Unlike stack memory, heap memory is allocated explicitly by programmers and it won’t be deallocated until it is explicitly freed [@jenny2022]. To store an object in the heap, you, the programmer, needs to explicitly tells Zig to do so, -by using an allocator to allocate some space in the heap. At @sec-allocators, I will present how you can use allocators to allocate memory +by using an allocator to allocate some space in the heap. In @sec-allocators, I will present how you can use allocators to allocate memory in Zig. ::: {.callout-important} @@ -393,7 +393,7 @@ object you declare is stored: Allocating memory on the stack is generally faster than allocating it on the heap. But this better performance comes with many restrictions. We have already discussed -many of these restrictions of the stack at @sec-stack. But there is one more important +many of these restrictions of the stack in @sec-stack. But there is one more important limitation that I want to talk about, which is the size of the stack itself. The stack is limited in size. This size varies from computer to computer, and it depends on @@ -495,7 +495,7 @@ but you don't need to change the function calls to the methods that do the memor ### Why you need an allocator? -As we described at @sec-stack, everytime you make a function call in Zig, +As we described in @sec-stack, everytime you make a function call in Zig, a space in the stack is reserved for this function call. But the stack has a key limitation which is: every object stored in the stack has a known fixed length. @@ -506,12 +506,12 @@ But in reality, there are two very common instances where this "fixed length lim 1. sometimes, it is impossible to know upfront how many inputs you will receive, or how big this input will be. Also, there is another instance where you might want to use an allocator, which is when you want to write a function that returns a pointer -to a local object. As I described at @sec-stack, you cannot do that if this local object is stored in the +to a local object. As I described in @sec-stack, you cannot do that if this local object is stored in the stack. However, if this object is stored in the heap, then, you can return a pointer to this object at the end of the function. Because you (the programmer) control the lifetime of any heap memory that you allocate. You decide when this memory gets destroyed/freed. -These are common situations for which the stack is not good. +These are common situations for which the stack is not good. That is why you need a different memory management strategy to store these objects inside your function. You need to use a memory type that can grow together with your objects, or that you @@ -622,7 +622,7 @@ the stack, or, from the heap. It all depends on where the buffer object that you In the above example, the `buffer` object lives in the stack, and, therefore, the memory allocated is based in the stack. But what if it was based on the heap? -As we described at @sec-stack-overflow, one of the main reasons why you would use the heap, +As we described in @sec-stack-overflow, one of the main reasons why you would use the heap, instead of the stack, is to allocate huge amounts of space to store very big objects. Thus, let's suppose you wanted to use a very big buffer object as the basis for your allocator objects. You would have to allocate this very big buffer object on the heap. @@ -699,7 +699,7 @@ you can create an array to store any type of value you want. Next, on the second define the size of the allocated array, by specifying how many elements this array will contain. In the case below, we are allocating an array of 50 elements. -At @sec-zig-strings we described that strings in Zig are simply arrays of characters. +In @sec-zig-strings we described that strings in Zig are simply arrays of characters. Each character is represented by a `u8` value. So, this means that the array that was allocated in the object `input` is capable of storing a string that is 50-characters long. @@ -732,12 +732,12 @@ pub fn main() !void { } ``` -Also, notice that in this example, we use the `defer` keyword (which I described at @sec-defer) to run a small +Also, notice that in this example, we use the `defer` keyword (which I described in @sec-defer) to run a small piece of code at the end of the current scope, which is the expression `allocator.free(input)`. When you execute this expression, the allocator will free the memory that it allocated for the `input` object. -We have talked about this at @sec-heap. You **should always** explicitly free any memory that you allocate +We have talked about this in @sec-heap. You **should always** explicitly free any memory that you allocate using an allocator! You do that by using the `free()` method of the same allocator object you used to allocate this memory. The `defer` keyword is used in this example only to help us execute this free operation at the end of the current scope. @@ -787,6 +787,3 @@ pub fn main() !void { user.* = User.init(0, "Pedro"); } ``` - - - diff --git a/Chapters/01-zig-weird.qmd b/Chapters/01-zig-weird.qmd index 1a1afa74..4b395303 100644 --- a/Chapters/01-zig-weird.qmd +++ b/Chapters/01-zig-weird.qmd @@ -60,7 +60,7 @@ your C code. With macros, you are no longer 100% sure about which pieces of the code are being sent to the compiler, i.e. they obscure the actual source code that you wrote. -You don't have macros in Zig. In Zig, the code you write, is the actual code that get's compiled by the compiler. +You don't have macros in Zig. In Zig, the code you write, is the actual code that gets compiled by the compiler. You also don't have a hidden control flow happening behind the scenes. And, you also don't have functions or operators from the standard library that make hidden memory allocations behind your back. @@ -125,7 +125,7 @@ tree . The `init` command also creates two additional files in our working directory: `build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig. This script is executed when you call the `build` command from the `zig` compiler. -In other words, this file contain Zig code that executes the necessary steps to build the entire project. +In other words, this file contains Zig code that executes the necessary steps to build the entire project. Low-level languages normally use a compiler to build your @@ -150,9 +150,8 @@ these build systems separately. In Zig, we don't need to use a separate set of tools to build our projects, because a build system is embedded inside the language itself. -Therefore, Zig contains a native build system in it, and -we can use this build system to write small scripts in Zig, -which describes the necessary steps to build/compile our Zig project[^zig-build-system]. +We can use this build system to write small scripts in Zig, +which describe the necessary steps to build/compile our Zig project[^zig-build-system]. So, everything you need to build a complex Zig project is the `zig` compiler, and nothing more. @@ -199,9 +198,9 @@ In this example, we are importing the `std` module, which gives you access to the Zig Standard Library. In this `root.zig` file, we can also see how assignments (i.e. creating new objects) -are made in Zig. You can create a new object in Zig by using the following syntax +are made in Zig. You can create a new object in Zig by using the syntax `(const|var) name = value;`. In the example below, we are creating two constant -objects (`std` and `testing`). At @sec-assignments we talk more about objects in general. +objects (`std` and `testing`). In @sec-assignments we talk more about objects in general. ```{zig} @@ -222,7 +221,7 @@ The function returns an integer of the type `i32` as result. Zig is a strongly-typed language. There are some specific situations where you can (if you want to) omit the type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more -about that at @sec-type-inference). But there are other situations where you do need to be explicit. +about that in @sec-type-inference). But there are other situations where you do need to be explicit. For example, you do have to explicitly specify the type of each function argument, and also, the return type of every function that you create in Zig. @@ -258,7 +257,7 @@ First, look at the return type of the `main()` function in this file. We can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`). This exclamation mark tells us that this `main()` function might return an error. -Is worth noting that, a `main()` function in Zig is allowed to return nothing (`void`), +It's worth noting that, a `main()` function in Zig is allowed to return nothing (`void`), or an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig to return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function, which returns an integer value that usually serves as a "status code" for the process. @@ -391,14 +390,14 @@ includes some global variables whose initialization rely on runtime resources, t you might have some troubles while trying to compile this Zig code on Windows. An example of that is accessing the `stdout` (i.e. the *standard output* of your system), which is usually -done in Zig by using the expression `std.io.getStdOut()`. Thus, if you use this expression to instantiate +done in Zig by using the expression `std.io.getStdOut()`. If you use this expression to instantiate a global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows, -with a "unable to evaluate comptime expression" error message. +with an "unable to evaluate comptime expression" error message. This failure in the compilation process happens because all global variables in Zig are initialized -at *compile-time*. However, operations like accessing the `stdout` (or opening a file) on Windows -depends on resources that are available only at *runtime* (you will learn more about compile-time -versus runtime at @sec-compile-time). +at *compile-time*. However, on Windows, operations like accessing the `stdout` (or opening a file) depend on +resources that are available only at *runtime* (you will learn more about compile-time versus runtime +in @sec-compile-time). For example, if you try to compile this code example on Windows, you will likely get the error message exposed below: @@ -430,7 +429,7 @@ that by simply moving the expression to a function body. This solves the problem because all expressions that are inside a function body in Zig are evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour. -You will learn more about this `comptime` keyword at @sec-comptime. +You will learn more about this `comptime` keyword in @sec-comptime. ```{zig} @@ -448,8 +447,8 @@ pub fn main() !void { Hello ``` -You can read more details about this Windows-specific limitation at a couple of -GitHub issues opened at the official Zig repository. More specifically, the issues +You can read more details about this Windows-specific limitation in a couple of +GitHub issues opened the official Zig repository. More specifically, the issues 17186 [^cissue1] and 19864 [^cissue2]. [^cissue1]: @@ -511,7 +510,7 @@ Hello, world! ## How to learn Zig? -What are the best strategies to learn Zig? +What are the best strategies to learn Zig? First of all, of course this book will help you a lot on your journey through Zig. But you will also need some extra resources if you want to be really good at Zig. @@ -675,7 +674,7 @@ On the other hand, you can, in fact, declare a new object in your source code, and not give it an explicit value. But we need to use a special keyword for that, which is the `undefined` keyword. -Is important to emphasize that, you should avoid using `undefined` as much as possible. +It's important to emphasize that, you should avoid using `undefined` as much as possible. Because when you use this keyword, you leave your object uninitialized, and, as a consequence, if for some reason, your code use this object while it is uninitialized, then, you will definitely have undefined behaviour and major bugs in your program. @@ -702,7 +701,7 @@ But in case you really need to declare an object without initializing it... the Every object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object to a function call, as a function argument, or, you can use it in another expression to calculate the value of another object, or, you can call a method that belongs to this -particular object. +particular object. It doesn't matter in which way you use it. As long as you use it. If you try to break this rule, i.e. if your try to declare a object, but not use it, @@ -771,7 +770,7 @@ t.zig:7:5: error: pointless discard This same rule applies to variable objects. Every variable object must also be used in some way. And if you assign a variable object to the underscore, -this object also get's discarded, and you can no longer use this object. +this object also gets discarded, and you can no longer use this object. @@ -857,7 +856,7 @@ const ls = [_]f64{432.1, 87.2, 900.05}; _ = ns; _ = ls; ``` -Is worth noting that these are static arrays, meaning that +It's worth noting that these are static arrays, meaning that they cannot grow in size. Once you declare your array, you cannot change the size of it. This is very common in low level languages. @@ -893,7 +892,7 @@ a range of indexes, and it have the syntax `start..end`. In the example below, at the second line of code, the `sl` object stores a slice (or a portion) of the `ns` array. More precisely, the elements at index 1 and 2 -in the `ns` array. +in the `ns` array. ```{zig} #| auto_main: true @@ -978,7 +977,7 @@ these are array operators. One important detail about these two operators is that they work only when both operands have a size (or "length") that is compile-time known. We are going to talk more about -the differences between "compile-time known" and "runtime known" at @sec-compile-time. +the differences between "compile-time known" and "runtime known" in @sec-compile-time. But for now, keep this information in mind, that you cannot use these operators in every situation. In summary, the `++` operator creates a new array that is the concatenation, @@ -995,7 +994,7 @@ try stdout.print("{any}\n", .{c}); ``` This `++` operator is particularly useful to concatenate strings together. -Strings in Zig are described in depth at @sec-zig-strings. In summary, a string object in Zig +Strings in Zig are described in depth in @sec-zig-strings. In summary, a string object in Zig is essentially an arrays of bytes. So, you can use this array concatenation operator to effectively concatenate strings together. @@ -1015,24 +1014,24 @@ try stdout.print("{any}\n", .{c}); ### Runtime versus compile-time known length in slices We are going to talk a lot about the differences between compile-time known -and runtime known across this book, especially at @sec-compile-time. +and runtime known across this book, especially in @sec-compile-time. But the basic idea is that a thing is compile-time known, when we know everything (the value, the attributes and the characteristics) about this thing at compile-time. In contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime. Therefore, we don't know the value of this thing at compile-time, only at runtime. -We have learned at @sec-select-array-elem that slices are created by using a *range selector*, +We have learned in @sec-select-array-elem that slices are created by using a *range selector*, which represents a range of indexes. When this "range of indexes" (i.e. the start and the end of this range) -is known at compile-time, the slice object that get's created is actually, under the hood, just +is known at compile-time, the slice object that gets created is actually, under the hood, just a single-item pointer to an array. You don't need to precisely understand what that means now. We are going to talk a lot about pointers -at @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time, -the slice that get's created is just a pointer to an array, accompanied by a length value that +in @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time, +the slice that gets created is just a pointer to an array, accompanied by a length value that tells the size of the slice. If you have a slice object like this, i.e. a slice that has a compile-time known range, -you can use common pointer operations over this slice object. For example, you can +you can use common pointer operations over this slice object. For example, you can dereference the pointer of this slice, by using the `.*` method, like you would do on a normal pointer object. @@ -1050,7 +1049,7 @@ const slice = arr1[1..4]; On the other hand, if the range of indexes is not known at compile time, then, the slice object -that get's created is not a pointer anymore, and, thus, it does not support pointer operations. +that gets created is not a pointer anymore, and, thus, it does not support pointer operations. For example, maybe the start index is known at compile time, but the end index is not. In such case, the range of the slice becomes runtime known only. @@ -1154,14 +1153,14 @@ Therefore, a string literal value have a data type in the format `*const [n:0]u8 indicates the size of the string. On the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes, -or, in other words, a slice of `u8` values (slices were presented at @sec-arrays). Thus, +or, in other words, a slice of `u8` values (slices were presented in @sec-arrays). Thus, a string object have a data type of `[]u8` or `[]const u8`, depending if the string object is marked as constant with `const`, or as variable with `var`. Because a string object is essentially a slice, it means that a string object always contains two things: a pointer to an array of bytes (i.e. `u8` values) that represents the string value; and also, a length value, which specifies the size of the slice, or, how many elements there is in the slice. -Is worth to emphasize that the array of bytes in a string object is not null-terminated, like in a +It's worth to emphasize that the array of bytes in a string object is not null-terminated, like in a string literal value. ```{zig} @@ -1337,7 +1336,7 @@ Type 4: []const u8 ### Byte vs unicode points -Is important to point out that each byte in the array is not necessarily a single character. +It's important to point out that each byte in the array is not necessarily a single character. This fact arises from the difference between a single byte and a single unicode point. The encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in @@ -1595,11 +1594,11 @@ program logic safety. These rules are: We already learned a lot about Zig's syntax, and also, some pretty technical details about it. Just as a quick recap: -- We talked about how functions are written in Zig at @sec-root-file and @sec-main-file. -- How to create new objects/identifiers at @sec-root-file and especially at @sec-assignments. -- How strings work in Zig at @sec-zig-strings. -- How to use arrays and slices at @sec-arrays. -- How to import functionality from other Zig modules at @sec-root-file. +- We talked about how functions are written in Zig in @sec-root-file and @sec-main-file. +- How to create new objects/identifiers in @sec-root-file and especially in @sec-assignments. +- How strings work in Zig in @sec-zig-strings. +- How to use arrays and slices in @sec-arrays. +- How to import functionality from other Zig modules in @sec-root-file. But, for now, this amount of knowledge is enough for us to continue with this book. @@ -1607,15 +1606,11 @@ Later, over the next chapters we will still talk more about other parts of Zig's syntax that are also equally important. Such as: -- How Object-Oriented programming can be done in Zig through *struct declarations* at @sec-structs-and-oop. -- Basic control flow syntax at @sec-zig-control-flow. -- Enums at @sec-enum; -- Pointers and Optionals at @sec-pointer; -- Error handling with `try` and `catch` at @sec-error-handling; -- Unit tests at @sec-unittests; -- Vectors at @sec-vectors-simd; -- Build System at @sec-build-system; - - - - +- How Object-Oriented programming can be done in Zig through *struct declarations* in @sec-structs-and-oop. +- Basic control flow syntax in @sec-zig-control-flow. +- Enums in @sec-enum; +- Pointers and Optionals in @sec-pointer; +- Error handling with `try` and `catch` in @sec-error-handling; +- Unit tests in @sec-unittests; +- Vectors in @sec-vectors-simd; +- Build System in @sec-build-system; diff --git a/Chapters/02-debugging.qmd b/Chapters/02-debugging.qmd index 46bfd83e..851c8d44 100644 --- a/Chapters/02-debugging.qmd +++ b/Chapters/02-debugging.qmd @@ -30,7 +30,7 @@ The key advantage that debugging offers you is *visibility*. With *print statements* you can easily see what results and objects are being produced by your application. -That is the essence of *print debugging*. Is to use +This is the essence of *print debugging* - using print expressions to see the values that are being generated by your program, and, as a result, get a much better understanding of how your program is behaving. @@ -157,7 +157,7 @@ By compiling your source code in `Debug` mode, you ensure that the debugger will find the necessary information in your program to debug it. By default, the compiler uses the `Debug` mode when compiling your code. Having this in mind, when you compile your program with the `build-exe` -command (which was described at @sec-compile-code), if you don't specify +command (which was described in @sec-compile-code), if you don't specify an explicit mode through the `-O` command-line [^oargument] argument, then, the compiler will compile your code in `Debug` mode. @@ -257,7 +257,7 @@ If we take a look at the value stored in the `n` object (`p n`), notice that it stores the hexadecimal value `0x06`, which is the number 6 in decimal. We can also see that this value has a type of `unsigned char`, which is an unsigned 8-bit integer. -We have talked already about this at @sec-zig-strings, that `u8` integers in Zig are equivalent +We have talked already about this in @sec-zig-strings, that `u8` integers in Zig are equivalent to the C data type `unsigned char`. @@ -346,4 +346,3 @@ pub fn main() !void { This function is similar to the `type()` built-in function from Python, or, the `typeof` operator in Javascript. - diff --git a/Chapters/03-structs.qmd b/Chapters/03-structs.qmd index 008c5e72..1f603615 100644 --- a/Chapters/03-structs.qmd +++ b/Chapters/03-structs.qmd @@ -352,7 +352,7 @@ functions, normal blocks, etc. This also affects the interpretation of `defer`. For example, if you use `defer` inside a for loop, then, the given expression will be executed everytime this specific for loop exits its own scope. -Before we continue, is worth emphasizing that the `defer` keyword is an "unconditional defer". +Before we continue, it's worth emphasizing that the `defer` keyword is an "unconditional defer". Which means that the given expression will be executed no matter how the code exits the current scope. For example, your code might exit the current scope because of an error value being generated, or, because of a return statement, or, a break statement, etc. @@ -378,7 +378,7 @@ But we are going to discuss `errdefer` later as a error handling tool in @sec-er The code example below demonstrates three things: -- that `defer` is an "unconditional defer", because the given expression get's executed regardless of how the function `foo()` exits its own scope. +- that `defer` is an "unconditional defer", because the given expression gets executed regardless of how the function `foo()` exits its own scope. - that `errdefer` is executed because the function `foo()` returned an error value. - that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order. @@ -410,7 +410,7 @@ You could also interpret this as: "defer expressions" are executed from bottom t from last to first. Therefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that -the value of `i` that get's printed to the console changes to 1. This doesn't mean that the +the value of `i` that gets printed to the console changes to 1. This doesn't mean that the `defer` expression was not executed in this case. This actually means that the `defer` expression was executed only after the `errdefer` expression. The code example below demonstrates this: @@ -1287,9 +1287,9 @@ are basically accessing the data members of the struct stored in the `std` object. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`) to access the data members and methods of the struct. -When this "import statement" get's executed, the result of this expression is a struct +When this "import statement" gets executed, the result of this expression is a struct object that contains the Zig Standard Library modules, global variables, functions, etc. -And this struct object get's saved (or stored) inside the constant object named `std`. +And this struct object gets saved (or stored) inside the constant object named `std`. Take the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread] @@ -1316,6 +1316,3 @@ const pool = ThreadPool.init( .{ .max_threads = num_threads } ); ``` - - - diff --git a/Chapters/03-unittests.qmd b/Chapters/03-unittests.qmd index 56cfb051..485f9da4 100644 --- a/Chapters/03-unittests.qmd +++ b/Chapters/03-unittests.qmd @@ -55,7 +55,7 @@ You can have multiple `test` blocks written on the same Zig module. Also, you can mix `test` blocks with your source code, with no problems or consequences. If you mix `test` blocks with your normal source code, when you execute the `build`, `build-exe`, `build-obj` or `build-lib` commands from the -`zig` compiler that we exposed at @sec-compile-code, these `test` blocks are automatically +`zig` compiler that we exposed in @sec-compile-code, these `test` blocks are automatically ignored by the compiler. In other words, the `zig` compiler builds and execute your unit tests only @@ -117,7 +117,7 @@ This is the `std.testing.allocator` object. This allocator object offers some basic memory safety detection features, which are capable of detecting memory leaks. -As we described at @sec-heap, to allocate memory on the heap, you need +As we described in @sec-heap, to allocate memory on the heap, you need to use an allocator object, and your functions that use these objects to allocate memory on the heap, should receive an allocator object as one of its inputs. Every memory on the heap that you allocate using these allocator objects, @@ -159,7 +159,7 @@ test "memory leak" { ``` Test [1/1] leak_memory.test.memory leak... - [gpa] (err): memory address 0x7c1fddf39000 leaked: + [gpa] (err): memory address 0x7c1fddf39000 leaked: ./ZigExamples/debugging/leak_memory.zig:4:39: 0x10395f2 const buffer = try allocator.alloc(u32, 10); ^ @@ -322,7 +322,7 @@ test "strings are equal?" { ``` ``` -1/1 t.test.strings are equal?... +1/1 t.test.strings are equal?... ====== expected this output: ========= hello, world!␃ ======== instead found this: ========= @@ -336,4 +336,3 @@ found: Hello, world! ^ ('\x48') ``` - diff --git a/Chapters/04-http-server.qmd b/Chapters/04-http-server.qmd index 4ba8c181..2cb1fe62 100644 --- a/Chapters/04-http-server.qmd +++ b/Chapters/04-http-server.qmd @@ -40,7 +40,7 @@ But the messages that are transmitted inside this connection are in a specific format. They are HTTP messages (i.e. messages that use the HTTP Protocol specification). The HTTP Protocol is the backbone of the modern web. -The world wide web as we know it today, would not exist without the +The world wide web as we know it today, would not exist without the HTTP Protocol. So, Web servers (which is just a fancy name to @@ -166,7 +166,7 @@ a separate Zig module. I will name it `config.zig`. In Zig, we can create a web socket using the `std.posix.socket()` function, from the Zig Standard Library. -As I mentioned earlier at @sec-http-how-impl, every socket object that we create +As I mentioned earlier in @sec-http-how-impl, every socket object that we create represents a communication channel, and we need to bind this channel to a specific address. An "address" is defined as an IP address, or, more specifically, an IPv4 address^[It can be also an IPv6 address. But normally, we use a IPv4 address for that.]. Every IPv4 address is composed by two components. The first component is the host, @@ -175,7 +175,7 @@ While the second component is a port number, which identifies the specific door, or, the specific port to use in the host machine. The sequence of 4 numbers (i.e. the host) identifies the machine (i.e. the computer itself) where -this socket will live in. Every computer normally have multiple "doors" available inside of him, because +this socket will live in. Every computer normally have multiple "doors" available inside of him, because this allows the computer to receive and work with multiple connections at the same time. He simply use a single door for each connection. So the port number, is essentially a number that identifies the specific door in the computer that will be responsible @@ -204,7 +204,7 @@ For TCP connections, which is our case here, a port number is a 16-bit unsigned integer (type `u16` in Zig), thus ranging from 0 to 65535 [@wikipedia_port]. So, we can choose -a number from 0 to 65535 for our port number. In the +a number from 0 to 65535 for our port number. In the example of this book, I will use the port number 3490 (just a random number). @@ -256,7 +256,7 @@ pub const Socket = struct { ### Listening and receiving connections Remember that we stored the `Socket` struct -declaration that we built at @sec-create-socket inside a Zig module named `config.zig`. +declaration that we built in @sec-create-socket inside a Zig module named `config.zig`. This is why I imported this module into our main module (`main.zig`) in the example below, as the `SocketConf` object, to access the `Socket` struct. @@ -435,7 +435,7 @@ will finally be executed to create the connection object that we need, and the remaining of the program will run. -You can see that at @fig-print-zigrun1. The message `Server Addr: 127.0.0.1:3490` +You can see that in @fig-print-zigrun1. The message `Server Addr: 127.0.0.1:3490` is printed to the console, and the program is now waiting for an incoming connection. ![A screenshot of running the program](./../Figures/print-zigrun1.png){#fig-print-zigrun1} @@ -473,7 +473,7 @@ when you have executed the program, you will see that the program finished its execution, and, a new message is printed in the console, which is the actual HTTP Request message that was sent by the web browser to the server. -You can see this message at @fig-print-zigrun2. +You can see this message in @fig-print-zigrun2. ![A screenshot of the HTTP Request sent by the web browser](./../Figures/print-zigrun2.png){#fig-print-zigrun2} @@ -680,7 +680,7 @@ But in order to build these functions, I will use a functionality from the Zig S In other words, we can use this map structure to map a string to the respective enum value. To some extent, this specific structure from the standard library works almost like a "hashtable" structure, and it is optimized for small sets of words, or, small sets of keys, which is our case here. -We are going to talk more about hashtables in Zig at @sec-maps-hashtables. +We are going to talk more about hashtables in Zig in @sec-maps-hashtables. To use this "static string map" structure, you have to import it from the `std.static_string_map` module of the Zig Standard Library. Just to make things shorter and easier to type, I am going to import this @@ -801,7 +801,7 @@ This is the line where we have the three information that we want to parse Therefore, we are using this `indexOfScalar()` function to limit our parsing process to the first line in the message. -Is also worth mentioning that, the `indexOfScalar()` function returns an optional value. +It's also worth mentioning that, the `indexOfScalar()` function returns an optional value. That is why I use the `orelse` keyword to provide an alternative value, in case the value returned by the function is a null value. @@ -843,11 +843,11 @@ pub fn parse_request(text: []u8) Request { ``` -As I described at @sec-zig-strings, strings in Zig are simply arrays of bytes in the language. +As I described in @sec-zig-strings, strings in Zig are simply arrays of bytes in the language. So, you will find lots of excellent utility functions to work directly with strings inside this `mem` module from the Zig Standard Library. We have described some of these useful utility functions already -at @sec-strings-useful-funs. +in @sec-strings-useful-funs. @@ -987,7 +987,7 @@ or not to decide which function to call. Also, notice that I'm using the function `std.mem.eql()` from the Zig Standard Library to check if the string from `uri` is equal or not the string `"/"`. We have -described this function already at @sec-strings-useful-funs, so, comeback to +described this function already in @sec-strings-useful-funs, so, comeback to that section if you are not familiar yet with this function. @@ -1036,4 +1036,3 @@ successfully to the web browser, as demonstrated by @fig-print-zigrun3. ![The Hello World message sent in the HTTP Response](./../Figures/print-zigrun3.png){#fig-print-zigrun3} - diff --git a/Chapters/05-pointers.qmd b/Chapters/05-pointers.qmd index 3e2d8dc1..bf8eba08 100644 --- a/Chapters/05-pointers.qmd +++ b/Chapters/05-pointers.qmd @@ -66,7 +66,7 @@ std.debug.print("{d}\n", .{doubled}); This syntax to dereference the pointer is nice. Because we can easily chain it with methods of the value pointed by the pointer. We can use the `User` struct that we have -created at @sec-structs-and-oop as an example. If you comeback to that section, +created in @sec-structs-and-oop as an example. If you comeback to that section, you will see that this struct have a method named `print_name()`. So, for example, if we have an user object, and a pointer that points to this user object, @@ -126,7 +126,7 @@ one of main reasons why pointers are used in programming languages. You can have a pointer that points to a constant object, or, a pointer that points to a variable object. But regardless of who this pointer is, a pointer **must always respect the characteristics of the object that it points to**. As a consequence, if the pointer points to a constant object, then, you cannot use this pointer -to change the value that it points to. Because it points to a value that is constant. As we discussed at @sec-assignments, you cannot +to change the value that it points to. Because it points to a value that is constant. As we discussed in @sec-assignments, you cannot change a value that is constant. For example, if I have a `number` object, which is constant, I cannot execute @@ -270,7 +270,7 @@ try stdout.print("{d}\n", .{ptr[0]}); Although you can create a pointer to an array like that, and start to walk through this array by using pointer arithmetic, -in Zig, we prefer to use slices, which were presented at @sec-arrays. +in Zig, we prefer to use slices, which were presented in @sec-arrays. Behind the hood, slices already are pointers, and they also come with the `len` property, which indicates @@ -280,7 +280,7 @@ can use it to check for potential buffer overflows, and other problems like that Also, you don't need to use pointer arithmetic to walk through the elements of a slice. You can simply use the `slice[index]` syntax to directly access any element you want in the slice. -As I mentioned at @sec-arrays, you can get a slice from an array by using +As I mentioned in @sec-arrays, you can get a slice from an array by using a range selector inside brackets. In the example below, I'm creating a slice (`sl`) that covers the entire `ar` array. I can access any element of `ar` from this slice, and, the slice itself already is a pointer @@ -505,5 +505,3 @@ p7.zig:12:34: 0x103419d in main (p7): [^un-docs]: . - - diff --git a/Chapters/07-build-system.qmd b/Chapters/07-build-system.qmd index 6bced377..d1dce207 100644 --- a/Chapters/07-build-system.qmd +++ b/Chapters/07-build-system.qmd @@ -47,7 +47,7 @@ for this particular task. ## How source code is built? We already have talked about the challenges of building source code in low-level languages -at @sec-project-files. As we described at that section, programmers invented Build Systems +in @sec-project-files. As we described at that section, programmers invented Build Systems to surpass these challenges on the process of building source code in low-level languages. Low-level languages uses a compiler to compile (or to build) your source code into binary instructions. @@ -73,7 +73,7 @@ If that is not your case, you can forget about it. Your build process is usually organized in a build script. In Zig, we normally write this build script into a Zig module in the root directory of our project, named as `build.zig`. You write this build script, then, when you run it, your project -get's built into binary files that you can use and distribute to your users. +gets built into binary files that you can use and distribute to your users. This build script is normally organized around *target objects*. A target is simply something to be built, or, in other words, it's something that you want the `zig` compiler @@ -89,19 +89,19 @@ There are four types of target objects that you can build in Zig, which are: - A static library (e.g. a `.a` file in Linux or a `.lib` file on Windows). - An executable file that executes only unit tests (or, a "unit tests executable"). -We are going to talk more about these target objects at @sec-targets. +We are going to talk more about these target objects in @sec-targets. ## The `build()` function {#sec-build-fun} A build script in Zig always contains a public (and top-level) `build()` function declared. -It is like the `main()` function on the main Zig module of your project, that we discussed at @sec-main-file. +It is like the `main()` function on the main Zig module of your project, that we discussed in @sec-main-file. But instead of creating the entrypoint to your code, this `build()` function is the entrypoint to the build process. This `build()` function should accept a pointer to a `Build` object as input, and it should use this "build object" to perform the necessary steps to build your project. The return type of this function is always `void`, -and this `Build` struct comes directly from the Zig Standard Library (`std.Build`). So, you can +and this `Build` struct comes directly from the Zig Standard Library (`std.Build`). So, you can access this struct by just importing the Zig Standard Library into your `build.zig` module. Just as a very simple example, here you can see the source code necessary to build @@ -145,7 +145,7 @@ The Zig Build System official documentation have a [great code example that demo A target object is created by the following methods of the `Build` struct that we introduced -at @sec-build-fun: +in @sec-build-fun: - `addExecutable()` creates an executable file; - `addSharedLibrary()` creates a shared library file; @@ -176,7 +176,7 @@ const exe = b.addExecutable(.{ The `name` option specify the name that you want to give to the binary file defined by this target object. So, in this example, we are building an executable file named `hello`. -Is common to set this `name` option to the name of your project. +It's common to set this `name` option to the name of your project. Furthermore, the `target` option specify the target computer architecture (or the target operating system) of this @@ -258,7 +258,7 @@ an "optimization vs safety" problem. So optimization plays an important role her Don't worry, I'm going back to this question very soon. In Zig, we have four build modes (which are listed below). Each one of these build modes offer -different advantages and characteristics. As we described at @sec-compile-debug-mode, the `zig` compiler +different advantages and characteristics. As we described in @sec-compile-debug-mode, the `zig` compiler uses the `Debug` build mode by default, when you don't explicitly choose a build mode. - `Debug`, mode that produces and includes debugging information in the output of the build process (i.e. the binary file defined by the target object); @@ -322,7 +322,7 @@ b.installArtifact(exe); ## Detecting the OS in your build script {#sec-detect-os} -Is very common in Build Systems to use different options, or, to include different modules, or, +It's very common in Build Systems to use different options, or, to include different modules, or, to link against different libraries depending on the Operational System (OS) that you are targeting in the build process. @@ -346,7 +346,7 @@ if (builtin.target.os.tag == .windows) { One thing that is neat in Rust is that you can compile and run your source code with one single command (`cargo run`) from the Rust compiler. -We saw at @sec-compile-run-code how can we perform a similar job in Zig, by +We saw in @sec-compile-run-code how can we perform a similar job in Zig, by building and running our Zig source code through the `run` command from the `zig` compiler. But how can we, at the same time, build and run the binary file specified by a target object in our @@ -446,7 +446,7 @@ zig build run ## Build unit tests in your project -We have talked at length about writing unit tests in Zig at @sec-unittests, +We have talked at length about writing unit tests in Zig in @sec-unittests, and we also have talked about how to execute these unit tests through the `test` command of the `zig` compiler. However, as we did with the `run` command on the previous section, we also might want to @@ -455,7 +455,7 @@ include some commands in our build script to also build and execute the unit tes So, once again, we are going to discuss how a specific built-in command from the `zig` compiler, (in this case, the `test` command) can be used in a build script in Zig. Here is where a "test target object" comes into play. -As was described at @sec-targets, we can create a test target object by using the `addTest()` method of +As was described in @sec-targets, we can create a test target object by using the `addTest()` method of the `Build` struct. The first thing that we need to do is to declare a test target object in our build script. @@ -570,9 +570,9 @@ that represent your code, into a single executable file. It also links this executable file to external libraries, if you use any in your code. In Zig, we have two notions of a "library", which are: 1) a system's library; -2) a local library. A system's library is just a library that already is installed +2) a local library. A system's library is just a library that is already installed in your system. While a local library is a library that belongs to the current -project. Is a library that is present in your project directory, and +project; a library that is present in your project directory, and that you are building together with your project source code. The basic difference between the two, is that a system's library is already @@ -732,7 +732,7 @@ const c_flags = [_][]const u8{ In theory, there is nothing stopping you from using this array to add "include paths" (with the `-I` flag) or "library paths" (with the `-L` flag) to the compilation process. But there are formal ways in Zig to -add these types of paths in the compilation process. Both are discussed at @sec-include-paths +add these types of paths in the compilation process. Both are discussed in @sec-include-paths and @sec-library-paths. Anyway, in Zig, we add C flags to the build process together with the C files that we want to compile, by using the @@ -786,7 +786,7 @@ across all C files, then, you will probably find `addCSourceFiles()` a better ch Notice that we are using the `addCSourceFiles()` method in the example below, to add both the C files and the C compiler flags. Also notice that we -are using the `os.tag` that we learned about at @sec-detect-os, to add the platform-specific +are using the `os.tag` that we learned about in @sec-detect-os, to add the platform-specific C files. ```{zig} @@ -896,4 +896,3 @@ const inc_path: std.Build.LazyPath = .{ }; lib.addIncludePath(inc_path); ``` - diff --git a/Chapters/09-data-structures.qmd b/Chapters/09-data-structures.qmd index 82d26f5b..4b8f99cd 100644 --- a/Chapters/09-data-structures.qmd +++ b/Chapters/09-data-structures.qmd @@ -74,7 +74,7 @@ is ready to receive a value to be stored. ![Difference between capacity and length in a dynamic array](./../Figures/dynamic-array.png){#fig-capacity-length} -We can also see at @fig-capacity-length that, when *length* and *capacity* are equal, it means that the array have no space left. +We can also see in @fig-capacity-length that, when *length* and *capacity* are equal, it means that the array have no space left. We have reached the ceiling of our capacity, and because of that, if we want to store more values in this array, we need to expand it. We need to get a bigger space that can hold more values than what we currently have. @@ -105,7 +105,7 @@ buffer.items.len; ### Creating an `ArrayList` object In order to use `ArrayList`, you must provide an allocator object to it. -Remember, Zig does not have a default memory allocator. And as I described at @sec-allocators, all memory +Remember, Zig does not have a default memory allocator. And as I described in @sec-allocators, all memory allocations must be done by an allocator object that you define, that you have control over. In our example here, I'm going to use a general purpose allocator, but you can use any other allocator @@ -159,7 +159,7 @@ as the `append()` method from a Python list, or, the `emplace_back()` method fro You provide a single value to this method, and the method appends this value to the array. You can also use the `appendSlice()` method to append multiple values at once. You provide -a slice (slices were described at @sec-arrays) to this method, and the method adds all values present +a slice (slices were described in @sec-arrays) to this method, and the method adds all values present in this slice to your dynamic array. ```{zig} @@ -175,7 +175,7 @@ try buffer.appendSlice(" World!"); ### Removing elements from the array {#sec-dynamic-array-remove} You can use the `pop()` method to "pop" or remove -the last element in the array. Is worth noting that this method +the last element in the array. It's worth noting that this method do not change the capacity of the array. It just deletes or erases the last value stored in the array. @@ -566,7 +566,7 @@ Some other properties of a `ArrayHashMap` hashtable are: You can create an `ArrayHashMap` object by using, once again, a helper function that chooses automatically for you a hash function implementation. This is the `AutoArrayHashMap()` function, which works very similarly to the `AutoHashMap()` -function that we presented at @sec-hashmap. +function that we presented in @sec-hashmap. You provide two data types to this function. The data type of the keys that will be used in this hashtable, and the data type of the values that will be stored in @@ -578,7 +578,7 @@ a value from the hashtable by using the `get()` method. But the `remove()` metho in this specific type of hashtable. In order to delete values from the hashtable, you would use the same methods that you find in -an `ArrayList` object, i.e. a dynamic array. I presented these methods at @sec-dynamic-array-remove, +an `ArrayList` object, i.e. a dynamic array. I presented these methods in @sec-dynamic-array-remove, which are the `swapRemove()` and `orderedRemove()` methods. These methods have the same meaning here, or, the same effect that they have in an `ArrayList` object. @@ -587,7 +587,7 @@ the order in which the values were inserted into the structure. While `orderedRe to retain the order in which these values were inserted. But instead of providing an index as input to `swapRemove()` or `orderedRemove()`, like I described -at @sec-dynamic-array-remove, these methods here in an `ArrayHashMap` take a key as input, like +in @sec-dynamic-array-remove, these methods here in an `ArrayHashMap` take a key as input, like the `remove()` method from a `HashMap` object. If you want to provide an index as input, instead of a key, you should use the `swapRemoveAt()` and `orderedRemoveAt()` methods. @@ -683,16 +683,16 @@ that preserves insertion order, and also, that uses strings as keys. You can create such type of hashtable by using the `StringArrayHashMap()` function. This function accepts a data type as input, which is the data type of the values that are going to be stored inside this hashtable, in the same style as the function presented -at @sec-string-hash-map. +in @sec-string-hash-map. You can insert new values into this hashtable by using the same `put()` method that -we have discussed at @sec-string-hash-map. And you can also get values from the hashtable +we have discussed in @sec-string-hash-map. And you can also get values from the hashtable by using the same `get()` method. Like its `ArrayHashMap` brother, to delete values from this specific type of hashtable, we also use the `orderedRemove()` and `swapRemove()` methods, with the same effects that -I have described at @sec-array-map. +I have described in @sec-array-map. -If we take the code example that was exposed at @sec-string-hash-map, we can +If we take the code example that was exposed in @sec-string-hash-map, we can achieve the exact same result with `StringArrayHashMap()`: ```{zig} @@ -716,7 +716,7 @@ connected to each other by pointers. This means that linked lists are usually no in memory, because each node might be anywhere in memory. They do not need to be close to one another. -At @fig-linked-list we can see a diagram of a singly linked list. We begin at the first node +In @fig-linked-list we can see a diagram of a singly linked list. We begin at the first node (which is usually called "the head of the linked list"). Then, from this first node we uncover the remaining nodes in the structure, by following the locations pointed by the pointers found in each node. @@ -728,7 +728,7 @@ is null, then, it means that we have reached the end of our linked list. ![A diagram of a singly linked list.](./../Figures/linked-list.png){#fig-linked-list} -At @fig-linked-list2 we can see a diagram of a doubly linked list. The only thing that really +In @fig-linked-list2 we can see a diagram of a doubly linked list. The only thing that really changes now is that every node in the linked list has both a pointer to the previous node, and, a pointer to the next node. So every node in a doubly linked list has two pointers in it. These are usually called the `prev` (for "previous") and the `next` (for "next") pointers of the node. @@ -742,7 +742,7 @@ normally have only the `next` pointer in them. Linked lists are available in Zig through the functions `SinglyLinkedList()` and `DoublyLinkedList()`, for "singly linked lists" and "doubly linked lists", respectively. These functions are -actually generic functions, which we are going to talk more about at @sec-generic-fun. +actually generic functions, which we are going to talk more about in @sec-generic-fun. For now, just understand that, in order to create a linked list object, we begin by providing a data type to these functions. This data type defines @@ -774,7 +774,7 @@ When you provide a node to this method, it creates a pointer to this input node, and stores this pointer in the `next` attribute of the current node, from which the method was called from. Because doubly linked lists have both a `next` and a `prev` attributes in each node -(as described at @fig-linked-list2), a node object created from +(as described in @fig-linked-list2), a node object created from a `DoublyLinkedList` object have both an `insertBefore()` (for `prev`) and an `insertAfter()` (for `next`) methods available. @@ -827,7 +827,7 @@ summary of them in the bullet points below: ## Multi array structure Zig introduces a new data structure called `MultiArrayList()`. It is a different version of the dynamic array -that we have introduced at @sec-dynamic-array. The difference between this structure and the `ArrayList()` +that we have introduced in @sec-dynamic-array. The difference between this structure and the `ArrayList()` that we know from @sec-dynamic-array, is that `MultiArrayList()` creates a separate dynamic array for each field of the struct that you provide as input. @@ -954,9 +954,3 @@ There are some very specific data structures in this list, like a [^home]: [^priority]: . [^bounded]: - - - - - - diff --git a/Chapters/09-error-handling.qmd b/Chapters/09-error-handling.qmd index 81df68fc..ea05ebc7 100644 --- a/Chapters/09-error-handling.qmd +++ b/Chapters/09-error-handling.qmd @@ -20,7 +20,7 @@ knitr::opts_chunk$set( In this chapter, I want to discuss how error handling is done in Zig. We already briefly learned about one of the available strategies to handle errors in Zig, -which is the `try` keyword presented at @sec-main-file. But we still haven't learned about +which is the `try` keyword presented in @sec-main-file. But we still haven't learned about the other methods, such as the `catch` keyword. I also want to discuss in this chapter how union types are created in Zig. @@ -73,7 +73,7 @@ t.zig:8:17: note: consider using 'try', 'catch', or 'if' ### Returning errors from functions -As we described at @sec-main-file, when we have a function that might return an error +As we described in @sec-main-file, when we have a function that might return an error value, this function normally includes an exclamation mark (`!`) in its return type annotation. The presence of this exclamation mark indicates that this function might return an error value as result, and, the `zig` compiler forces you to always handle explicitly @@ -138,7 +138,7 @@ Unions are used to allow an object to have multiple data types. For example, a union of `x`, `y` and `z`, means that an object can be either of type `x`, or type `y` or type `z`. -We are going to talk in more depth about unions at @sec-unions. +We are going to talk in more depth about unions in @sec-unions. But you can write an error set by writing the keyword `error` before a pair of curly braces, then you list the error values that can be returned from the function inside this pair of curly braces. @@ -269,7 +269,7 @@ return an error, we are basically referring to an expression that have a return type in the format `!T`. The `!` indicates that this expression returns either an error value, or a value of type `T`. -At @sec-main-file, I presented the `try` keyword and where to use it. +In @sec-main-file, I presented the `try` keyword and where to use it. But I did not talked about what exactly this keyword does to your code, or, in other words, I have not explained yet what `try` means in your code. @@ -446,18 +446,18 @@ our program to leak resources of the system. The `errdefer` keyword is a tool to perform such "cleanup actions" in hostile situations. This keyword is commonly used to clean (or to free) allocated resources, before the execution of our program -get's stopped because of an error value being generated. +gets stopped because of an error value being generated. The basic idea is to provide an expression to the `errdefer` keyword. Then, `errdefer` executes this expression if, and only if, an error occurs during the execution of the current scope. -In the example below, we are using an allocator object (that we have presented at @sec-allocators) +In the example below, we are using an allocator object (that we have presented in @sec-allocators) to create a new `User` object. If we are successful in creating and registering this new user, this `create_user()` function will return this new `User` object as its return value. However, if for some reason, an error value is generated by some expression that is after the `errdefer` line, for example, in the `db.add(user)` expression, -the expression registered by `errdefer` get's executed before the error value is returned +the expression registered by `errdefer` gets executed before the error value is returned from the function, and before the program enters in panic mode and stops the current execution. @@ -476,7 +476,7 @@ fn create_user(db: Database, allocator: Allocator) !User { By using `errdefer` to destroy the `user` object that we have just created, we guarantee that the memory allocated for this `user` object -get's freed, before the execution of the program stops. +gets freed, before the execution of the program stops. Because if the expression `try db.add(user)` returns an error value, the execution of our program stops, and we lose all references and control over the memory that we have allocated for the `user` object. @@ -485,19 +485,19 @@ we cannot free this memory anymore. We simply lose our chance to do the right th That is why `errdefer` is essential in this situation. Just to state clearly the differences between `defer` and `errdefer` -(which I described at @sec-defer and @sec-errdefer1), it might be worth +(which I described in @sec-defer and @sec-errdefer1), it might be worth to discuss the subject a bit further. You might still have the question "why use `errdefer` if we can use `defer` instead?" in your mind. Although being similar, the key difference between `errdefer` and `defer` keyword -is when the provided expression get's executed. +is when the provided expression gets executed. The `defer` keyword always execute the provided expression at the end of the current scope, no matter how your code exits this scope. In contrast, `errdefer` executes the provided expression only when an error occurs in the current scope. This becomes important if a resource that you allocate in the -current scope get's freed later in your code, in a different scope. +current scope gets freed later in your code, in a different scope. The `create_user()` functions is an example of this. If you think closely about this function, you will notice that this function returns the `user` object as the result. @@ -627,7 +627,7 @@ target = LakeTarget { }; ``` -A curious fact about union types, is that, at first, you cannot use them in switch statements (which were presented at @sec-switch). +A curious fact about union types, is that, at first, you cannot use them in switch statements (which were presented in @sec-switch). In other words, if you have an object of type `LakeTarget` for example, you cannot give this object as input to a switch statement. @@ -654,4 +654,3 @@ pub const Registry = union(enum) { extension: ExtensionRegistry, }; ``` - diff --git a/Chapters/10-stack-project.qmd b/Chapters/10-stack-project.qmd index ada7535d..3d9a8263 100644 --- a/Chapters/10-stack-project.qmd +++ b/Chapters/10-stack-project.qmd @@ -37,7 +37,7 @@ how generics work in Zig. One of the key features of Zig is `comptime`. This keyword introduces a whole new concept and paradigm, that is tightly connected with the compilation process. -At @sec-compile-time we have described the importance and the role that "compile-time versus runtime" +In @sec-compile-time we have described the importance and the role that "compile-time versus runtime" plays into Zig. At that section, we learned that the rules applied to a value/object change a lot depending on whether this value is known at compile-time, or just at runtime. @@ -59,7 +59,7 @@ There are three ways in which you can apply the `comptime` keyword, which are: When you apply the `comptime` keyword on a function argument, you are saying to the `zig` compiler that the value assigned to that particular function argument must be known at compile-time. -We explained in details at @sec-compile-time what exactly "value known at compile-time" means, so, +We explained in details in @sec-compile-time what exactly "value known at compile-time" means, so, in case you have doubts about this idea, come back to that section. Now let's think about the consequences of this idea. First of all, we are imposing a limit, or, a requirement @@ -114,12 +114,12 @@ test "test comptime" { ``` ``` -t.zig:12:16: error: runtime-known argument passed to comptime parameter +t.zig:12:16: error: runtime-known argument passed to comptime parameter ``` Comptime arguments are frequently used on functions that return some sort of generic structure. In fact, `comptime` is the essence (or the basis) to make generics in Zig. -We are going to talk more about generics at @sec-generics. +We are going to talk more about generics in @sec-generics. For now, let's take a look at this code example from @karlseguin_generics. You can see that this `IntArray()` function have one argument named `length`. @@ -140,7 +140,7 @@ think about the consequences of that. If the size of the array is dependent on the value assigned to the `length` argument, this means that the data type of the output of the function depends on the value of this `length` argument. -Let this statement sink for a bit in your mind. As I described at @sec-root-file, +Let this statement sink for a bit in your mind. As I described in @sec-root-file, Zig is a strongly-typed language, especially on function declarations. So every time we write a function in Zig, we have to annotate the data type of the value returned by the function. But how can we do that, if this data type @@ -156,7 +156,7 @@ and raise a compilation error, saying something like this: So how can you solve this problem? How do we overcome this barrier? This is when the `type` keyword comes in. This `type` keyword is basically saying to the `zig` compiler that this function will return some data type as output, but it doesn't know yet -what exactly data type that is. We will talk more about this at @sec-generics. +what exactly data type that is. We will talk more about this in @sec-generics. @@ -197,7 +197,7 @@ test "fibonacci" { A lot of your Zig source code might be potentially executed at compile-time, because the `zig` compiler can figure it out the output of some expressions. Especially if these expressions depends only at compile-time known values. -We have talked about this at @sec-compile-time. +We have talked about this in @sec-compile-time. But when you use the `comptime` keyword on an expression, there is no "it might be executed at compile-time" anymore. With the `comptime` keyword you are ordering the `zig` compiler @@ -209,7 +209,7 @@ the compiler will raise a compilation error. ### Applying over a block -Blocks were described at @sec-blocks. When you apply the `comptime` keyword over a +Blocks were described in @sec-blocks. When you apply the `comptime` keyword over a block of expressions, you get essentially the same effect when you apply this keyword to a single expression. That is, the entire block of expressions is executed at compile-time by the `zig` compiler. @@ -246,7 +246,7 @@ test "fibonacci in a block" { First of all, what is a generic? Generic is the idea to allow a type (`f64`, `u8`, `u32`, `bool`, and also, user-defined types, like the `User` struct -that we defined at @sec-structs-and-oop) to be a parameter to methods, classes and +that we defined in @sec-structs-and-oop) to be a parameter to methods, classes and interfaces [@geeks_generics]. In other words, a "generic" is a class (or a method) that can work with multiple data types. @@ -272,7 +272,7 @@ Notice that this `T` argument have a data type of `type`. Weird right? This `typ Because we have used this `type` keyword in the `T` argument, we are telling the `zig` compiler that this `T` argument will receive some data type as input. Also notice the use of the `comptime` keyword in this argument. -As I described at @sec-comptime, every time you use this keyword in a function argument, +As I described in @sec-comptime, every time you use this keyword in a function argument, this means that the value of this argument must be known at compile-time. This makes sense, right? Because there is no data type that is not known at compile-time. @@ -438,7 +438,7 @@ responsible for adding a new value to the stack. So how can we add a new value to the `Stack` object that we have? The `push()` function exposed below is a possible answer to this question. -Remember from what we discussed at @sec-what-stack that values are always added to the top of the stack. +Remember from what we discussed in @sec-what-stack that values are always added to the top of the stack. This means that this `push()` function must always find the element in the underlying array that currently represents the top position of the stack, and then, add the input value there. @@ -565,7 +565,7 @@ For example, we might need to create a stack object to store `User` values in it. How can we make this possible? The answer lies on the use of generics and `comptime`. -As I described at @sec-generic-struct, the basic idea is to write a generic +As I described in @sec-generic-struct, the basic idea is to write a generic function that returns a struct definition as output. In theory, we do not need much to transform our `Stack` struct into a generic data structure. All that we need to do is to transform the underlying array @@ -686,4 +686,3 @@ for the generic version, available inside the `ZigExamples` folder of the reposi [^zig-stack]: [^zig-stack2]: - diff --git a/Chapters/12-file-op.qmd b/Chapters/12-file-op.qmd index 0a880e28..cdf64326 100644 --- a/Chapters/12-file-op.qmd +++ b/Chapters/12-file-op.qmd @@ -89,7 +89,7 @@ receiving new data from users, or, as another example, a live chat in a game tha receiving and displaying new messages from the players of the game. [^gen-zig]: Previously, these objects were known as the `Reader` and `Writer` objects. -[^sock]: The socket objects that we have created at @sec-create-socket, are examples of network sockets. +[^sock]: The socket objects that we have created in @sec-create-socket, are examples of network sockets. So, if you want to **read** data from something, or somewhere, it means that you need to use a `GenericReader` object. But if you need instead, to **write** data into this "something", then, you need to use a `GenericWriter` object instead. @@ -173,7 +173,7 @@ a file descriptor to this particular IO resource. So you usually get a `File` object by using functions and methods from the Zig Standard Library that asks the OS to open some IO resource, like the `openFile()` method that opens a file in the -filesystem. The `net.Stream` object that we have created at @sec-create-socket is also a type of +filesystem. The `net.Stream` object that we have created in @sec-create-socket is also a type of file descriptor object. @@ -277,7 +277,7 @@ the purpose of this channel. ## Buffered IO -As we described at @sec-io-basics, input/output (IO) operations are made directly by the operating system. +As we described in @sec-io-basics, input/output (IO) operations are made directly by the operating system. It is the OS that manages the IO resource that you want to use for your IO operations. The consequence of this fact is that IO operations are heavily based on system calls (i.e. calling the operating system directly). @@ -294,16 +294,16 @@ the number of system calls performed to a minimum. ### Understanding how buffered IO works Buffered IO is a strategy to achieve better performance. It is used to reduce the number of system calls made by IO operations, and, as -consequence, achieve a much higher performance. At @fig-unbuffered-io and @fig-buffered-io you can find two different diagrams +consequence, achieve a much higher performance. In @fig-unbuffered-io and @fig-buffered-io you can find two different diagrams which presents the difference between read operations performed in an unbuffered IO environment versus a buffered IO environment. To give a better context to these diagrams, let's suppose that we have a text file that contains the famous Lorem ipsum text[^lorem] -in our filesystem. Let's also suppose that these diagrams at @fig-unbuffered-io and @fig-buffered-io +in our filesystem. Let's also suppose that these diagrams in @fig-unbuffered-io and @fig-buffered-io are showing the read operations that we are performing to read the Lorem ipsum text from this text file. The first thing you will notice when looking at these diagrams, is that in an unbuffered environment the read operations leads to many system calls. -More precisely, in the diagram exposed at @fig-unbuffered-io we get one system call per each byte that we read from the text file. -On the other hand, at @fig-buffered-io we have only one system call at the very beginning. +More precisely, in the diagram exposed in @fig-unbuffered-io we get one system call per each byte that we read from the text file. +On the other hand, in @fig-buffered-io we have only one system call at the very beginning. When we use a buffered IO system, at the first read operation we perform, instead of sending one single byte directly to our program, the OS first sends a chunk of bytes from the file to a buffer object (i.e. an array). @@ -342,7 +342,7 @@ buffered depending on which functions from the standard libraries that you are u For example, in Rust, buffered IO is implemented through the `BufReader` and `BufWriter` structs, while in Zig, it is implemented through the `BufferedReader` and `BufferedWriter` structs. So any IO operation that you perform through the `GenericWriter` and `GenericReader` objects -that I presented at @sec-writer-reader are not buffered, which means that these objects +that I presented in @sec-writer-reader are not buffered, which means that these objects might create a lot of system calls depending on the situation. @@ -364,7 +364,7 @@ function, which creates a new `BufferedWriter` or `BufferedReader` object. Then, the `writer()` or `reader()` methods of this buffered writer or buffered reader object, which gives you access to a generic writer or a generic reader object that is buffered. -Take this program as an example. This program is demonstrating the process exposed at @fig-buffered-io. +Take this program as an example. This program is demonstrating the process exposed in @fig-buffered-io. We are simply opening a text file that contains the Lorem ipsum text, and then, we create a buffered IO reader object at `bufreader`, and we use this `bufreader` object to read the contents of this file into a buffer object, then, we end the program by printing this buffer to `stdout`. @@ -410,7 +410,7 @@ and have the exact same methods. So, although these two types of objects perform they have the same interface, so you, the programmer, can interchangeably use them without the need to change anything in your source code. So a buffered IO reader or a buffered IO writer objects have the same methods than its generic and unbuffered brothers, -i.e. the generic reader and generic writer objects that I presented at @sec-writer-reader. +i.e. the generic reader and generic writer objects that I presented in @sec-writer-reader. ::: {.callout-tip} In general, you should always use a buffered IO reader or a buffered IO writer object to perform @@ -423,7 +423,7 @@ IO operations in Zig. Because they deliver better performance to your IO operati Now that we have discussed the basics around Input/Output operations in Zig, we need to talk about the basics around filesystems, which is another core part of any operating system. Also, filesystems are related to input/output, because the files that we store and create in our -computer are considered an IO resource, as we described at @sec-file-descriptor. +computer are considered an IO resource, as we described in @sec-file-descriptor. ### The concept of current working directory (CWD) @@ -440,7 +440,7 @@ in the terminal. In other words, if you are in the terminal of your OS, and you execute a binary file (i.e. a program) from this terminal, the folder to which your terminal is pointing at is the current working directory of your program that is being executed. -At @fig-cwd we have an example of me executing a program from the terminal. We are executing +In @fig-cwd we have an example of me executing a program from the terminal. We are executing the program outputted by the `zig` compiler by compiling the Zig module named `hello.zig`. The CWD in this case is the `zig-book` folder. In other words, while the `hello.zig` program is executing, it will be looking at the `zig-book` folder, and any file operation that we perform @@ -475,7 +475,7 @@ On Windows, the backward slash (`\`) is normally used to connect the path segmen slash (`/`) is the character used to connect path segments. A relative path is a path that start at the CWD. In other words, a relative path is -"relative to the CWD". The path used to access the `hello.zig` file at @fig-cwd is an example of a relative path. This path +"relative to the CWD". The path used to access the `hello.zig` file in @fig-cwd is an example of a relative path. This path is reproduced below. This path begins at the CWD, which in the context of @fig-cwd, is the `zig-book` folder, then, it goes to the `ZigExamples` folder, then, into `zig-basics`, then, to the `hello.zig` file. @@ -544,7 +544,7 @@ do the necessary steps to create such file. You can also provide a relative path and it will create the file by following this path, which is relative to the CWD. This function might return an error, so, you should use `try`, `catch`, or any of the other methods presented -at @sec-error-handling to handle the possible error. But if everything goes well, +in @sec-error-handling to handle the possible error. But if everything goes well, this `createFile()` method returns a file descriptor object (i.e. a `File` object) as result, through which you can add content to the file with the IO operations that I presented before. @@ -600,7 +600,7 @@ get a `NotOpenForReading` error as result. But how can you overcome this barrier? How can you create a file that is open to read operations? All you have to do, is to set the `read` flag to true in the second argument of `createFile()`. When you set this flag to true, -then the file get's create with "read permissions", and, as consequence, +then the file gets create with "read permissions", and, as consequence, a program like this one below becomes valid: @@ -634,7 +634,7 @@ We are going to read this line If you are not familiar with position indicators, you might not recognize the method `seekTo()`. If that is your case, do not worry, -we are going to talk more about this method at @sec-indicators. But essentially +we are going to talk more about this method in @sec-indicators. But essentially this method is moving the position indicator back to the beginning of the file, so that we can read the contents of the file from the beginning. @@ -649,11 +649,11 @@ that dictates how the file is opened. You can see the full list of options for `openFile()` by visiting the documentation for [`OpenFlags`](https://ziglang.org/documentation/master/std/#std.fs.File.OpenFlags)[^oflags]. But the main flag that you will most certainly use is the `mode` flag. -This flag specifies the IO mode that the file will be using when it get's opened. +This flag specifies the IO mode that the file will be using when it gets opened. There are three IO modes, or, three values that you can provide to this flag, which are: - `read_only`, allows only read operations on the file. All write operations are blocked. -- `write_only`, allows only write operations on the file. All read operations are blocked. +- `write_only`, allows only write operations on the file. All read operations are blocked. - `read_write`, allows both write and read operations on the file. [^oflags]: @@ -664,7 +664,7 @@ These modes are similar to the modes that you provide to the `mode` argument of In the code example below, we are opening the `foo.txt` text file with a `write_only` mode, and appending a new line of text to the end of the file. We use `seekFromEnd()` this time to guarantee that we are going to append the text to the end of the file. Once again, methods -such as `seekFromEnd()` are described in more depth at @sec-indicators. +such as `seekFromEnd()` are described in more depth in @sec-indicators. [^py-open]: [^c-open]: @@ -754,7 +754,7 @@ to write 50 bytes into this same file, these 50 bytes will be written from the c position indicated by the position indicator. Since the indicator is at a 100 bytes forward from the beginning of the file, these 50 bytes would be written in the middle of the file. -This is why we have used the `seekTo()` method at the last code example presented at @sec-creating-files. +This is why we have used the `seekTo()` method at the last code example presented in @sec-creating-files. We have used this method to move the position indicator back to the beginning of the file, which would make sure that we would write the text that we wanted to write from the beginning of the file, instead of writing it from the middle of the file. Because before the write operation, we had @@ -884,7 +884,3 @@ or how to open a directory, or how to create symbolic links, or how to use `acce path exists in your computer. But for all of these less common tasks, I recommend you to read the documentation of the [`Dir` type](https://ziglang.org/documentation/master/std/#std.fs.Dir)[^zig-dir] , since you can find a good description of these cases there. - - - - diff --git a/Chapters/13-image-filter.qmd b/Chapters/13-image-filter.qmd index 66e83e96..513b83c3 100644 --- a/Chapters/13-image-filter.qmd +++ b/Chapters/13-image-filter.qmd @@ -22,7 +22,7 @@ this project is to write a program that applies a filter over an image. More specifically, a "grayscale filter", which transforms any color image into a grayscale image. -We are going to use the image displayed at @fig-pascal in this project. +We are going to use the image displayed in @fig-pascal in this project. In other words, we want to transform this colored image into a grayscale image, by using our "image filter program" written in Zig. @@ -34,9 +34,9 @@ by explaining the theory behind digital images and how colors are represented in We also give a brief explanation about the PNG (Portable Network Graphics) file format, which is the format used in the example images. -At the end of this chapter, we should have a full example of a program that takes the PNG image displayed at @fig-pascal +At the end of this chapter, we should have a full example of a program that takes the PNG image displayed in @fig-pascal as input, and writes a new image to the current working directory that is the grayscale version of this input image. -This grayscale version of @fig-pascal is exposed at @fig-pascal-gray. +This grayscale version of @fig-pascal is exposed in @fig-pascal-gray. You can find the full source code of this small project at the `ZigExamples/image_filter` [folder at the official repository of this book](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/image_filter)[^img-filter-folder]. @@ -131,13 +131,13 @@ and 70 of blue. In contrast, the set `(129, 77, 250)` describes a color that is This is not a rule written in stone, but the big majority of digital images are displayed from top to bottom and left to right. Most computers screens also follow this pattern. So, the first pixels in the image are the ones that are at the top and left corner of the image. You can find a visual representation -of this logic at @fig-img-display. +of this logic in @fig-img-display. Also notice in @fig-img-display that, because a raster image is essentially a 2D matrix of pixels, the image is organized into rows and columns of pixels. The columns are defined by the horizontal x axis, while the rows are defined by the vertical y axis. -Each pixel (i.e. the gray rectangles) exposed at @fig-img-display contains a number inside of it. +Each pixel (i.e. the gray rectangles) exposed in @fig-img-display contains a number inside of it. These numbers are the indexes of the pixels. You can notice that the first pixels are in the top and left corner, and also, that the indexes of these pixels "grow to the sides", or, in other words, they grow in the direction of the horizontal x axis. Most raster images are organized as rows of pixels. Thus, when these digital images are @@ -214,9 +214,9 @@ to store this image in our Zig code, we need to create an array whose size is a Let's begin our project by focusing on writing the necessary Zig code to read the data from the PNG file. In other words, we want to read the PNG file exposed -at @fig-pascal, and parse its data to extract the 2D matrix of pixels that represents the image. +in @fig-pascal, and parse its data to extract the 2D matrix of pixels that represents the image. -As we have discussed at @sec-pixel-repr, the image that we are using as example here +As we have discussed in @sec-pixel-repr, the image that we are using as example here is a PNG file that uses the RGBA color model, and, therefore, each pixel of the image is represented by 4 integer values. You can download this image by visiting the `ZigExamples/image_filter` [folder at the official repository of this book](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/image_filter)[^img-filter-folder]. @@ -259,7 +259,7 @@ a function called `spng_decode_image()` that does all this heavy work for us. Now, since `libspng` is a C library, most of the file and I/O operations in this library are made by using a `FILE` C pointer. Because of that, is probably a better idea to use the `fopen()` C function -to open our PNG file, instead of using the `openFile()` method that I introduced at @sec-filesystem. +to open our PNG file, instead of using the `openFile()` method that I introduced in @sec-filesystem. That is why I'm importing the `stdio.h` C header in this project, and using the `fopen()` C function to open the file. If you look at the snippet below, you can see that we are: @@ -328,7 +328,7 @@ image header section of the PNG file. Since this Zig function is receiving a C object (the `libspng` context object) as input, I marked the function argument `ctx` as "a pointer to the context object" (`*c.spng_ctx`), following the recommendations -that we have discussed at @sec-pass-c-structs. +that we have discussed in @sec-pass-c-structs. ```{zig} #| eval: false @@ -463,7 +463,7 @@ the first $12 / 4 = 3$ pixels in the image. So, based on how these first 12 bytes (or these 3 pixels) look, with these 255 values at every 4 bytes, we can say that is likely that every pixel in the image have alpha (or transparency) setted to 100%. This might not be true, but, is the most likely possibility. Also, if we look at the image itself, which if your recall is -exposed at @fig-pascal, we can see that the transparency does not change across the image, +exposed in @fig-pascal, we can see that the transparency does not change across the image, which enforces this theory. @@ -503,7 +503,7 @@ $$ p' = (0.2126 \times r) + (0.7152 \times g) + (0.0722 \times b) $${#eq-grayscale} -This @eq-grayscale is the formula to calculate the linear luminance of a pixel. Is worth noting that this formula +This @eq-grayscale is the formula to calculate the linear luminance of a pixel. It's worth noting that this formula works only for images whose pixels are using the sRGB color space, which is the standard color space for the web. Thus, ideally, all images on the web should use this color space. Luckily, this is our case here, i.e. the `pedro_pascal.png` image is using this sRGB color space, and, as consequence, @@ -610,7 +610,7 @@ try save_png(&image_header, buffer[0..]); After we execute this `save_png()` function, we should have a new PNG file inside our CWD, named `pedro_pascal_filter.png`. If we open this PNG file, -we will see the same image exposed at @fig-pascal-gray. +we will see the same image exposed in @fig-pascal-gray. ## Building our project @@ -662,5 +662,3 @@ running the `zig build` command in the terminal. ```bash zig build ``` - - diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 8ddbc00a..3dd7802b 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -119,7 +119,7 @@ this `send_order()` function returns almost immediately, so the waiter spends almost no time worrying about the order, and just move on and tries to get the next order from the clients. -Inside the new thread created, the order get's cooked by a chef, and when the +Inside the new thread created, the order gets cooked by a chef, and when the food is ready, it is delivered to the client's table. @@ -203,15 +203,15 @@ This method have three arguments, which are, respectively: 1. the name of the function that is going to be executed (or, that is going to be "called") inside this new thread. 1. a list of arguments (or inputs) to be passed to the function provided in the second argument. -With these three arguments, you can control how the thread get's created, and also, specify which +With these three arguments, you can control how the thread gets created, and also, specify which work (or "tasks") will be performed inside this new thread. A thread is just a separate context of execution, and we usually create new threads in our code, because we want to perform some work inside this new context of execution. And we specify which exact work, or, which exact steps that are going to be performed inside this context, by providing the name of a function on the second argument of the `spawn()` method. -Thus, when this new thread get's created, this function that you provided as input to the `spawn()` -method get's called, or, get's executed inside this new thread. You can control the -arguments, or, the inputs that are passed to this function when it get's called, by providing +Thus, when this new thread gets created, this function that you provided as input to the `spawn()` +method gets called, or, gets executed inside this new thread. You can control the +arguments, or, the inputs that are passed to this function when it gets called, by providing a list of arguments (or a list of inputs) on the third argument of the `spawn()` method. These arguments are passed to the function in the same order that they are provided to `spawn()`. @@ -264,19 +264,19 @@ But, if the new thread is successfully created, the `spawn()` method returns a h object (which is just an object of type `Thread`) to this new thread. You can use this handler object to effectively control all aspects of the thread. -When the thread get's created, the function that you provided as input to `spawn()` -get's invoked (i.e. get's called) to start the execution on this new thread. -In other words, everytime you call `spawn()`, not only a new thread get's created, -but also, the "start work button" of this thread get's automatically pressed. +When the thread gets created, the function that you provided as input to `spawn()` +gets invoked (i.e. gets called) to start the execution on this new thread. +In other words, everytime you call `spawn()`, not only a new thread gets created, +but also, the "start work button" of this thread gets automatically pressed. So the work being performed in this thread starts at the moment that the thread is created. This is similar to how `pthread_create()` from the `pthreads` library in C works, -which also starts the execution at the moment that the thread get's created. +which also starts the execution at the moment that the thread gets created. ## Returning from a thread We have learned on the previous section that the execution of the thread starts at the moment -that the thread get's created. Now, we will learn how to "join" or "detach" a thread in Zig. +that the thread gets created. Now, we will learn how to "join" or "detach" a thread in Zig. "Join" and "detach" are operations that control how the thread returns to the main thread, or, to the main process in our program. @@ -291,7 +291,7 @@ that you cannot call both `join()` and `detach()` on the same thread. But a thread must be one of the two, meaning that, you should always call either `join()` or `detach()` over a thread. If you don't call one of these two methods over your thread, you introduce undefined behaviour into your program, -which is described at @sec-not-call-join-detach. +which is described in @sec-not-call-join-detach. Now, let's describe what each of these two methods do to your thread. @@ -305,7 +305,7 @@ and just called `join()` over this thread at the end. This section of the code e Because we are joining this new thread inside the `main()`'s scope, it means that the execution of the `main()` function is temporarily stopped, to wait for the execution of the thread -to finish. That is, the execution of `main()` stops temporarily at the line where `join()` get's called, +to finish. That is, the execution of `main()` stops temporarily at the line where `join()` gets called, and it will continue only after the thread has finished its tasks. ```{zig} @@ -379,7 +379,7 @@ or vice-versa. This happens because: - the threads are executing basically at the same time as the main process of the program (i.e. the `main()` function). - the threads share the same `stdout` from the main process of the program, which means that the messages that the threads produce are sent to exact same place as the messages produced by the main process. -Both of these points were described previously at @sec-what-thread. +Both of these points were described previously in @sec-what-thread. So the messages might get intertwined because they are being produced and sent to the same `stdout` roughly at the same time. Anyway, when you call `join()` over a thread, the current process will wait @@ -425,7 +425,7 @@ Finish main Now, if you look closely at the output of this code example, you will notice that only the final message in main was printed to the console. The message that was supposed to be printed by `print_id()` did not appear in the console. -Why? Is because the main process of our program has finished first, +Why? It's because the main process of our program has finished first, before the thread was able to say anything. And that is perfectly ok behaviour, because the thread was detached, so, it was @@ -615,7 +615,7 @@ In summary, an operation is categorized as "atomic", when there is no way to hap the middle of this operation. In other words, this operation is always done from beginning to end, without interruptions of another process or operation in the middle of its execution phase. -Not many operations today are atomic. But why atomic operations matters here? Is because data races +Not many operations today are atomic. But why do atomic operations matter here? It's because data races (which is a type of a race condition) cannot happen on operations that are atomic. So if a particular line in your code performs an atomic operation, then, this line will never suffer from a data race problem. Therefore, programmers sometimes use an atomic operation @@ -631,7 +631,7 @@ In this module, you will find a public and generic function called `Value()`. Wi a value that contains some native atomic operations, most notably, a `load()` and a `fetchAdd()` operation. If you have experience with multithreading in C++, you probably have recognized this pattern. So yes, this generic "atomic object" in Zig is essentially identical to the template struct `std::atomic` from the C++ Standard Library. -Is important to emphasize that only primitive data types (i.e. the types presented at @sec-primitive-data-types) +It's important to emphasize that only primitive data types (i.e. the types presented in @sec-primitive-data-types) are supported by these atomic operations in Zig. @@ -646,13 +646,13 @@ which happens when one thread is accessing a particular memory location (i.e. a time that another thread is trying to write/save new data into this same memory location (i.e. the same shared object). We can simply define a race condition as any type of bug in your program that is based -on a "who get's there first" problem. A data race problem is a type of a race condition, because it occurs when two or more parties +on a "who gets there first" problem. A data race problem is a type of a race condition, because it occurs when two or more parties are trying to read and write into the same memory location at the same time, and, therefore, the end result of this operation -depends completely on who get's to this memory location first. +depends completely on who gets to this memory location first. As consequence, a program that have a data race problem will likely produce a different result each time that we execute it. Thus, race conditions produce undefined behaviour and unpredictability because the program produces -a different answer in each time that a different person get's to the target location first than the others. +a different answer in each time that a different person gets to the target location first than the others. And we have no easy way to either predict or control who is getting to this target location first. In other words, in each execution of your program, you get a different answer, because a different person, or, a different function, or, a different part of the code is finishing its tasks first than the others. @@ -717,9 +717,9 @@ three basic operations at each iteration of the for loop, which are: Ideally, a thread B should read the value of `count`, only after the other thread A has finished writing the incremented value back into the `count` object. Therefore, in the ideal scenario, which is demonstrated -at @tbl-data-race-ideal, the threads should work in sync with each other. But the reality is that these +in @tbl-data-race-ideal, the threads should work in sync with each other. But the reality is that these threads are out of sync, and because of that, they suffer from a data race problem, which is demonstrated -at @tbl-data-race-not. +in @tbl-data-race-not. Notice that, in the data race scenario (@tbl-data-race-not), the read performed by a thread B happens before the write operation of thread A, and that ultimately leads to wrong results at the end of the program. @@ -759,9 +759,9 @@ reading the new and incremented version of this value that would be calculated b If you think about these diagrams exposed in form of tables, you will notice that they relate back to our discussion of atomic operations -at @sec-atomic-operation. Remember, atomic operations are operations that the CPU executes +in @sec-atomic-operation. Remember, atomic operations are operations that the CPU executes from beginning to end, without interruptions from other threads or processes. So, -the scenario exposed at @tbl-data-race-ideal do not suffer from a data race, because +the scenario exposed in @tbl-data-race-ideal do not suffer from a data race, because the operations performed by thread A are not interrupted in the middle by the operations from thread B. @@ -860,7 +860,7 @@ this C struct, you can create: The terminology might be a little different compared to Zig. But the meaning is still the same. Therefore, just remember this relationship, write locks are exclusive locks, while read locks are shared locks. -When a thread tries to acquire a read lock (i.e. a shared lock), this thread get's the shared lock +When a thread tries to acquire a read lock (i.e. a shared lock), this thread gets the shared lock if, and only if another thread does not currently holds a write lock (i.e. an exclusive lock), and also, if there are no other threads that are already in the queue, waiting for their turn to acquire a write lock. In other words, the thread in the queue have attempted @@ -960,7 +960,7 @@ to focus on doing other things instead?". So this yield operation is also a way for you to stop a particular thread, so that you can work and prioritize other threads instead. -Is important to say that, yielding a thread is a "not so common" thread operation these days. +It's important to say that, yielding a thread is a "not so common" thread operation these days. In other words, not many programmers use yielding in production, simply because is hard to use this operation and make it work properly, and also, there are better alternatives. Most programmers prefer to use `join()` instead. @@ -1002,7 +1002,7 @@ After that, the function sleeps for 1 second, to simulate some type of work, and then, the function tries to acquire the `mut2` lock. On the other hand, when we look into the second thread, which executes the `work2()` function, -we can see that this function acquires the `mut2` lock first. Because when this thread get's created and it tries +we can see that this function acquires the `mut2` lock first. Because when this thread gets created and it tries to acquire this `mut2` lock, the first thread is still sleeping on that "sleep 1 second" line. After acquiring `mut2`, the `work2()` function also sleeps for 1 second, to simulate some type of work, and then, the function tries to acquire the `mut1` lock. @@ -1061,7 +1061,7 @@ control over the thread, and its resources are never freed When we think about the `pthreads` C library, there is a possible way to asynchronously kill or cancel a thread, which is by sending a `SIGTERM` signal to the thread through the `pthread_kill()` function. -But canceling a thread like this is bad. Is dangerously bad. As consequence, the Zig implementation +But canceling a thread like this is bad. It's dangerously bad. As consequence, the Zig implementation of threads does not have a similar function, or, a similar way to asynchronously cancel or kill a thread. @@ -1069,13 +1069,13 @@ Therefore, if you want to cancel a thread in the middle of its execution in Zig, then, one good strategy that you can take is to use control flow in conjunction with `join()`. More specifically, you can design your thread around a while loop, that is constantly checking if the thread should continue running. -If is time to cancel the thread, we could make the while loop break, and join the thread with the main thread +If it's time to cancel the thread, we could make the while loop break, and join the thread with the main thread by calling `join()`. The code example below demonstrates to some extent this strategy. Here, we are using control flow to break the while loop, and exit the thread earlier than what we have initially planned to. This example also demonstrates how can we use -atomic objects in Zig with the `Value()` generic function that we have mentioned at @sec-atomic-operation. +atomic objects in Zig with the `Value()` generic function that we have mentioned in @sec-atomic-operation. ```{zig} @@ -1110,4 +1110,3 @@ pub fn main() !void { thread.join(); } ``` - diff --git a/Chapters/14-zig-c-interop.qmd b/Chapters/14-zig-c-interop.qmd index 97b9e73e..dd184bbc 100644 --- a/Chapters/14-zig-c-interop.qmd +++ b/Chapters/14-zig-c-interop.qmd @@ -19,7 +19,7 @@ knitr::opts_chunk$set( # Zig interoperability with C In this chapter, we are going to discuss the interoperability of Zig with C. -We have discussed at @sec-building-c-code how you can use the `zig` compiler to build C code. +We have discussed in @sec-building-c-code how you can use the `zig` compiler to build C code. But we haven't discussed yet how to actually use C code in Zig. In other words, we haven't discussed yet how to call and use C code from Zig. @@ -33,7 +33,7 @@ this next project. Interoperability with C is not something new. Most high-level programming languages have FFI (foreign function interfaces), which can be used to call C code. For example, Python have Cython, R have `.Call()`, Javascript have `ccall()`, etc. -But Zig integrates with C in a deeper level, which affects not only the way that C code get's called, but also, +But Zig integrates with C in a deeper level, which affects not only the way that C code gets called, but also, how this C code is compiled and incorporated into your Zig project. In summary, Zig have great interoperability with C. If you want to call any C code from Zig, @@ -111,7 +111,7 @@ installed in your system. Anyway, if you have doubts about this, comeback to @se ## Importing C header files {#sec-import-c-header} -At @sec-strategy-c, we have described that, currently, there are two different paths that +In @sec-strategy-c, we have described that, currently, there are two different paths that you can take to import a C header file into your Zig modules, `translate-c` or `@cImport()`. This section describes each strategy separately in more details. @@ -134,7 +134,7 @@ Also notice that we are saving the results of the translation process inside a Z Therefore, after running this command, all we have to do is to import this `c.zig` module, and start calling the C functions that you want to call from it. The example below demonstrates that. -Is important to remember what we've discussed at @sec-linking-c. In order to compile this +It's important to remember what we've discussed in @sec-linking-c. In order to compile this example you have to link this code with `libc`, by passing the flag `-lc` to the `zig` compiler. ```{zig} @@ -204,7 +204,7 @@ pub fn main() !void { Zig objects have some intrinsic differences between their C equivalents. Probably the most noticeable one is the difference between C strings and Zig strings, -which I described at @sec-zig-strings. +which I described in @sec-zig-strings. Zig strings are objects that contains both an array of arbitrary bytes and a length value. On the other hand, a C string is usually just a pointer to a null-terminated array of arbitrary bytes. @@ -221,7 +221,7 @@ that Zig object into a C compatible value, before passing it to C code. There is also a third scenario that is not being described here, which is when you create a C object, or, a C struct, or a C compatible value in your Zig code, and you pass this C object/value as input to a C function in your Zig code. -This scenario will be described later at @sec-c-inputs. In this section, we are focused on the scenarios where +This scenario will be described later in @sec-c-inputs. In this section, we are focused on the scenarios where we are passing Zig objects/values to C code, instead of C objects/values being passed to C code. @@ -231,7 +231,7 @@ An "auto-conversion" scenario is when the `zig` compiler automatically converts C compatible values for us. This specific scenario happens mostly in two instances: - with string literal values; -- with any of the primitive data types that were introduced at @sec-primitive-data-types. +- with any of the primitive data types that were introduced in @sec-primitive-data-types. When we think about the second instance described above, the `zig` compiler does automatically convert any of the primitive data types into their C equivalents, because the compiler knows how @@ -321,7 +321,7 @@ Therefore, when we talk exclusively about string literal values, as long as you explicit data type to these string literal values, the `zig` compiler should be capable of automatically converting them into C strings as needed. -But what about using one of the primitive data types that were introduced at @sec-primitive-data-types? +But what about using one of the primitive data types that were introduced in @sec-primitive-data-types? Let's take code exposed below as an example of that. Here, we are giving some float literal values as input to the C function `powf()`. Notice that this code example compiles and runs successfully. @@ -440,7 +440,7 @@ with no errors. ## Creating C objects in Zig {#sec-c-inputs} Creating C objects, or, in other words, creating instances of C structs in your Zig code -is actually something quite easy to do. You first need to import the C header file (like I described at @sec-import-c-header) that defines +is actually something quite easy to do. You first need to import the C header file (like I described in @sec-import-c-header) that defines the C struct that you are trying to instantiate in your Zig code. After that, you can just create a new object in your Zig code, and annotate it with the data type of the C struct. @@ -469,7 +469,7 @@ i.e. the memory is currently populated with "garbage" values. Thus, this expression have the exact same effect of the expression `User new_user;` in C, which means "declare a new object named `new_user` of type `User`". -Is our responsibility to properly initialize this memory associated with this `new_user` object, +It's our responsibility to properly initialize this memory associated with this `new_user` object, by assigning valid values to the members (or the fields) of the C struct. In the example below, I'm assigning the integer 1 to the member `id`. I am also saving the string `"pedropark99"` into the member `name`. Notice in this example that I manually add the null character (zero byte) to the end of the allocated array @@ -538,7 +538,7 @@ any special manner to use them in C code. This is how we create and use C object Now that we have learned how to create/declare C objects in our Zig code, we need to learn how to pass these C objects as inputs to Zig functions. -As I described at @sec-c-inputs, we can freely pass these C objects as inputs to C code +As I described in @sec-c-inputs, we can freely pass these C objects as inputs to C code that we call from our Zig code. But what about passing these C objects to Zig functions? In essence, this specific case requires one small adjustment in the Zig function declaration. @@ -546,7 +546,7 @@ All you need to do, is to make sure that you pass your C object *by reference* t instead of passing it *by value*. To do that, you have to annotate the data type of the function argument that is receiving this C object as "a pointer to the C struct", instead of annotating it as "an instance of the C struct". -Let's consider the C struct `User` from the `user.h` C header file that we have used at @sec-c-inputs. +Let's consider the C struct `User` from the `user.h` C header file that we have used in @sec-c-inputs. Now, consider that we want to create a Zig function that sets the value of the `id` field in this C struct, like the `set_user_id()` function declared below. Notice that the `user` argument in this function is annotated as a pointer (`*`) to a `c.User` object. @@ -593,4 +593,3 @@ pub fn main() !void { ``` New ID: 25 ``` - diff --git a/Chapters/15-vectors.qmd b/Chapters/15-vectors.qmd index 94019c19..47d3fd60 100644 --- a/Chapters/15-vectors.qmd +++ b/Chapters/15-vectors.qmd @@ -123,7 +123,7 @@ _ = v1; _ = v2; ``` -Is worth emphasizing that only arrays and slices whose sizes +It's worth emphasizing that only arrays and slices whose sizes are compile-time known can be transformed into vectors. Vectors in general are structures that work only with compile-time known sizes. Therefore, if you have an array whose size is runtime known, then, you first need to @@ -154,7 +154,7 @@ try stdout.print("{any}\n", .{v1}); ### Careful with vectors that are too big -As I described at @sec-what-vectors, each vector object is usually a small block of 128, 256 or 512 bits. +As I described in @sec-what-vectors, each vector object is usually a small block of 128, 256 or 512 bits. This means that a vector object is usually small in size, and when you try to go in the opposite direction, by creating a vector object that is very big in size (i.e. sizes that are close to $2^{20}$), you usually end up with crashes and loud errors from the compiler. @@ -171,7 +171,3 @@ _ = v1; ``` Segmentation fault (core dumped) ``` - - - - diff --git a/README.md b/README.md index cf953f91..567e904d 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ You can find instructions on how to install these pieces of software by clicking After you installed the three pieces of software listed above, you should run the `dependencies.R` R script, to install some R packages that are used across the book. Just run the command below in your terminal, and you should be fine. -OBS: If you are on Linux or MacOS, this command will probably take some time to run, because every single dependency get's built from source. +OBS: If you are on Linux or MacOS, this command will probably take some time to run, because every single dependency gets built from source. In Windows, this usually doesn't take that long because pre-built binaries are usually available. ```bash @@ -138,5 +138,3 @@ slower than the first one, but is more garanteed to work. Copyright © 2024 Pedro Duarte Faria. This book is licensed by the CC-BY 4.0 Creative Commons Attribution 4.0 International Public License. Creative Commons License - - diff --git a/zig_engine.R b/zig_engine.R index d3831fc5..9471c870 100644 --- a/zig_engine.R +++ b/zig_engine.R @@ -173,7 +173,7 @@ increase_indentation__ <- function(code_without_main) { #' This function is used to get the value of the `auto_main` code block option. #' The `auto_main` code block option is used to specify if the Zig code written #' in the current code block should (or should not) be encapsulated inside a -#' `main()` function, before it get's sent to the Zig compiler to be compiled. +#' `main()` function, before it gets sent to the Zig compiler to be compiled. #' #' If the user did not configured/setted this #' specific option in the current code block that is being analyzed, From eb5665b1eba9c82776eafb3b98e08114dd71f983 Mon Sep 17 00:00:00 2001 From: Glystik Date: Tue, 25 Feb 2025 17:41:25 +0100 Subject: [PATCH 102/151] Fixing typos and grammar --- Chapters/01-base64.qmd | 6 +++--- Chapters/01-memory.qmd | 2 +- Chapters/01-zig-weird.qmd | 2 +- Chapters/02-debugging.qmd | 2 +- Chapters/04-http-server.qmd | 6 +++--- Chapters/07-build-system.qmd | 4 ++-- Chapters/14-threads.qmd | 8 ++++---- Chapters/15-vectors.qmd | 6 +++--- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Chapters/01-base64.qmd b/Chapters/01-base64.qmd index 0d9a22f5..cddc5b70 100644 --- a/Chapters/01-base64.qmd +++ b/Chapters/01-base64.qmd @@ -170,9 +170,9 @@ the algorithm does, is to check how to divide the input bytes into groups of 6 b If the algorithm notices that there is a group of 6 bits that, have some bits in it, but, at the same time, it is not full (in other words, $0 < nbits < 6$, being $nbits$ the number of bits), meaning that, it lacks -some bits to fill the 6-bits requirement, the algorithm simply add extra zeros in this group -to fill the space that it needs. That is why in @fig-base64-algo1, on the third group after the 6-bit transformation, -2 extra zeros were added to fill the gap in this group. +some bits to fill the 6-bits requirement, the algorithm simply adds extra zeros in this group +to fill the space that it needs. That is why in @fig-base64-algo1, in the third group after the 6-bit transformation, +2 extra zeros were added to fill the gap. When we have a 6-bit group that is not completely full, like the third group, extra zeros are added to fill the gap. But what about when an entire 6-bit group is empty, or, it diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index c08ce5d9..f92e5bd0 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -695,7 +695,7 @@ of the allocator object is used to allocate an array capable of storing 50 `u8` Notice that this `alloc()` method receives two inputs. The first one, is a type. This defines what type of values the allocated array will store. In the example below, we are allocating an array of unsigned 8-bit integers (`u8`). But -you can create an array to store any type of value you want. Next, on the second argument, we +you can create an array to store any type of value you want. Next, in the second argument, we define the size of the allocated array, by specifying how many elements this array will contain. In the case below, we are allocating an array of 50 elements. diff --git a/Chapters/01-zig-weird.qmd b/Chapters/01-zig-weird.qmd index 4b395303..18afd01f 100644 --- a/Chapters/01-zig-weird.qmd +++ b/Chapters/01-zig-weird.qmd @@ -406,7 +406,7 @@ exposed below: #| auto_main: false #| build_type: "ast" const std = @import("std"); -// ERROR! Compile-time error that emerge from +// ERROR! Compile-time error that emerges from // this next line, on the `stdout` object const stdout = std.io.getStdOut().writer(); diff --git a/Chapters/02-debugging.qmd b/Chapters/02-debugging.qmd index 851c8d44..23751eb7 100644 --- a/Chapters/02-debugging.qmd +++ b/Chapters/02-debugging.qmd @@ -142,7 +142,7 @@ or LLDB (LLVM Project Debugger) as your debugger. Both debuggers can work with Zig code, and it's a matter of taste here. You choose the debugger of your preference, and you work with it. -In this book, I will use LLDB as my debugger on the examples. +In this book, I will use LLDB as my debugger in the examples. ### Compile your source code in debug mode {#sec-compile-debug-mode} diff --git a/Chapters/04-http-server.qmd b/Chapters/04-http-server.qmd index 2cb1fe62..e4804dd8 100644 --- a/Chapters/04-http-server.qmd +++ b/Chapters/04-http-server.qmd @@ -283,7 +283,7 @@ when someone tries to connect to the socket. This means that, the `accept()` met returns a new connection object as a result. And you can use this connection object to read or write messages from or to the client. For now, we are not doing anything with this connection object. -But we are going to use it on the next section. +But we are going to use it in the next section. ```{zig} @@ -306,7 +306,7 @@ server will wait for one incoming connection, and as soon as the server is done with this first connection that it establishes, the program ends, and the server stops. -This is not the norm on the real world. Most people that write +This is not the norm in the real world. Most people that write a HTTP server like this, usually put the `accept()` method inside a `while` (infinite) loop, where if a connection is created with `accept()`, a new thread of execution is created to deal with @@ -530,7 +530,7 @@ work in C. Each enum value is essentially represented as an integer. The first value in the set is represented as zero, then, the second value is one, ... etc. -One thing that we are going to learn on the next section is that +One thing that we are going to learn in the next section is that enums can have methods in them. Wait... What? This is amazing! Yes, enums in Zig are similar to structs, and they can have private and public methods inside them. diff --git a/Chapters/07-build-system.qmd b/Chapters/07-build-system.qmd index d1dce207..349fc81b 100644 --- a/Chapters/07-build-system.qmd +++ b/Chapters/07-build-system.qmd @@ -27,7 +27,7 @@ from the compiler, to build your code. You can find a good description of Zig's build system -on the [article entitled "Build System"](https://ziglang.org/learn/build-system/#user-provided-options)[^zig-art1] +in the [article entitled "Build System"](https://ziglang.org/learn/build-system/#user-provided-options)[^zig-art1] from the official Zig's website. We also have the excellent [series of posts written by Felix](https://zig.news/xq/zig-build-explained-part-1-59lf)[^felix]. Hence, this chapter represents an extra resource for you to consult and rely on. @@ -823,7 +823,7 @@ by using the `defineCMacro()` method from the target object that defines the binary file that you are building. In the example below, we are using the `lib` object that we have defined -on the previous sections to define some C Macros used by the FreeType project +in the previous sections to define some C Macros used by the FreeType project in the compilation process. These C Macros specify if FreeType should (or should not) include functionalities from different external libraries. diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 3dd7802b..bf99dffa 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -207,12 +207,12 @@ With these three arguments, you can control how the thread gets created, and als work (or "tasks") will be performed inside this new thread. A thread is just a separate context of execution, and we usually create new threads in our code, because we want to perform some work inside this new context of execution. And we specify which exact work, or, which exact steps that are going to be -performed inside this context, by providing the name of a function on the second argument of the `spawn()` method. +performed inside this context, by providing the name of a function in the second argument of the `spawn()` method. Thus, when this new thread gets created, this function that you provided as input to the `spawn()` method gets called, or, gets executed inside this new thread. You can control the arguments, or, the inputs that are passed to this function when it gets called, by providing -a list of arguments (or a list of inputs) on the third argument of the `spawn()` method. +a list of arguments (or a list of inputs) in the third argument of the `spawn()` method. These arguments are passed to the function in the same order that they are provided to `spawn()`. @@ -275,7 +275,7 @@ which also starts the execution at the moment that the thread gets created. ## Returning from a thread -We have learned on the previous section that the execution of the thread starts at the moment +We have learned in the previous section that the execution of the thread starts at the moment that the thread gets created. Now, we will learn how to "join" or "detach" a thread in Zig. "Join" and "detach" are operations that control how the thread returns to the main thread, or, to the main process in our program. @@ -558,7 +558,7 @@ and, therefore, the other people (in this case, the other threads) that wants to have to be patient, and simply wait for the other person (or the other thread) to unlock the door and get out of the bathroom. Some other programmers also like to explain mutexes by using the analogy of "each person will have their turn to speak". -This is the analogy used on the [*Multithreading Code* video from the Computerphile project](https://www.youtube.com/watch?v=7ENFeb-J75k&ab_channel=Computerphile)[^computerphile]. +This is the analogy used in the [*Multithreading Code* video from the Computerphile project](https://www.youtube.com/watch?v=7ENFeb-J75k&ab_channel=Computerphile)[^computerphile]. Imagine if you are in a conversation circle. There is a moderator in this circle, which is the person that decides who have the right to speak at that particular moment. The moderator gives a green card (or some sort of an authorization card) to the person that is going to speak, and, as a result, everyone else must be silent and hear this person that has the green card. diff --git a/Chapters/15-vectors.qmd b/Chapters/15-vectors.qmd index 47d3fd60..ee6c5335 100644 --- a/Chapters/15-vectors.qmd +++ b/Chapters/15-vectors.qmd @@ -34,8 +34,8 @@ Most modern CPU models (from AMD, Intel, etc.) these days (either in a desktop o notebook model) have support for SIMD operations. So, if you have a very old CPU model installed in your computer, then, is possible that you have no support for SIMD operations in your computer. -Why people have started using SIMD on their software? The answer is performance. -But what SIMD precisely do to achieve better performance? Well, in essence, SIMD operations are a different +Why have people started using SIMD in their software? The answer is performance. +But what precisely are SIMD doing to achieve better performance? Well, in essence, SIMD operations are a different strategy to get parallel computing in your program, and therefore, make faster calculations. The basic idea behind SIMD is to have a single instruction that operates over multiple data @@ -93,7 +93,7 @@ to iterate through the elements of `v1` and `v2`, and adding them together, one we enjoy the benefits of SIMD, which performs all 4 additions in parallel, at the same time. Therefore, the `@Vector` structure is essentially the Zig representation of SIMD vector objects. -The elements on these vector objects will be operated in parallel, if, and only if your current CPU model +The elements in these vector objects will be operated in parallel, if, and only if your current CPU model supports SIMD operations. If your CPU model does not have support for SIMD, then, the `@Vector` structure will likely produce a similar performance from a "for loop solution". From ad348c8a6bf97ddf8aeba57035bd9946b3173119 Mon Sep 17 00:00:00 2001 From: Michael Lynch Date: Tue, 25 Feb 2025 14:36:11 -0500 Subject: [PATCH 103/151] Fix syntax of get's -> gets There's an error pattern in the book in that the word 'get's' appears frequently, but this is not correct English syntax. The word 'gets' has no apostrophe, so this change replaces instances of 'get's' with 'gets'. Note that I only updated Markdown files and did not modify the JSON files, as the JSON files appear to be derived from the Markdown files. --- Chapters/01-zig-weird.qmd | 10 +++++----- Chapters/03-structs.qmd | 6 +++--- Chapters/07-build-system.qmd | 2 +- Chapters/09-error-handling.qmd | 10 +++++----- Chapters/12-file-op.qmd | 4 ++-- Chapters/14-threads.qmd | 2 +- Chapters/14-zig-c-interop.qmd | 2 +- README.md | 2 +- zig_engine.R | 2 +- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Chapters/01-zig-weird.qmd b/Chapters/01-zig-weird.qmd index 1a1afa74..063e87ac 100644 --- a/Chapters/01-zig-weird.qmd +++ b/Chapters/01-zig-weird.qmd @@ -60,7 +60,7 @@ your C code. With macros, you are no longer 100% sure about which pieces of the code are being sent to the compiler, i.e. they obscure the actual source code that you wrote. -You don't have macros in Zig. In Zig, the code you write, is the actual code that get's compiled by the compiler. +You don't have macros in Zig. In Zig, the code you write, is the actual code that gets compiled by the compiler. You also don't have a hidden control flow happening behind the scenes. And, you also don't have functions or operators from the standard library that make hidden memory allocations behind your back. @@ -771,7 +771,7 @@ t.zig:7:5: error: pointless discard This same rule applies to variable objects. Every variable object must also be used in some way. And if you assign a variable object to the underscore, -this object also get's discarded, and you can no longer use this object. +this object also gets discarded, and you can no longer use this object. @@ -1023,12 +1023,12 @@ Therefore, we don't know the value of this thing at compile-time, only at runtim We have learned at @sec-select-array-elem that slices are created by using a *range selector*, which represents a range of indexes. When this "range of indexes" (i.e. the start and the end of this range) -is known at compile-time, the slice object that get's created is actually, under the hood, just +is known at compile-time, the slice object that gets created is actually, under the hood, just a single-item pointer to an array. You don't need to precisely understand what that means now. We are going to talk a lot about pointers at @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time, -the slice that get's created is just a pointer to an array, accompanied by a length value that +the slice that gets created is just a pointer to an array, accompanied by a length value that tells the size of the slice. If you have a slice object like this, i.e. a slice that has a compile-time known range, @@ -1050,7 +1050,7 @@ const slice = arr1[1..4]; On the other hand, if the range of indexes is not known at compile time, then, the slice object -that get's created is not a pointer anymore, and, thus, it does not support pointer operations. +that gets created is not a pointer anymore, and, thus, it does not support pointer operations. For example, maybe the start index is known at compile time, but the end index is not. In such case, the range of the slice becomes runtime known only. diff --git a/Chapters/03-structs.qmd b/Chapters/03-structs.qmd index 008c5e72..26f03b18 100644 --- a/Chapters/03-structs.qmd +++ b/Chapters/03-structs.qmd @@ -410,7 +410,7 @@ You could also interpret this as: "defer expressions" are executed from bottom t from last to first. Therefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that -the value of `i` that get's printed to the console changes to 1. This doesn't mean that the +the value of `i` that gets printed to the console changes to 1. This doesn't mean that the `defer` expression was not executed in this case. This actually means that the `defer` expression was executed only after the `errdefer` expression. The code example below demonstrates this: @@ -1287,9 +1287,9 @@ are basically accessing the data members of the struct stored in the `std` object. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`) to access the data members and methods of the struct. -When this "import statement" get's executed, the result of this expression is a struct +When this "import statement" gets executed, the result of this expression is a struct object that contains the Zig Standard Library modules, global variables, functions, etc. -And this struct object get's saved (or stored) inside the constant object named `std`. +And this struct object gets saved (or stored) inside the constant object named `std`. Take the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread] diff --git a/Chapters/07-build-system.qmd b/Chapters/07-build-system.qmd index 6bced377..0fe6f2b4 100644 --- a/Chapters/07-build-system.qmd +++ b/Chapters/07-build-system.qmd @@ -73,7 +73,7 @@ If that is not your case, you can forget about it. Your build process is usually organized in a build script. In Zig, we normally write this build script into a Zig module in the root directory of our project, named as `build.zig`. You write this build script, then, when you run it, your project -get's built into binary files that you can use and distribute to your users. +gets built into binary files that you can use and distribute to your users. This build script is normally organized around *target objects*. A target is simply something to be built, or, in other words, it's something that you want the `zig` compiler diff --git a/Chapters/09-error-handling.qmd b/Chapters/09-error-handling.qmd index 81df68fc..5a92b0fb 100644 --- a/Chapters/09-error-handling.qmd +++ b/Chapters/09-error-handling.qmd @@ -446,7 +446,7 @@ our program to leak resources of the system. The `errdefer` keyword is a tool to perform such "cleanup actions" in hostile situations. This keyword is commonly used to clean (or to free) allocated resources, before the execution of our program -get's stopped because of an error value being generated. +gets stopped because of an error value being generated. The basic idea is to provide an expression to the `errdefer` keyword. Then, `errdefer` executes this expression if, and only if, an error occurs @@ -457,7 +457,7 @@ this `create_user()` function will return this new `User` object as its return v However, if for some reason, an error value is generated by some expression that is after the `errdefer` line, for example, in the `db.add(user)` expression, -the expression registered by `errdefer` get's executed before the error value is returned +the expression registered by `errdefer` gets executed before the error value is returned from the function, and before the program enters in panic mode and stops the current execution. @@ -476,7 +476,7 @@ fn create_user(db: Database, allocator: Allocator) !User { By using `errdefer` to destroy the `user` object that we have just created, we guarantee that the memory allocated for this `user` object -get's freed, before the execution of the program stops. +gets freed, before the execution of the program stops. Because if the expression `try db.add(user)` returns an error value, the execution of our program stops, and we lose all references and control over the memory that we have allocated for the `user` object. @@ -490,14 +490,14 @@ to discuss the subject a bit further. You might still have the question "why use `errdefer` if we can use `defer` instead?" in your mind. Although being similar, the key difference between `errdefer` and `defer` keyword -is when the provided expression get's executed. +is when the provided expression gets executed. The `defer` keyword always execute the provided expression at the end of the current scope, no matter how your code exits this scope. In contrast, `errdefer` executes the provided expression only when an error occurs in the current scope. This becomes important if a resource that you allocate in the -current scope get's freed later in your code, in a different scope. +current scope gets freed later in your code, in a different scope. The `create_user()` functions is an example of this. If you think closely about this function, you will notice that this function returns the `user` object as the result. diff --git a/Chapters/12-file-op.qmd b/Chapters/12-file-op.qmd index 0a880e28..1ccc6ad8 100644 --- a/Chapters/12-file-op.qmd +++ b/Chapters/12-file-op.qmd @@ -600,7 +600,7 @@ get a `NotOpenForReading` error as result. But how can you overcome this barrier? How can you create a file that is open to read operations? All you have to do, is to set the `read` flag to true in the second argument of `createFile()`. When you set this flag to true, -then the file get's create with "read permissions", and, as consequence, +then the file gets create with "read permissions", and, as consequence, a program like this one below becomes valid: @@ -649,7 +649,7 @@ that dictates how the file is opened. You can see the full list of options for `openFile()` by visiting the documentation for [`OpenFlags`](https://ziglang.org/documentation/master/std/#std.fs.File.OpenFlags)[^oflags]. But the main flag that you will most certainly use is the `mode` flag. -This flag specifies the IO mode that the file will be using when it get's opened. +This flag specifies the IO mode that the file will be using when it gets opened. There are three IO modes, or, three values that you can provide to this flag, which are: - `read_only`, allows only read operations on the file. All write operations are blocked. diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index 232fee95..8ec78648 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -119,7 +119,7 @@ this `send_order()` function returns almost immediately, so the waiter spends almost no time worrying about the order, and just move on and tries to get the next order from the clients. -Inside the new thread created, the order get's cooked by a chef, and when the +Inside the new thread created, the order gets cooked by a chef, and when the food is ready, it is delivered to the client's table. diff --git a/Chapters/14-zig-c-interop.qmd b/Chapters/14-zig-c-interop.qmd index 97b9e73e..5b1d133b 100644 --- a/Chapters/14-zig-c-interop.qmd +++ b/Chapters/14-zig-c-interop.qmd @@ -33,7 +33,7 @@ this next project. Interoperability with C is not something new. Most high-level programming languages have FFI (foreign function interfaces), which can be used to call C code. For example, Python have Cython, R have `.Call()`, Javascript have `ccall()`, etc. -But Zig integrates with C in a deeper level, which affects not only the way that C code get's called, but also, +But Zig integrates with C in a deeper level, which affects not only the way that C code gets called, but also, how this C code is compiled and incorporated into your Zig project. In summary, Zig have great interoperability with C. If you want to call any C code from Zig, diff --git a/README.md b/README.md index cf953f91..b450a5dc 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ You can find instructions on how to install these pieces of software by clicking After you installed the three pieces of software listed above, you should run the `dependencies.R` R script, to install some R packages that are used across the book. Just run the command below in your terminal, and you should be fine. -OBS: If you are on Linux or MacOS, this command will probably take some time to run, because every single dependency get's built from source. +OBS: If you are on Linux or MacOS, this command will probably take some time to run, because every single dependency gets built from source. In Windows, this usually doesn't take that long because pre-built binaries are usually available. ```bash diff --git a/zig_engine.R b/zig_engine.R index d3831fc5..9471c870 100644 --- a/zig_engine.R +++ b/zig_engine.R @@ -173,7 +173,7 @@ increase_indentation__ <- function(code_without_main) { #' This function is used to get the value of the `auto_main` code block option. #' The `auto_main` code block option is used to specify if the Zig code written #' in the current code block should (or should not) be encapsulated inside a -#' `main()` function, before it get's sent to the Zig compiler to be compiled. +#' `main()` function, before it gets sent to the Zig compiler to be compiled. #' #' If the user did not configured/setted this #' specific option in the current code block that is being analyzed, From 7c05040d65ff965b0804703054421609f926b01f Mon Sep 17 00:00:00 2001 From: glystik <81292524+glystik@users.noreply.github.com> Date: Wed, 26 Feb 2025 12:00:05 +0100 Subject: [PATCH 104/151] Removed duplicate, wrong sentence --- Chapters/14-threads.qmd | 2 -- 1 file changed, 2 deletions(-) diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index addac8e4..bf389319 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -275,8 +275,6 @@ which also starts the execution as soon as the thread is created. ## Returning from a thread -We have learned in the previous section that the execution of the thread starts at the moment -that the thread gets created. Now, we will learn how to "join" or "detach" a thread in Zig. We have learned in the previous section that the execution of the thread starts as soon as the thread is created. Now, we will learn how to "join" or "detach" a thread in Zig. "Join" and "detach" are operations that control how the thread returns to From 3048303c2413b563937faeb8b0ed4f843df9de9e Mon Sep 17 00:00:00 2001 From: Glystik Date: Wed, 26 Feb 2025 14:29:36 +0100 Subject: [PATCH 105/151] Adjusting "it is" to "it's", "i.e.,", etc --- CONTRIBUTING.md | 3 +- Chapters/01-base64.qmd | 24 +++++++-------- Chapters/01-memory.qmd | 24 +++++++-------- Chapters/01-zig-weird.qmd | 52 ++++++++++++++++----------------- Chapters/02-debugging.qmd | 10 +++---- Chapters/03-structs.qmd | 36 +++++++++++------------ Chapters/04-http-server.qmd | 32 ++++++++++---------- Chapters/05-pointers.qmd | 12 ++++---- Chapters/07-build-system.qmd | 16 +++++----- Chapters/09-data-structures.qmd | 46 ++++++++++++++--------------- Chapters/09-error-handling.qmd | 28 +++++++++--------- Chapters/10-stack-project.qmd | 12 ++++---- Chapters/12-file-op.qmd | 50 +++++++++++++++---------------- Chapters/13-image-filter.qmd | 10 +++---- Chapters/14-threads.qmd | 32 ++++++++++---------- Chapters/14-zig-c-interop.qmd | 10 +++---- Chapters/15-vectors.qmd | 6 ++-- README.md | 2 +- index.qmd | 4 +-- zig_engine.R | 10 +++---- 20 files changed, 208 insertions(+), 211 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 52219fde..304049e4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ on the official repository of the project: - to give a feedback, or, a suggestion of improvement. - to point out an error in the book. This error can be: - a typo; - - it might also be an error in the code examples (i.e. the code example doesn't work when it is supposed to work); + - it might also be an error in the code examples (i.e., the code example doesn't work when it is supposed to work); - a knowledge error in the book, meaning that, there is a mistake in the technical explanation of a subject. Now, maybe, you want to do something more than just open an issue. Maybe you want to actually @@ -35,4 +35,3 @@ If you've never done this before, the process is very easy: If you send a Pull Request with significant changes, you need to include the phrase "I assign the copyright of this contribution to Pedro Duarte Faria" in the description of your Pull Request - I need this so I can publish the book. - diff --git a/Chapters/01-base64.qmd b/Chapters/01-base64.qmd index cddc5b70..7a831bb7 100644 --- a/Chapters/01-base64.qmd +++ b/Chapters/01-base64.qmd @@ -54,7 +54,7 @@ take a look at @sec-encode-vs-decode. ### The base64 scale {#sec-base64-scale} The base64 encoding system is based on a scale that goes from 0 to 63 (hence the name). -Each index in this scale is represented by a character (it is a scale of 64 characters). +Each index in this scale is represented by a character (it's a scale of 64 characters). So, in order to convert some binary data, to the base64 encoding, we need to convert each binary number to the corresponding character in this "scale of 64 characters". @@ -95,7 +95,7 @@ We retrieve the character that we need directly from memory. We can start building a Zig struct to store our base64 decoder/encoder logic. We start with the `Base64` struct below. For now, we only have one single data member in this -struct, i.e. the member `_table`, which represents our lookup table. We also have an `init()` method, +struct, i.e., the member `_table`, which represents our lookup table. We also have an `init()` method, to create a new instance of a `Base64` object, and, a `_char_at()` method, which is a "get character at index $x$" type of function. @@ -123,7 +123,7 @@ const Base64 = struct { In other words, the `_char_at()` method is responsible for getting the character in the lookup -table (i.e. the `_table` struct data member) that corresponds to a particular index in the +table (i.e., the `_table` struct data member) that corresponds to a particular index in the "base64 scale". So, in the example below, we know that the character that corresponds to the index 28 in the "base64 scale" is the character "c". @@ -168,10 +168,10 @@ Taking the string "Hi" as an example, we have 2 bytes, or, 16 bits in total. So, to complete the window of 24 bits that the base64 algorithm likes to work on. The first thing that the algorithm does, is to check how to divide the input bytes into groups of 6 bits. -If the algorithm notices that there is a group of 6 bits that, have some bits in it, but, at the same time, it is not full -(in other words, $0 < nbits < 6$, being $nbits$ the number of bits), meaning that, it lacks -some bits to fill the 6-bits requirement, the algorithm simply adds extra zeros in this group -to fill the space that it needs. That is why in @fig-base64-algo1, in the third group after the 6-bit transformation, +If the algorithm notices that there is a group of 6 bits that have some bits in it, but, at the same time it's +not full—lacking some bits to fill the 6-bits requirement ($0 < nbits < 6$, being $nbits$ the number of bits), +the algorithm simply adds extra zeros in this group to fill the space that it needs. +That is why in @fig-base64-algo1, in the third group after the 6-bit transformation, 2 extra zeros were added to fill the gap. When we have a 6-bit group that is not completely full, like the third group, extra zeros @@ -201,7 +201,7 @@ two characters in the output sequence (MA==) are `==`. The algorithm behind a base64 decoder is essentially the inverse process of a base64 encoder. A base64 decoder needs to translate base64 messages back into their original meaning, -i.e. into the original sequence of binary data. +i.e., into the original sequence of binary data. A base64 decoder usually works on a window of 4 bytes. Because it wants to convert these 4 bytes back into the original sequence of 3 bytes, that was converted into 4 groups of 6 bits by the @@ -229,7 +229,7 @@ in the base64 sequence. So, every `=` character in a base64 encoded sequence sho If you don't have any previous experience with base64, you might not understand the differences between "encode" and "decode". Essentially, the terms "encode" and "decode" here -have the exact same meaning as they have in the field of encryption (i.e. they mean the same thing as "encode" and "decode" in hashing +have the exact same meaning as they have in the field of encryption (i.e., they mean the same thing as "encode" and "decode" in hashing algorithms, like the MD5 algorithm). Thus, "encode" means that we want to encode, or, in other words, we want to translate some message into @@ -242,7 +242,7 @@ So, in this process we get a sequence of base64 characters as input, and produce the binary data that is represented by this sequence of base64 characters. Any base64 library is normally composed of these two parts: 1) the encoder, which is a function that encodes -(i.e. it converts) any sequence of binary data into a sequence of base64 characters; 2) the decoder, which is a function +(i.e., it converts) any sequence of binary data into a sequence of base64 characters; 2) the decoder, which is a function that converts a sequence of base64 characters back into the original sequence of binary data. @@ -291,7 +291,7 @@ will be produced in the output of the decoder. I mean, this is roughly true, bec take the `=` character into account, which is always ignored by the decoder, as we described in @sec-base64-decoder-algo, and, in @fig-base64-algo2. But we can ignore this fact for now, just to keep things simple. -The function `_calc_decode_length()` exposed below summarizes this logic that we described. It is very similar +The function `_calc_decode_length()` exposed below summarizes this logic that we described. It's very similar to the function `_calc_encode_length()`. Only the division part is twisted, and also, in the special case where we have less than 4 bytes in the input to work on. Also notice that this time, we apply a floor operation over the output of the division, by using the `divFloor()` @@ -669,7 +669,7 @@ base64 scale as the result. Notice that, if the input character is `'='`, the function returns the index 64, which is "out of range" in the scale. But, as I described in @sec-base64-scale, the character `'='` does not belong to the base64 scale itself. -It is a special and meaningless character in base64. +It's a special and meaningless character in base64. Also notice that this `_char_index()` function is a method from our `Base64` struct, because of the `self` argument. Again, I have omitted the `Base64` struct definition in this example diff --git a/Chapters/01-memory.qmd b/Chapters/01-memory.qmd index f92e5bd0..54d71fe0 100644 --- a/Chapters/01-memory.qmd +++ b/Chapters/01-memory.qmd @@ -72,7 +72,7 @@ and only if, the type of this object has a known fixed size. In order for a type to have a known fixed size, this type must have data members whose size is fixed. If this type includes, for example, a variable sized array in it, then, this type does not have a known fixed size. Because this array can have any size at runtime -(i.e. it can be an array of 2 elements, or 50 elements, or 1 thousand elements, etc.). +(i.e., it can be an array of 2 elements, or 50 elements, or 1 thousand elements, etc.). For example, a string object, which internally is an array of constant u8 values (`[]const u8`) has a variable size. It can be a string object with 100 or 500 characters in it. If we do not @@ -118,8 +118,8 @@ argument depends on the value that you assign to this particular argument, when you call the function. For example, the function `input_length()` contains an argument named `input`, which is an array of constant `u8` integers (`[]const u8`). -It is impossible to know the value of this particular argument at compile time. And it also is impossible to know the size/length -of this particular argument. Because it is an array that do not have a fixed size specified explicitly in the argument type annotation. +It's impossible to know the value of this particular argument at compile time. And it also is impossible to know the size/length +of this particular argument. Because it's an array that does not have a fixed size specified explicitly in the argument type annotation. So, we know that this `input` argument will be an array of `u8` integers. But we do not know at compile-time, its value, and neither its size. This information is known only at runtime, which is the period of time when you program is executed. @@ -163,7 +163,7 @@ I will describe each memory space in detail over the next sections. But for now, stablish the main difference between these two types of memory. In essence, the stack memory is normally used to store values whose length is fixed and known -at compile time. In contrast, the heap memory is a *dynamic* type of memory space, meaning that, it is +at compile time. In contrast, the heap memory is a *dynamic* type of memory space, meaning that, it's used to store values whose length might grow during the execution (runtime) of your program [@jenny2022]. Lengths that grow during runtime are intrinsically associated with "runtime known" type of values. @@ -200,7 +200,7 @@ usually stored in this same stack space. Looking at the example below, the object `result` is a local object declared inside the scope of the `add()` function. Because of that, this object is stored inside the stack space reserved for the `add()` function. The `r` object (which is declared outside of the `add()` function scope) is also stored in the stack. -But since it is declared in the "outer" scope, this object is stored in the +But since it's declared in the "outer" scope, this object is stored in the stack space that belongs to this outer scope. ```{zig} @@ -277,7 +277,7 @@ Think about that for a second. If all local objects in the stack are destroyed a would you even consider returning a pointer to one of these objects? This pointer is at best, invalid, or, more likely, "undefined". -Conclusion, it is totally fine to write a function that returns the local object +In conclusion, it's totally fine to write a function that returns the local object itself as result, because then, you return the value of that object as the result. But, if this local object is stored in the stack, you should never write a function that returns a pointer to this local object. Because the memory address pointed by the pointer @@ -286,7 +286,7 @@ no longer exists. So, using again the `add()` function as an example, if you rewrite this function so that it returns a pointer to the local object `result`, the `zig` compiler will actually compile -your program, with no warnings or errors. At first glance, it looks that this is good code +your program, with no warnings or errors. At first glance, it looks like this is good code that works as expected. But this is a lie! If you try to take a look at the value inside of the `r` object, @@ -315,7 +315,7 @@ pub fn main() !void { ``` This "invalid pointer to stack variable" problem is well known across many programming language communities. -If you try to do the same thing, for example, in a C or C++ program (i.e. returning an address to +If you try to do the same thing, for example, in a C or C++ program (i.e., returning an address to a local object stored in the stack), you would also get undefined behaviour in the program. @@ -337,7 +337,7 @@ from its scope. One important limitation of the stack, is that, only objects whose length/size is known at compile-time can be stored in it. In contrast, the heap is a much more dynamic -(and flexible) type of memory. It is the perfect type of memory to use +(and flexible) type of memory. It's the perfect type of memory to use for objects whose size/length might grow during the execution of your program. Virtually any application that behaves as a server is a classic use case of the heap. @@ -404,7 +404,7 @@ In essence, if you try to make an allocation on the stack, that is so big that e a *stack overflow* happens, and your program just crashes as a result of that. In other words, a stack overflow happens when you attempt to use more space than is available on the stack. -This type of problem is very similar to a *buffer overflow*, i.e. you are trying to use more space +This type of problem is very similar to a *buffer overflow*, i.e., you are trying to use more space than is available in the "buffer object". However, a stack overflow always causes your program to crash, while a buffer overflow does not always cause your program to crash (although it often does). @@ -503,7 +503,7 @@ known fixed length. But in reality, there are two very common instances where this "fixed length limitation" of the stack is a deal braker: 1. the objects that you create inside your function might grow in size during the execution of the function. -1. sometimes, it is impossible to know upfront how many inputs you will receive, or how big this input will be. +1. sometimes, it's impossible to know upfront how many inputs you will receive, or how big this input will be. Also, there is another instance where you might want to use an allocator, which is when you want to write a function that returns a pointer to a local object. As I described in @sec-stack, you cannot do that if this local object is stored in the @@ -650,7 +650,7 @@ defer allocator.free(input); ### Arena allocator {#sec-arena-allocator} The `ArenaAllocator()` is an allocator object that takes a child allocator as input. The idea behind the `ArenaAllocator()` in Zig -is similar to the concept of "arenas" in the programming language Go[^go-arena]. It is an allocator object that allows you +is similar to the concept of "arenas" in the programming language Go[^go-arena]. It's an allocator object that allows you to allocate memory as many times you want, but free all memory only once. In other words, if you have, for example, called 5 times the method `alloc()` of an `ArenaAllocator()` object, you can free all the memory you allocated over these 5 calls at once, by simply calling the `deinit()` method of the same `ArenaAllocator()` object. diff --git a/Chapters/01-zig-weird.qmd b/Chapters/01-zig-weird.qmd index 18afd01f..a05d7747 100644 --- a/Chapters/01-zig-weird.qmd +++ b/Chapters/01-zig-weird.qmd @@ -52,9 +52,9 @@ with tons of features, and also, there are lots of different "flavors of C++". T are what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction. Zig is a very simple language, more closely related to other simple languages such as C and Go. -The phrase above is still important for C programmers too. Because, even C being a simple -language, it is still hard sometimes to read and understand C code. For example, pre-processor macros in -C are a frequent source of confusion. They really make it sometimes hard to debug +The phrase above is still important for C programmers too. Because, even if C is a simple +language, it's still hard sometimes to read and understand C code. For example, pre-processor macros in +C are a frequent source of confusion. They sometimes really make it hard to debug C programs. Because macros are essentially a second language embedded in C that obscures your C code. With macros, you are no longer 100% sure about which pieces of the code are being sent to the compiler, i.e. @@ -101,7 +101,7 @@ is a separate Zig module, which is simply a text file that contains some Zig cod By convention, the `main.zig` module is where your main function lives. Thus, if you are building an executable program in Zig, you need to declare a `main()` function, -which represents the entrypoint of your program, i.e. it is where the execution of your program begins. +which represents the entrypoint of your program, i.e., where the execution of your program begins. However, if you are building a library (instead of an executable program), then, the normal procedure is to delete this `main.zig` file and start with the `root.zig` module. @@ -197,7 +197,7 @@ in C or C++, or, to the `import` statement in Python or Javascript code. In this example, we are importing the `std` module, which gives you access to the Zig Standard Library. -In this `root.zig` file, we can also see how assignments (i.e. creating new objects) +In this `root.zig` file, we can also see how assignments (i.e., creating new objects) are made in Zig. You can create a new object in Zig by using the syntax `(const|var) name = value;`. In the example below, we are creating two constant objects (`std` and `testing`). In @sec-assignments we talk more about objects in general. @@ -284,7 +284,7 @@ which, in this example, is the `stdout.print()` expression. In essence, the `try` keyword executes the expression `stdout.print()`. If this expression returns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward. -It is like if this `try` keyword was never there. However, if the expression does return an error, then, +It's like if this `try` keyword was never there. However, if the expression does return an error, then, the `try` keyword will unwrap the error value, then, it returns this error from the function and also prints the current stack trace to `stderr`. @@ -389,7 +389,7 @@ operating systems, such as Linux and macOS. In summary, if you have a piece of Z includes some global variables whose initialization rely on runtime resources, then, you might have some troubles while trying to compile this Zig code on Windows. -An example of that is accessing the `stdout` (i.e. the *standard output* of your system), which is usually +An example of that is accessing the `stdout` (i.e., the *standard output* of your system), which is usually done in Zig by using the expression `std.io.getStdOut()`. If you use this expression to instantiate a global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows, with an "unable to evaluate comptime expression" error message. @@ -576,7 +576,7 @@ more about the language each day: Another great strategy to learn Zig, or honestly, to learn any language you want, is to practice it by solving exercises. For example, there is a famous repository in the Zig community called [Ziglings](https://ziglings.org)[^ziglings] -, which contains more than 100 small exercises that you can solve. It is a repository of +, which contains more than 100 small exercises that you can solve. It's a repository of tiny programs written in Zig that are currently broken, and your responsibility is to fix these programs, and make them work again. @@ -603,7 +603,7 @@ the exercises, you can look at these two repositories: -## Creating new objects in Zig (i.e. identifiers) {#sec-assignments} +## Creating new objects in Zig (i.e., identifiers) {#sec-assignments} Let's talk more about objects in Zig. Readers that have past experience with other programming languages might know this concept through @@ -653,7 +653,7 @@ in your source code. So, using the same code example exposed above, if I change the declaration of the `age` object to use the `var` keyword, then, the program gets compiled successfully. Because now, the `zig` compiler detects that we are changing the value of an -object that allows this behaviour, because it is an "variable object". +object that allows this behaviour, because it's a "variable object". ```{zig} #| build_type: "run" @@ -676,7 +676,7 @@ which is the `undefined` keyword. It's important to emphasize that, you should avoid using `undefined` as much as possible. Because when you use this keyword, you leave your object uninitialized, and, as a consequence, -if for some reason, your code use this object while it is uninitialized, then, you will definitely +if for some reason, your code uses this object while it's uninitialized, then, you will definitely have undefined behaviour and major bugs in your program. In the example below, I'm declaring the `age` object again. But this time, @@ -704,7 +704,7 @@ to calculate the value of another object, or, you can call a method that belongs particular object. It doesn't matter in which way you use it. As long as you use it. -If you try to break this rule, i.e. if your try to declare a object, but not use it, +If you try to break this rule, i.e., if your try to declare a object, but not use it, the `zig` compiler will not compile your Zig source code, and it will issue a error message warning that you have unused objects in your code. @@ -746,7 +746,7 @@ _ = age; ``` Now, remember, everytime you assign a particular object to the underscore, this object -is essentially destroyed. It is discarded by the compiler. This means that you can no longer +is essentially destroyed. It's discarded by the compiler. This means that you can no longer use this object further in your code. It doesn't exist anymore. So if you try to use the constant `age` in the example below, after we discarded it, you @@ -827,7 +827,7 @@ But here is a quick list: ## Arrays {#sec-arrays} You create arrays in Zig by using a syntax that resembles the C syntax. -First, you specify the size of the array (i.e. the number of elements that will be stored in the array) +First, you specify the size of the array (i.e., the number of elements that will be stored in the array) you want to create inside a pair of brackets. Then, you specify the data type of the elements that will be stored inside this array. @@ -910,8 +910,8 @@ Therefore, the syntax `start..end` actually means `start..end - 1` in practice. You can for example, create a slice that goes from the first to the last elements of the array, by using `ar[0..ar.len]` syntax -In other words, it is a slice that -access all elements in the array. +In other words, it's a slice that +accesses all elements in the array. ```{zig} #| auto_main: true @@ -1021,7 +1021,7 @@ In contrast, a runtime known thing is when the exact value of a thing is calcula Therefore, we don't know the value of this thing at compile-time, only at runtime. We have learned in @sec-select-array-elem that slices are created by using a *range selector*, -which represents a range of indexes. When this "range of indexes" (i.e. the start and the end of this range) +which represents a range of indexes. When this "range of indexes" (i.e., the start and the end of this range) is known at compile-time, the slice object that gets created is actually, under the hood, just a single-item pointer to an array. @@ -1030,7 +1030,7 @@ in @sec-pointer. For now, just understand that, when the range of indexes is kno the slice that gets created is just a pointer to an array, accompanied by a length value that tells the size of the slice. -If you have a slice object like this, i.e. a slice that has a compile-time known range, +If you have a slice object like this, i.e., a slice that has a compile-time known range, you can use common pointer operations over this slice object. For example, you can dereference the pointer of this slice, by using the `.*` method, like you would do on a normal pointer object. @@ -1104,7 +1104,7 @@ are also examples of blocks. This means that, every if statement, or for loop, etc., that you create in your source code have its own separate scope. That is why you can't access the objects that you defined inside -of your for loop (or if statement) in an outer scope, i.e. a scope outside of the for loop. +of your for loop (or if statement) in an outer scope, i.e., a scope outside of the for loop. Because you are trying to access an object that belongs to a scope that is different than your current scope. @@ -1147,7 +1147,7 @@ In summary, there are two types of string values that you care about in Zig, whi - String literal values. - String objects. -A string literal value is just a pointer to a null-terminated array of bytes (i.e. similar to a C string). +A string literal value is just a pointer to a null-terminated array of bytes (i.e., similar to a C string). But in Zig, a string literal value also embeds the length of the string into the data type of the value itself. Therefore, a string literal value have a data type in the format `*const [n:0]u8`. The `n` in the data type indicates the size of the string. @@ -1158,7 +1158,7 @@ a string object have a data type of `[]u8` or `[]const u8`, depending if the str marked as constant with `const`, or as variable with `var`. Because a string object is essentially a slice, it means that a string object always contains two things: -a pointer to an array of bytes (i.e. `u8` values) that represents the string value; and also, a length value, +a pointer to an array of bytes (i.e., `u8` values) that represents the string value; and also, a length value, which specifies the size of the slice, or, how many elements there is in the slice. It's worth to emphasize that the array of bytes in a string object is not null-terminated, like in a string literal value. @@ -1182,7 +1182,7 @@ So if your string literal is not UTF-8 encoded, then, you will likely have probl Let's take for example the word "Hello". In UTF-8, this sequence of characters (H, e, l, l, o) is represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this sequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values, -and ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then, +and ask Zig to print this sequence of bytes as a sequence of characters (i.e., a string), then, the text "Hello" will be printed into the terminal: ```{zig} @@ -1229,10 +1229,10 @@ and this array is also null-terminated. But one key difference between a Zig string literal and a C string, is that Zig also stores the length of the string inside the object itself. In the case of a string literal value, this length is stored in the -data type of the value (i.e. the `n` variable in `[n:0]u8`). While, in a string object, the length is stored +data type of the value (i.e., the `n` variable in `[n:0]u8`). While, in a string object, the length is stored in the `len` attribute of the slice that represents the string object. This small detail makes your code safer, -because it is much easier for the Zig compiler to check if you are trying to access an element that is -"out of bounds", i.e. if your trying to access memory that does not belong to you. +because it's much easier for the Zig compiler to check if you are trying to access an element that is +"out of bounds", i.e., if your trying to access memory that does not belong to you. To achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless. So getting this kind of safety is not automatic and much harder to do in C. For example, if you want @@ -1297,7 +1297,7 @@ Now, if we create an pointer to the `simple_array` object, then, we get a consta which is very similar to the type of the string literal value. This demonstrates that a string literal value in Zig is already a pointer to a null-terminated array of bytes. -Furthermore, if we take a look at the type of the `string_obj` object, you will see that it is a +Furthermore, if we take a look at the type of the `string_obj` object, you will see that it's a slice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence the `const u8` portion of the type). diff --git a/Chapters/02-debugging.qmd b/Chapters/02-debugging.qmd index 23751eb7..15c337bc 100644 --- a/Chapters/02-debugging.qmd +++ b/Chapters/02-debugging.qmd @@ -37,7 +37,7 @@ is behaving. Many programmers often resort to the print functions in Zig, such as the `stdout.print()`, or, the `std.debug.print()`, to get a better understanding of their programs. -This is a known and old strategy that is very simple and effective, and it is better known within +This is a known and old strategy that is very simple and effective, and it's better known within the programming community as *print debugging*. In Zig, you can print information to the `stdout` or `stderr` streams of your system. @@ -78,7 +78,7 @@ Here is a quick list of the most used format specifiers: - `s`: for printing strings. - `p`: for printing memory addresses. - `x`: for printing hexadecimal values. -- `any`: use any compatible format specifier (i.e. it automatically selects a format specifier for you). +- `any`: use any compatible format specifier (i.e., it automatically selects a format specifier for you). The code example below gives you an example of use of this `print()` method with the `d` format specifier. @@ -98,7 +98,7 @@ pub fn main() !void { } ``` -It is important to emphasize that, the `stdout.print()` method, as you would expect, +It's important to emphasize that, the `stdout.print()` method, as you would expect, prints your template string into the `stdout` stream of your system. However, you can also print your template string into the `stderr` stream if your prefer. All you need to do, is to replace the `stdout.print()` @@ -188,7 +188,7 @@ pub fn main() !void { } ``` -There is nothing wrong with this program. But it is +There is nothing wrong with this program. But it's a good start for us. First, we need to compile this program with the `zig build-exe` command. For this example, suppose that I have compiled the above @@ -207,7 +207,7 @@ lldb add_program From now on, LLDB is started, and you can know that I'm executing LLDB commands by looking at the prefix `(lldb)`. If something is prefixed with `(lldb)`, then you know -that it is a LLDB command. +that it's a LLDB command. The first thing I will do, is to set a breakpoint at the `main()` function, by executing `b main`. diff --git a/Chapters/03-structs.qmd b/Chapters/03-structs.qmd index 1f603615..999845d4 100644 --- a/Chapters/03-structs.qmd +++ b/Chapters/03-structs.qmd @@ -176,7 +176,7 @@ comes from the Zig Standard Library. More precisely, from the [`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod]. There are multiple lines in this function, but I omitted them to focus solely on the switch statement found in this function. Notice that this switch statement has four -possible cases (i.e. four explicit branches). Also, notice that we used an `else` branch +possible cases (i.e., four explicit branches). Also, notice that we used an `else` branch in this case. An `else` branch in a switch statement works as the "default branch". @@ -240,7 +240,7 @@ t.zig:9:13: 0x1033c58 in main (switch2) Furthermore, you can also use ranges of values in switch statements. That is, you can create a branch in your switch statement that is used whenever the input value is within the specified range. These "range expressions" -are created with the operator `...`. It is important +are created with the operator `...`. It's important to emphasize that the ranges created by this operator are inclusive on both ends. @@ -555,7 +555,7 @@ In Zig, you can explicitly stop the execution of a loop, or, jump to the next it the keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is, at first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`. But what makes this `while` loop stop when the `i` object reaches the count -10? It is the `break` keyword! +10? It's the `break` keyword! Inside the while loop, we have an if statement that is constantly checking if the `i` variable is equal to 10. Since we are incrementing the value of `i` at each iteration of the @@ -565,7 +565,7 @@ will execute the `break` expression, and, as a result, the execution of the whil Notice the use of the `expect()` function from the Zig Standard Library after the while loop. This `expect()` function is an "assert" type of function. This function checks if the logical test provided is equal to true. If so, the function do nothing. -Otherwise (i.e. the logical test is equal to false), the function raises an assertion error. +Otherwise (i.e., the logical test is equal to false), the function raises an assertion error. ```{zig} #| auto_main: true @@ -624,7 +624,7 @@ cannot assign values to them inside the body's function. This is the reason why, the code example below does not compile successfully. If you try to compile this code example, you will get a compile error message about "trying to change the value of a -immutable (i.e. constant) object". +immutable (i.e., constant) object". ```{zig} #| eval: false @@ -677,7 +677,7 @@ You can change the value that the pointer points to, by dereferencing it. Therefore, if we take our previous `add2()` example, we can change the value of the function argument `x` inside the function's body by marking the `x` argument as a -"pointer to a `u32` value" (i.e. `*u32` data type), instead of a `u32` value. +"pointer to a `u32` value" (i.e., `*u32` data type), instead of a `u32` value. By making it a pointer, we can finally alter the value of this function argument directly inside the body of the `add2()` function. You can see that the code example below compiles successfully. @@ -883,7 +883,7 @@ usually declare this method as a function that has a `self` argument. This `self` argument is the reference to the object itself from which the method is being called from. -It is not mandatory to use this `self` argument. But why would you not use this `self` argument? +It's not mandatory to use this `self` argument. But why would you not use this `self` argument? There is no reason to not use it. Because the only way to get access to the data stored in the data members of your struct is to access them through this `self` argument. If you don't need to use the data in the data members of your struct inside your method, you very likely don't need @@ -970,7 +970,7 @@ But why? Why am I talking about this here? It's because the `self` argument in the methods are affected depending on whether the methods present in a struct change or don't change the state of the object itself. More specifically, when you have a method in a struct that changes the state -of the object (i.e. changes the value of a data member), the `self` argument +of the object (i.e., changes the value of a data member), the `self` argument in this method must be annotated in a different manner. As I described in @sec-self-arg, the `self` argument in methods of @@ -1070,7 +1070,7 @@ So remember, every function argument is immutable in Zig, and `self` is no exception to this rule. In this example, we marked the `v3` object as a variable object. -But this does not matter. Because it is not about the input object, it is about +But this does not matter. Because it's not about the input object, it's about the function argument. The problem begins when we try to alter the value of `self` directly, which is a function argument, @@ -1105,7 +1105,7 @@ as input. In general, type inference in Zig is done by using the dot character (`.`). Everytime you see a dot character written before a struct literal, or before an enum value, or something like that, -you know that this dot character is playing a special part in this place. More specifically, it is +you know that this dot character is playing a special part in this place. More specifically, it's telling the `zig` compiler something along the lines of: "Hey! Can you infer the type of this value for me? Please!". In other words, this dot character is playing a similar role as the `auto` keyword in C++. @@ -1137,8 +1137,8 @@ switch statements that begin with a dot character, such as `.release` and `.acqu Because these weird values contain a dot character before them, we are asking the `zig` compiler to infer the types of these values inside the switch statement. Then, the `zig` -compiler is looking into the current context where these values are being used, and it is -trying to infer the types of these values. +compiler is looking into the current context where these values are being used, and trying +to infer the types of these values. Since they are being used inside a switch statement, the `zig` compiler looks into the type of the input object given to the switch statement, which is the `order` object in this case. @@ -1187,7 +1187,7 @@ is commonly used on switch statements in Zig. In this section, I want to discuss type casting (or, type conversion) with you. We use type casting when we have an object of type "x", and we want to convert -it into an object of type "y", i.e. we want to change the data type of the object. +it into an object of type "y", i.e., we want to change the data type of the object. Most languages have a formal way to perform type casting. In Rust for example, we normally use the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`. @@ -1195,7 +1195,7 @@ In Zig, we use the `@as()` built-in function to cast an object of type "x", into an object of type "y". This `@as()` function is the preferred way to perform type conversion (or type casting) -in Zig. Because it is explicit, and, it also performs the casting only if it +in Zig. Because it's explicit, and, it also performs the casting only if it is unambiguous and safe. To use this function, you just provide the target data type in the first argument, and, the object that you want cast as the second argument. @@ -1212,8 +1212,8 @@ test { ``` This is the general way to perform type casting in Zig. But remember, `@as()` works only when casting -is unambiguous and safe, and there are situations where these assumptions do not hold. For example, -when casting an integer value into a float value, or vice-versa, it is not clear to the compiler +is unambiguous and safe—there are situations where these assumptions do not hold. For example, +when casting an integer value into a float value, or vice-versa, it's not clear to the compiler how to perform this conversion safely. Therefore, we need to use specialized "casting functions" in such situations. @@ -1244,7 +1244,7 @@ Another built-in function that is very useful when performing type casting opera In essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object from a type "x" to a type "y", etc. However, pointers (we are going to discuss pointers in more depth in @sec-pointer) are a special type of object in Zig, -i.e. they are treated differently from "normal objects". +i.e., they are treated differently from "normal objects". Everytime a pointer is involved in some "type casting operation" in Zig, the `@ptrCast()` function is used. This function works similarly to `@floatFromInt()`. @@ -1273,7 +1273,7 @@ test { ## Modules We already talked about what modules are, and also, how to import other modules into -your current module via *import statements*. Every Zig module (i.e. a `.zig` file) that you write in your project +your current module via *import statements*. Every Zig module (i.e., a `.zig` file) that you write in your project is internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the Zig Standard Library into our current module. diff --git a/Chapters/04-http-server.qmd b/Chapters/04-http-server.qmd index e4804dd8..06e115e6 100644 --- a/Chapters/04-http-server.qmd +++ b/Chapters/04-http-server.qmd @@ -38,7 +38,7 @@ through this connection. But the messages that are transmitted inside this connection are in a specific format. They are HTTP messages -(i.e. messages that use the HTTP Protocol specification). +(i.e., messages that use the HTTP Protocol specification). The HTTP Protocol is the backbone of the modern web. The world wide web as we know it today, would not exist without the HTTP Protocol. @@ -91,7 +91,7 @@ that connected to the server is asking this server to do something for him. There are different "types of request" that a client can send to a HTTP Server. But the most basic type of request, is when a client ask to the -HTTP Server to serve (i.e. to send) some specific web page (which is a HTML file) to him. +HTTP Server to serve (i.e., to send) some specific web page (which is a HTML file) to him. When you type `google.com` in your web browser, you are essentially sending a HTTP Request to Google's HTTP servers. This request is asking these servers to send the Google webpage to you. @@ -137,7 +137,7 @@ You are creating a channel where people can send messages through. When you create a socket object, this object is not binded to any particular address. This means that with this object you have a representation of a channel of communication in your hands. But this channel is not currently available, or, it is not currently accessible, -because it do not have a known address where you can find it. +because it does not have a known address where you can find it. That is what the "bind" operation do. It binds a name (or more specifically, an address) to this socket object, or, this channel of communication, so that it becomes available, @@ -174,7 +174,7 @@ which is a sequence of 4 numbers separated by dot characters (`.`) that identifi While the second component is a port number, which identifies the specific door, or, the specific port to use in the host machine. -The sequence of 4 numbers (i.e. the host) identifies the machine (i.e. the computer itself) where +The sequence of 4 numbers (i.e., the host) identifies the machine (i.e., the computer itself) where this socket will live in. Every computer normally have multiple "doors" available inside of him, because this allows the computer to receive and work with multiple connections at the same time. He simply use a single door for each connection. So the port number, is @@ -273,7 +273,7 @@ you will notice that the programs keeps running indefinitely, without a clear end. This happens, because the program is waiting for something to happen. -It is waiting for someone to try to connect to the address (`http://127.0.0.1:3490`) where +It's waiting for someone to try to connect to the address (`http://127.0.0.1:3490`) where the server is running and listening for incoming connections. This is what the `listen()` method do, it makes the socket to be active waiting for someone to connect. @@ -329,7 +329,7 @@ terminates as soon as the connection is accepted. ### Reading the message from the client {#sec-read-http-message} -Now that we have a connection established, i.e. the connection +Now that we have a connection established, i.e., the connection object that we created through the `accept()` function, we can now use this connection object to read any messages that the client send to our server. But we can also use it to send messages back @@ -566,7 +566,7 @@ and third, we have the version of the HTTP protocol that is being used in this H In the snippet below, you can find an example of this first line in a HTTP Request. First, we have the HTTP method of this request (`GET`). Many programmers refer to the URI component (`/users/list`) as the "API endpoint" to which the HTTP Request -is being sent to. In the context of this specific request, since it is a GET request, +is being sent to. In the context of this specific request, since it's a GET request, you could also say that the URI component is the path to the resource we want to access, or, the path to the document (or the file) that we want to retrieve from the server. @@ -609,9 +609,9 @@ of this `Accept` header. ### The body -The body comes after the list of HTTP headers, and it is an optional section of the HTTP Request, meaning that, not -all HTTP Request will come with a body in it. For example, every HTTP Request that uses the -GET method usually do not come with a body. +The body comes after the list of HTTP headers, and it's an optional section of the HTTP Request, meaning that, not +all HTTP Requests will come with a body in them. For example, every HTTP Request that uses the +GET method usually does not come with a body. Because a GET request is used to request data, instead of sending it to the server. So, the body section is more related to the POST method, which is a method that involves @@ -635,7 +635,7 @@ is identified by one these words: - and some other methods. Each HTTP method is used for a specific type of task. The POST method for example is normally -used to post some data into the destination. In other words, it is used +used to post some data into the destination. In other words, it's used to send some data to the HTTP server, so that it can be processed and stored by the server. As another example, the GET method is normally used to get content from the server. @@ -679,7 +679,7 @@ But in order to build these functions, I will use a functionality from the Zig S `StaticStringMap()`. This function allows us to create a simple map from strings to enum values. In other words, we can use this map structure to map a string to the respective enum value. To some extent, this specific structure from the standard library works almost like a "hashtable" structure, -and it is optimized for small sets of words, or, small sets of keys, which is our case here. +and it's optimized for small sets of words, or, small sets of keys, which is our case here. We are going to talk more about hashtables in Zig in @sec-maps-hashtables. To use this "static string map" structure, you have to import it from the `std.static_string_map` module @@ -687,9 +687,9 @@ of the Zig Standard Library. Just to make things shorter and easier to type, I a function through a different and shorter name (`Map`). With `Map()` imported, we can just apply this function over the enum structure -that we are going to use in the resulting map. In our case here, it is the `Method` enum structure +that we are going to use in the resulting map. In our case here, it's the `Method` enum structure that we declared at the last code example. Then, I call the `initComptime()` method with the -map, i.e. the list of key-value pairs that we are going to use. +map, i.e., the list of key-value pairs that we are going to use. You can see in the example below that I wrote this map using multiple anonymous struct literals. Inside the first (or "top-level") struct literal, we have a list (or a sequence) of struct literals. @@ -762,7 +762,7 @@ actually parsing the HTTP Request. The first thing we can do, is to write a struct to represent the HTTP Request. Take the `Request` struct below as an example. It contains the three -essential information from the "top-level" header (i.e. the first line) +essential information from the "top-level" header (i.e., the first line) in the HTTP Request. ```{zig} @@ -956,7 +956,7 @@ pub fn send_404(conn: Connection) !void { Notice that both functions receives the connection object as input, and use the `write()` method to write the HTTP Response message directly into this communication channel. As result, the party in the other -side of the connection (i.e. the client), will receive such message. +side of the connection (i.e., the client), will receive such message. Most real-world HTTP Servers will have a single function (or a single struct) to effectively handle the response. It gets the HTTP Request already parsed as input, and then, it tries to build diff --git a/Chapters/05-pointers.qmd b/Chapters/05-pointers.qmd index bf8eba08..f75cbe85 100644 --- a/Chapters/05-pointers.qmd +++ b/Chapters/05-pointers.qmd @@ -23,11 +23,11 @@ Pointers in Zig are similar to pointers in C. But they come with some extra adva A pointer is an object that contains a memory address. This memory address is the address where a particular value is stored in memory. It can be any value. Most of the times, -it is a value that comes from another object (or variable) present in our code. +it's a value that comes from another object (or variable) present in our code. In the example below, I'm creating two objects (`number` and `pointer`). The `pointer` object contains the memory address where the value of the `number` object -(the number 5) is stored. So, that is a pointer in a nutshell. It is a memory +(the number 5) is stored. So, that is a pointer in a nutshell. It's a memory address that points to a particular existing value in the memory. You could also say, that, the `pointer` object points to the memory address where the `number` object is stored. @@ -103,7 +103,7 @@ try stdout.print("{d}\n", .{number}); Therefore, as I mentioned earlier, people use pointers as an alternative way to access a particular value. And they use it especially when they do not want to "move" these values around. There are situations where, -you want to access a particular value in a different scope (i.e. a different location) of your code, +you want to access a particular value in a different scope (i.e., a different location) of your code, but you do not want to "move" this value to this new scope (or location) that you are in. This matters especially if this value is big in size. Because if it is, then, @@ -178,7 +178,7 @@ We can have a constant pointer that points to a constant value. But we can also have a variable pointer that points to a constant value. And vice-versa. Until this point, the `pointer` object was always constant, -but what this means for us? What is the consequence of the +but what does this mean for us? What is the consequence of the `pointer` object being constant? The consequence is that we cannot change the pointer object, because it is constant. We can use the pointer object in multiple ways, but we cannot change the @@ -377,7 +377,7 @@ the `*` identifies it as a pointer object. In the example below, we are creating a variable object named `num`, and an optional pointer object named `ptr`. Notice that the data type of the object -`ptr` indicates that it is either a null value, or a pointer to an `i32` value. +`ptr` indicates that it's either a null value, or a pointer to an `i32` value. Also, notice that the pointer object (`ptr`) can be marked as optional, even if the object `num` is not optional. @@ -418,7 +418,7 @@ _ = ptr; ### Null handling in optionals {#sec-null-handling} When you have an optional object in your Zig code, you have to explicitly handle -the possibility of this object being null. It is like error-handling with `try` and `catch`. +the possibility of this object being null. It's like error-handling with `try` and `catch`. In Zig you also have to handle null values like if they were a type of error. We can do that, by using either: diff --git a/Chapters/07-build-system.qmd b/Chapters/07-build-system.qmd index 349fc81b..6c64c0cd 100644 --- a/Chapters/07-build-system.qmd +++ b/Chapters/07-build-system.qmd @@ -96,7 +96,7 @@ We are going to talk more about these target objects in @sec-targets. ## The `build()` function {#sec-build-fun} A build script in Zig always contains a public (and top-level) `build()` function declared. -It is like the `main()` function on the main Zig module of your project, that we discussed in @sec-main-file. +It's like the `main()` function in the main Zig module of your project, that we discussed in @sec-main-file. But instead of creating the entrypoint to your code, this `build()` function is the entrypoint to the build process. This `build()` function should accept a pointer to a `Build` object as input, and it should use this "build object" to perform @@ -194,13 +194,13 @@ currently running the `zig` compiler. At last, the `root_source_file` option specifies the root Zig module of your project. -That is the Zig module that contains the entrypoint to your application (i.e. the `main()` function), or, the main API of your library. +That is the Zig module that contains the entrypoint to your application (i.e., the `main()` function), or, the main API of your library. This also means that, all the Zig modules that compose your project are automatically discovered from the import statements you have inside this "root source file". The `zig` compiler can detect when a Zig module depends on the other through the import statements, and, as a result, it can discover the entire map of Zig modules used in your project. -This is handy, and it is different from what happens in other build systems. +This is handy, and it's different from what happens in other build systems. In CMake for example, you have to explicitly list the paths to all source files that you want to include in your build process. This is probably a symptom of the "lack of conditional compilation" in the C and C++ compilers. Since they lack this feature, you have @@ -261,7 +261,7 @@ In Zig, we have four build modes (which are listed below). Each one of these bui different advantages and characteristics. As we described in @sec-compile-debug-mode, the `zig` compiler uses the `Debug` build mode by default, when you don't explicitly choose a build mode. -- `Debug`, mode that produces and includes debugging information in the output of the build process (i.e. the binary file defined by the target object); +- `Debug`, mode that produces and includes debugging information in the output of the build process (i.e., the binary file defined by the target object); - `ReleaseSmall`, mode that tries to produce a binary file that is small in size; - `ReleaseFast`, mode that tries to optimize your code, in order to produce a binary file that is as fast as possible; - `ReleaseSafe`, mode that tries to make your code as safe as possible, by including safeguards when possible. @@ -475,7 +475,7 @@ A test target object essentially selects all `test` blocks in all Zig modules across your project, and builds only the source code present inside these `test` blocks in your project. As a result, this target object creates an executable file that contains only the source code present -in all of these `test` blocks (i.e. the unit tests) in your project. +in all of these `test` blocks (i.e., the unit tests) in your project. Perfect! Now that we have declared this test target object, an executable file named `unit_tests` is built by the `zig` compiler when we trigger the build @@ -674,7 +674,7 @@ through the `cc` command of the `zig` compiler. As an example, let's use the famous [FreeType library](https://freetype.org/)[^freetype]. FreeType is one of the most widely used pieces of software in the world. -It is a C library designed to produce high-quality fonts. But it is also +It's a C library designed to produce high-quality fonts. But it's also heavily used in the industry to natively render text and fonts in the screen of your computer. @@ -777,7 +777,7 @@ Now that we declared both the files that we want to include and the C compiler f we can add them to the target object that describes the FreeType library, by using the `addCSourceFile()` and `addCSourceFiles()` methods. -Both of these functions are methods from a `Compile` object (i.e. a target object). +Both of these functions are methods from a `Compile` object (i.e., a target object). The `addCSourceFile()` method is capable of adding a single C file to the target object, while the `addCSourceFiles()` method is used to add multiple C files in a single command. You might prefer to use `addCSourceFile()` when you need to use different compiler flags @@ -871,7 +871,7 @@ lib.addLibraryPath(lib_path); ### Adding include paths {#sec-include-paths} The preprocessor search path is a popular concept from the -C community, but it is also known by many C programmers as "include paths", because +C community, but it's also known by many C programmers as "include paths", because the paths in this "search path" relate to the `#include` statements found in the C files. Include paths are similar to library paths. They are a set of pre-defined places in your computer where diff --git a/Chapters/09-data-structures.qmd b/Chapters/09-data-structures.qmd index 4b8f99cd..add3878e 100644 --- a/Chapters/09-data-structures.qmd +++ b/Chapters/09-data-structures.qmd @@ -60,8 +60,8 @@ However, only a portion of these $n$ elements are being used most of the time. T of $n$ is the *length* of the array. So every time you append a new value to the array, you are incrementing its *length* by one. -This means that a dynamic array usually works with an extra margin, or, an extra space -which is currently empty, but it is waiting and ready to be used. This "extra space" +This means that a dynamic array usually works with an extra margin, or an extra space +that is currently empty, but waiting and ready to be used. This "extra space" is essentially the difference between *capacity* and *length*. *Capacity* represents the total number of elements that the array can hold without the need to re-allocate or re-expand the array, while the *length* represents how much of this capacity @@ -82,12 +82,12 @@ than what we currently have. A dynamic array works by expanding the underlying array, whenever the *length* becomes equal to the *capacity* of the array. It basically allocates a new contiguous block of memory that is bigger than the previous one, then, it copies all values that are currently being stored to this new -location (i.e. this new block of memory), then, it frees the previous block of +location (i.e., this new block of memory), then, it frees the previous block of memory. At the end of this process, the new underlying array have a bigger *capacity*, and, therefore, the *length* becomes, once again, smaller than the *capacity* of the array. -This is the cycle of an dynamic array. Notice that, throughout this cycle, the *capacity* is always -either equal to or higher than the *length* of the array. If youh have an `ArrayList` object (let's suppose +This is the cycle of a dynamic array. Notice that, throughout this cycle, the *capacity* is always +either equal to or higher than the *length* of the array. If you have an `ArrayList` object (let's suppose you named it `buffer`), you can check the current capacity of your array by accessing the `capacity` attribute of your `ArrayList` object, while the current *length* of it is available at the `items.len` attribute. @@ -181,7 +181,7 @@ the last value stored in the array. Also, this method returns as result the value that got deleted. That is, you can use this method to both get the last value in the array, and also, remove -it from the array. It is a "get and remove value" type of method. +it from the array. It's a "get and remove value" type of method. ```{zig} #| eval: false @@ -322,7 +322,7 @@ and you access each bucket by using an index. When you provide a key to a hashtable, it passes this key to the hash function. This hash function uses some sort of hashing algorithm to transform -this key into an index. This index is actually an array index. It is a position +this key into an index. This index is actually an array index. It's a position in the underlying array of the hashtable. This is how a key identifies a specific position (or location) inside the hashtable structure. @@ -341,18 +341,18 @@ The @fig-hashtable presents this process visually. The operation described in the previous paragraph is normally called an *insertion* operation. Because you are inserting new values into the hashtable. But there are other types of operations in hashtables such as *delete* and *lookup*. -Delete is self describing, it is when you delete (or remove) a value from the hashtable. +Delete is self describing, it's when you delete (or remove) a value from the hashtable. While lookup corresponds to when you look at a value that is stored in the hashtable, by using the key that identifies the location where this value is stored. Sometimes, instead of storing the values directly, the underlying array of the hashtable might be an array of pointers, -i.e. the buckets of the array stores pointers that points to the value, +i.e., the buckets of the array stores pointers that points to the value, or also, may be an array of linked lists. These cases are common on hashtables that allows duplicate keys, or, in other words, on hashtables that effectively handle "collisions" that may arise from the hash function. Duplicate keys, or this "collision" thing that I'm talking about, is when you have two different keys -that points to the same location (i.e. to the same index) +that points to the same location (i.e., to the same index) in the underlying array of the hashtable. This might happen depending on the characteristics of the hash function that is being used in the hashtable. Some implementations of the hashtable will actively deal with collisions, meaning that, they will handle this case in some way. For example, the hashtable @@ -360,7 +360,7 @@ might transform all buckets into linked lists. Because with a linked list you ca multiple values into a single bucket. There are different techniques to handle collisions in hashtables, which I will not describe -in this book, because it is not our main scope here. But you can find a good description of +in this book, because it's not our main scope here. But you can find a good description of some of the most common techniques at the Wikipedia page of hashtables [@wikipedia_hashtables]. @@ -378,7 +378,7 @@ the behaviour of the hashtable itself, because you can provide a hash function implementation to be used by the hashtable through this context object. -But let's not worry about this context object now, because it is meant to be used +But let's not worry about this context object now, because it's meant to be used by "experts in the field of hashtables". Since we are most likely not experts in this field, we are going to take the easy way to create a hashtable. Which is by using the `AutoHashMap()` function. @@ -459,7 +459,7 @@ that the method successfully deleted the value. But this delete operation might not be always successful. For example, you might provide the wrong key to this method. I mean, maybe you provide (either intentionally or unintentionally) a key that points to an empty bucket, -i.e. a bucket that still doesn't have a value in it. +i.e., a bucket that still doesn't have a value in it. In this case, the `remove()` method would return a `false` value. @@ -472,7 +472,7 @@ You can do that in Zig by using an iterator object that can iterate through the elements of your hashtable object. This iterator object works like any other iterator object that you would -find in languages such as C++ and Rust. It is basically a pointer object +find in languages such as C++ and Rust. It's basically a pointer object that points to some value in the container, and has a `next()` method that you can use to navigate (or iterate) through the values in the container. @@ -559,7 +559,7 @@ The `ArrayHashMap` struct creates a hashtable that is faster to iterate over. That is why this specific type of hashtable might be valuable to you. Some other properties of a `ArrayHashMap` hashtable are: -- the order of insertion is preserved, i.e. the order of the values that you find while iterating through this hashtable is actually the order in which these values were inserted in the hashtable. +- the order of insertion is preserved, i.e., the order of the values that you find while iterating through this hashtable is actually the order in which these values were inserted in the hashtable. - the key-value pairs are stored sequentially, one after another. @@ -578,7 +578,7 @@ a value from the hashtable by using the `get()` method. But the `remove()` metho in this specific type of hashtable. In order to delete values from the hashtable, you would use the same methods that you find in -an `ArrayList` object, i.e. a dynamic array. I presented these methods in @sec-dynamic-array-remove, +an `ArrayList` object, i.e., a dynamic array. I presented these methods in @sec-dynamic-array-remove, which are the `swapRemove()` and `orderedRemove()` methods. These methods have the same meaning here, or, the same effect that they have in an `ArrayList` object. @@ -610,7 +610,7 @@ What this means is that you cannot use a slice value to represent a key in these types of hashtable. The most obvious consequence of this, is that you cannot use strings as keys -in these hashtables. But it is extremely common to use strings as keys +in these hashtables. But it's extremely common to use strings as keys in hashtables. Take this very simple Javascript code snippet as an example. We are creating @@ -751,7 +751,7 @@ we are creating a singly linked list of `u32` values. So each node in this linked list will store a `u32` value. Both the `SinglyLinkedList()` and `DoublyLinkedList()` functions returns a type, -i.e. a struct definition, as output. Therefore, the object `Lu32` is actually +i.e., a struct definition, as output. Therefore, the object `Lu32` is actually a struct definition. It defines the type "singly linked list of `u32` values". Now that we have the definition of the struct, we need to instantiate a `Lu32` object. @@ -818,15 +818,15 @@ summary of them in the bullet points below: - `remove()` to remove a specific node from the linked list. - if singly linked list, `len()` to count how many nodes there is in the linked list. - if doubly linked list, checkout the `len` attribute to see how many nodes there is in the linked list. -- if singly linked list, `popFirst()` to remove the first node (i.e. the "head") from the linked list. +- if singly linked list, `popFirst()` to remove the first node (i.e., the "head") from the linked list. - if doubly linked list, `pop()` and `popFirst()` to remove the last and first nodes from the linked list, respectively. -- if doubly linked list, `append()` to add a new node to end of the linked list (i.e. inverse of `prepend()`). +- if doubly linked list, `append()` to add a new node to end of the linked list (i.e., inverse of `prepend()`). ## Multi array structure -Zig introduces a new data structure called `MultiArrayList()`. It is a different version of the dynamic array +Zig introduces a new data structure called `MultiArrayList()`. It's a different version of the dynamic array that we have introduced in @sec-dynamic-array. The difference between this structure and the `ArrayList()` that we know from @sec-dynamic-array, is that `MultiArrayList()` creates a separate dynamic array for each field of the struct that you provide as input. @@ -906,13 +906,13 @@ the internal array of the `PersonArray` object that contains the values of the ` data member from the `Person` values that were added to the multi array struct. In this example we are calling the `items()` method directly from the `PersonArray` -object. However, it is recommended on most situations to call this `items()` method +object. However, in most situations it's recommened to call this `items()` method from a "slice object", which you can create from the `slice()` method. The reason for this is that calling `items()` multiple times have better performance if you use a slice object. Therefore, if you are planning to access only one of the -internal arrays from your "multi array struct", it is fine to call `items()` directly +internal arrays from your "multi array struct", it's fine to call `items()` directly from the multi array object. But if you need to access many of the internal arrays from your "multi array struct", then, you will likely need to call `items()` more than once, and, in such circumstance, is better to call `items()` through a slice object. diff --git a/Chapters/09-error-handling.qmd b/Chapters/09-error-handling.qmd index ea05ebc7..301b4c29 100644 --- a/Chapters/09-error-handling.qmd +++ b/Chapters/09-error-handling.qmd @@ -92,8 +92,8 @@ fn print_name() !void { In the example above, we are using the exclamation mark to tell the `zig` compiler that this function might return some error. But which error exactly is returned from -this function? For now, we are not specifying a specific error value. We only -known for now that some error value (whatever it is) might be returned. +this function? For now, we are not specifying a specific error value. For now, +we only know that some error value (whatever it is) might be returned. But in fact, you can (if you want to) specify clearly which exact error values might be returned from this function. There are lot of examples of @@ -110,9 +110,9 @@ pub fn fill(conn: *Connection) ReadError!void { This idea of specifying the exact error values that you expect to be returned from the function is interesting. Because they automatically become some sort of documentation -of your function, and also, it allows the `zig` compiler to perform some extra checks over -your code. Because it can check if there is any other type of error value -that is being generated inside your function, and, that it is not being accounted +of your function, and also, this allows the `zig` compiler to perform some extra checks over +your code. Because the compiler can check if there is any other type of error value +that is being generated inside your function, and, that it's not being accounted for in this return type annotation. Anyway, you can list the types of errors that can be returned from the function @@ -131,9 +131,9 @@ When you have such a function, you can list all of these different types of errors that can be returned from this function, through a structure in Zig that we call of an *error set*. -An error set is a special case of an union type. It is an union that contains error values in it. -Not all programming languages have a notion of an "union object". -But in summary, an union is just a set of data types. +An error set is a special case of a union type. It's a union that contains error values in it. +Not all programming languages have a notion of a "union object". +But in summary, a union is just a set of data types. Unions are used to allow an object to have multiple data types. For example, a union of `x`, `y` and `z`, means that an object can be either of type `x`, or type `y` or type `z`. @@ -173,7 +173,7 @@ of the error set in the return type annotation, instead of using the error set d We can see that in the `ReadError` error set that we showed earlier in the `fill()` function, which is defined in the `http.Client` module. So yes, I presented the `ReadError` as if it was just a standard and single error value, but in fact, -it is an error set defined in the `http.Client` module, and therefore, it actually represents +it's an error set defined in the `http.Client` module, and therefore, it actually represents a set of different error values that might happen inside the `fill()` function. @@ -349,7 +349,7 @@ by the expression. The Zig official language reference, provides a great example of this "default value" strategy with `catch`. This example is reproduced below. Notice that we are trying to parse some unsigned integer from a string object named `str`. In other words, this function -is trying to transform an object of type `[]const u8` (i.e. an array of characters, a string, etc.) +is trying to transform an object of type `[]const u8` (i.e., an array of characters, a string, etc.) into an object of type `u64`. But this parsing process done by the function `parseU64()` may fail, resulting in a runtime error. @@ -383,7 +383,7 @@ But if this expression returns a valid value instead, then, this value is unwrap into the `number` object. This means that, if the `parseU64()` expression returns a valid value, this value becomes available -inside the scope of this "if branch" (i.e. the "true branch") through the object that we listed inside the pair +inside the scope of this "if branch" (i.e., the "true branch") through the object that we listed inside the pair of pipe character (`|`), which is the object `number`. If an error occurs, we can use an "else branch" (or the "false branch") of the if statement @@ -520,7 +520,7 @@ that our program will free the allocated memory for the `user` object, even if an error occurs inside the `create_user()` function. If you allocate and free some memory for an object inside the same scope, then, -just use `defer` and be happy, i.e. `errdefer` have no use for you in such situation. +just use `defer` and be happy, i.e., `errdefer` have no use for you in such situation. But if you allocate some memory in a scope A, but you only free this memory later, in a scope B for example, then, `errdefer` becomes useful to avoid leaking memory in sketchy situations. @@ -529,7 +529,7 @@ in sketchy situations. ## Union type in Zig {#sec-unions} -An union type defines a set of types that an object can be. It is like a list of +A union type defines a set of types that an object can be. It's like a list of options. Each option is a type that an object can assume. Therefore, unions in Zig have the same meaning, or, the same role as unions in C. They are used for the same purpose. You could also say that unions in Zig produces a similar effect to @@ -581,7 +581,7 @@ in this instantiation. You could also interpret this as: only one data member of an union type can be activated at a time, the other data members remain deactivated and unaccessible. For example, if you create a `LakeTarget` object that uses the `azure` data member, you can no longer use or access the data members `google` or `amazon`. -It is like if these other data members didn't exist at all in the `LakeTarget` type. +It's like if these other data members didn't exist at all in the `LakeTarget` type. You can see this logic in the example below. Notice that, we first instantiate the union object using the `azure` data member. As a result, this `target` object contains only diff --git a/Chapters/10-stack-project.qmd b/Chapters/10-stack-project.qmd index 99c0e241..8dc43567 100644 --- a/Chapters/10-stack-project.qmd +++ b/Chapters/10-stack-project.qmd @@ -44,7 +44,7 @@ a lot depending on whether this value is known at compile-time, or just at runti The `comptime` keyword is strongly related to these two spaces in time (compile-time and runtime). Let's quickly recap the differences. Compile-time is the period of time when your Zig source code is being compiled by the `zig` compiler, while the runtime is -the period of time when your Zig program is being executed, i.e. when we execute +the period of time when your Zig program is being executed, i.e., when we execute the binary files that were generated by the `zig` compiler. There are three ways in which you can apply the `comptime` keyword, which are: @@ -455,7 +455,7 @@ Notice that we use the allocator object to allocate a new array that is twice as than the current array (`self.capacity * 2`). After that, we use a different built-in function named `@memcpy()`. This built-in function -is equivalent to the `memcpy()` function from the C Standard Library[^cmemcpy]. It is used to +is equivalent to the `memcpy()` function from the C Standard Library[^cmemcpy]. It's used to copy the values from one block of memory to another block of memory. In other words, you can use this function to copy the values from one array into another array. @@ -574,8 +574,8 @@ of the stack into a generic array. In other words, this underlying array needs to be a "chameleon". It needs to adapt, and transform it into an array of any data type that we want. For example, if we need to create a stack that will store `u8` values, then this underlying array needs to be -a `u8` array (i.e. `[]u8`). But if we need to store `User` values instead, then, -this array needs to be a `User` array (i.e. `[]User`). Etc. +a `u8` array (i.e., `[]u8`). But if we need to store `User` values instead, then, +this array needs to be a `User` array (i.e., `[]User`). Etc. We do that by using a generic function. Because a generic function can receive a data type as input, and we can pass this data type to the struct definition of our `Stack` object. @@ -586,7 +586,7 @@ the struct definition that describes a `Stack` object that can store `User` valu Look at the code example below. I have omitted some parts of the `Stack` struct definition for brevity. However, if a specific part of our `Stack` struct is not exposed here -in this example, then it is because this part did not change from the previous example. +in this example, then it's because this part did not change from the previous example. It remains the same. @@ -629,7 +629,7 @@ We can just provide a data type to this function, and it will create a definitio `Stack` object that can store values of the data type that we have provided. In the example below, we are creating the definition of a `Stack` object that can store `u8` values in it. This definition is stored at the `Stacku8` object. -This `Stacku8` object becomes our new struct, it is the struct that we are going to use +This `Stacku8` object becomes our new struct, that we are going to use to create our `Stack` object. diff --git a/Chapters/12-file-op.qmd b/Chapters/12-file-op.qmd index cdf64326..f38845ff 100644 --- a/Chapters/12-file-op.qmd +++ b/Chapters/12-file-op.qmd @@ -47,8 +47,8 @@ In essence, these input/output functions from high-level languages are just abst over the *standard output* and *standard input* channels of your operating system. This means that we receive an input, or send some output, through the operating system. -It is the OS that makes the bridge between the user and your program. Your program -does not have a direct access to the user. It is the OS that intermediates every +It's the OS that makes the bridge between the user and your program. Your program +does not have a direct access to the user. It's the OS that intermediates every message exchanged between your program and the user. The *standard output* and *standard input* channels of your OS are commonly known as the @@ -97,12 +97,12 @@ Both of these objects are normally created from a file descriptor object. More s methods of this file descriptor object. If you are not familiar with this type of object, go to the next section. Every `GenericWriter` object have methods like `print()`, which allows you to write/send a formatted string -(i.e. this formatted string is like a `f` string in Python, or, similar to the `printf()` C function) +(i.e., this formatted string is like a `f` string in Python, or, similar to the `printf()` C function) into the "something" (file, socket, stream, etc.) that you are using. It also have a `writeAll()` method, which allows you to write a string, or, an array of bytes into the "something". Likewise, every `GenericReader` object have methods like `readAll()`, which allows you to read the -data from the "something" (file, socket, stream, etc.) until it fills a particular array (i.e. a "buffer") object. +data from the "something" (file, socket, stream, etc.) until it fills a particular array (i.e., a "buffer") object. In other words, if you provide an array object of 300 `u8` values to `readAll()`, then, this method attempts to read 300 bytes of data from the "something", and it stores them into the array object that you have provided. @@ -110,7 +110,7 @@ We also have other methods, like the `readAtLeast()` method, which allows you to many bytes exactly you want to read from the "something". In more details, if you give the number $n$ as input to this method, then, it will attempt to read at least $n$ bytes of data from the "something". The "something" might have less than $n$ bytes of data available for you -to read, so, it is not guaranteed that you will get precisely $n$ bytes as result. +to read, so, it's not guaranteed that you will get precisely $n$ bytes as result. Another useful method is `readUntilDelimiterOrEof()`. In this method, you specify a "delimiter character". The idea is that this function will attempt to read as many bytes of data as possible from the "something", @@ -126,7 +126,7 @@ This is just a quick description of the methods present in these types of object to read the official docs, both for [`GenericWriter`](https://ziglang.org/documentation/master/std/#std.io.GenericWriter)[^gen-write] and [`GenericReader`](https://ziglang.org/documentation/master/std/#std.io.GenericReader)[^gen-read]. -I also think it is a good idea to read the source code of the modules in the Zig Standard Library +I also think it's a good idea to read the source code of the modules in the Zig Standard Library that defines the methods present in these objects, which are the [`Reader.zig`](https://github.com/ziglang/zig/blob/master/lib/std/io/Reader.zig)[^mod-read] and [`Writer.zig`]()[^mod-write]. @@ -223,7 +223,7 @@ use them here, from the file descriptor object of `stdout`, and vice-versa. ### The *standard input* -You can access the *standard input* (i.e. `stdin`) in Zig by using the `getStdIn()` function from the `std.io` module. +You can access the *standard input* (i.e., `stdin`) in Zig by using the `getStdIn()` function from the `std.io` module. Like its brother (`getStdOut()`), this function also returns a file descriptor object that describes the `stdin` channel of your OS. @@ -278,22 +278,22 @@ the purpose of this channel. ## Buffered IO As we described in @sec-io-basics, input/output (IO) operations are made directly by the operating system. -It is the OS that manages the IO resource that you want to use for your IO operations. -The consequence of this fact is that IO operations are heavily based on system calls (i.e. calling the operating system directly). +It's the OS that manages the IO resource that you want to use for your IO operations. +The consequence of this fact is that IO operations are heavily based on system calls (i.e., calling the operating system directly). Just to be clear, there is nothing particularly wrong with system calls. We use them all the time on any serious codebase written in any low-level programming language. However, system calls are always orders of magnitude slower than many different types of operations. So is perfectly fine to use a system call once in a while. But when these system calls are used often, -you can clearly notice most of the time the loss of performance in your application. So, the good rule of thumbs -is to use a system call only when it is needed, and also, only in infrequent situations, to reduce +you can clearly notice most of the time the loss of performance in your application. So, the good rule of thumb +is to use a system call only when it's needed, and also, only in infrequent situations, to reduce the number of system calls performed to a minimum. ### Understanding how buffered IO works -Buffered IO is a strategy to achieve better performance. It is used to reduce the number of system calls made by IO operations, and, as +Buffered IO is a strategy to achieve better performance. It's used to reduce the number of system calls made by IO operations, and, as consequence, achieve a much higher performance. In @fig-unbuffered-io and @fig-buffered-io you can find two different diagrams which presents the difference between read operations performed in an unbuffered IO environment versus a buffered IO environment. @@ -306,7 +306,7 @@ More precisely, in the diagram exposed in @fig-unbuffered-io we get one system c On the other hand, in @fig-buffered-io we have only one system call at the very beginning. When we use a buffered IO system, at the first read operation we perform, instead of sending one single byte directly -to our program, the OS first sends a chunk of bytes from the file to a buffer object (i.e. an array). +to our program, the OS first sends a chunk of bytes from the file to a buffer object (i.e., an array). This chunk of bytes are cached/stored inside this buffer object. Therefore, from now on, for every new read operation that you perform, instead of making a new system call to ask @@ -323,7 +323,7 @@ this next byte already cached and ready to go. -This is the basic logic behind buffered IO systems. The size of the buffer object depends on multiple factors. But it is usually +This is the basic logic behind buffered IO systems. The size of the buffer object depends on multiple factors. But it's usually equal to the size of a full page of memory (4096 bytes). If we follow this logic, then, the OS reads the first 4096 bytes of the file and caches it into the buffer object. As long as your program does not consume all of these 4096 bytes from the buffer, you will not create new system calls. @@ -339,7 +339,7 @@ IO operations made through a `FILE` pointer in C are buffered by default, so, at least in C, you don't need to worry about this subject. But in contrast, IO operations in both Rust and Zig are not buffered depending on which functions from the standard libraries that you are using. -For example, in Rust, buffered IO is implemented through the `BufReader` and `BufWriter` structs, while in Zig, it is implemented +For example, in Rust, buffered IO is implemented through the `BufReader` and `BufWriter` structs, while in Zig, it's implemented through the `BufferedReader` and `BufferedWriter` structs. So any IO operation that you perform through the `GenericWriter` and `GenericReader` objects that I presented in @sec-writer-reader are not buffered, which means that these objects @@ -410,7 +410,7 @@ and have the exact same methods. So, although these two types of objects perform they have the same interface, so you, the programmer, can interchangeably use them without the need to change anything in your source code. So a buffered IO reader or a buffered IO writer objects have the same methods than its generic and unbuffered brothers, -i.e. the generic reader and generic writer objects that I presented in @sec-writer-reader. +i.e., the generic reader and generic writer objects that I presented in @sec-writer-reader. ::: {.callout-tip} In general, you should always use a buffered IO reader or a buffered IO writer object to perform @@ -429,15 +429,15 @@ computer are considered an IO resource, as we described in @sec-file-descriptor. ### The concept of current working directory (CWD) The working directory is the folder on your computer where you are currently rooted at. -In other words, it is the folder that your program is currently looking at. +In other words, it's the folder that your program is currently looking at. Therefore, whenever you are executing a program, this program is always working with -a specific folder on your computer. It is always in this folder that the program will initially -look for the files you require, and it is also in this folder that the program +a specific folder on your computer. It's always in this folder that the program will initially +look for the files you require, and it's also in this folder that the program will initially save all the files you ask it to save. The working directory is determined by the folder from which you invoke your program in the terminal. In other words, if you are in the terminal of your OS, and you -execute a binary file (i.e. a program) from this terminal, the folder to which your terminal +execute a binary file (i.e., a program) from this terminal, the folder to which your terminal is pointing at is the current working directory of your program that is being executed. In @fig-cwd we have an example of me executing a program from the terminal. We are executing @@ -461,12 +461,12 @@ current working directory, you must provide a path to that file or folder. A path is essentially a location. It points to a location in your filesystem. We use paths to describe the location of files and folders in our computer. One important aspect about paths is that they are always written inside strings, -i.e. they are always provided as text values. +i.e., they are always provided as text values. There are two types of paths that you can provide to any program in any OS: a relative path, or an absolute path. Absolute paths are paths that start at the root of your filesystem, and go all the way to the file name or the specific folder that you are referring to. This type of path is called absolute, because it points to an unique and absolute location on your computer. -That is, there is no other existing location on your computer that corresponds to this path. It is an unique identifier. +That is, there is no other existing location on your computer that corresponds to this path. It's an unique identifier. In Windows, an absolute path is a path that starts with a hard disk identifier (e.g. `C:/Users/pedro`). On the other hand, absolute paths in Linux and macOS, are paths that start with a forward slash character (e.g. `/usr/local/bin`). @@ -545,7 +545,7 @@ and it will create the file by following this path, which is relative to the CWD This function might return an error, so, you should use `try`, `catch`, or any of the other methods presented in @sec-error-handling to handle the possible error. But if everything goes well, -this `createFile()` method returns a file descriptor object (i.e. a `File` object) as result, +this `createFile()` method returns a file descriptor object (i.e., a `File` object) as result, through which you can add content to the file with the IO operations that I presented before. Take this code example below. In this example, we are creating a new text file @@ -585,7 +585,7 @@ in erase all the contents of the existing file. If you don't want this to happen, meaning, that you don't want to overwrite the contents of the existing file, but you want to write data to this file anyway -(i.e. you want to append data to the file), you should use the `openFile()` +(i.e., you want to append data to the file), you should use the `openFile()` method from the `Dir` object. Another important aspect about `createFile()` is that this method creates a file @@ -702,7 +702,7 @@ try cwd.deleteFile("foo.txt"); ### Copying files To copy existing files, we use the `copyFile()` method. The first argument in this method -is the path to the file that you want to copy. The second argument is a `Dir` object, i.e. a directory handler, +is the path to the file that you want to copy. The second argument is a `Dir` object, i.e., a directory handler, more specifically, a `Dir` object that points to the folder in your computer where you want to copy the file to. The third argument is the new path of the file, or, in other words, the new location of the file. The fourth argument is the options (or flags) to be used in the copy operation. diff --git a/Chapters/13-image-filter.qmd b/Chapters/13-image-filter.qmd index 513b83c3..55ebd3cc 100644 --- a/Chapters/13-image-filter.qmd +++ b/Chapters/13-image-filter.qmd @@ -137,7 +137,7 @@ Also notice in @fig-img-display that, because a raster image is essentially a 2D the image is organized into rows and columns of pixels. The columns are defined by the horizontal x axis, while the rows are defined by the vertical y axis. -Each pixel (i.e. the gray rectangles) exposed in @fig-img-display contains a number inside of it. +Each pixel (i.e., the gray rectangles) exposed in @fig-img-display contains a number inside of it. These numbers are the indexes of the pixels. You can notice that the first pixels are in the top and left corner, and also, that the indexes of these pixels "grow to the sides", or, in other words, they grow in the direction of the horizontal x axis. Most raster images are organized as rows of pixels. Thus, when these digital images are @@ -167,7 +167,7 @@ Therefore, we need to create an array of 36 `u8` values to store this small imag The reason why unsigned 8-bit integer (`u8`) values are used to represent the amounts of each color, instead of any other integer type, is because they take the minimum amount of space as possible, or, -the minimum amount of bits as possible. Which helps to reduces the binary size of the image, i.e. the 2D matrix. +the minimum amount of bits as possible. Which helps to reduces the binary size of the image, i.e., the 2D matrix. Also, they convey a good amount of precision and detail about the colors, even though they can represent a relatively small range (from 0 to 255) of "color amounts". @@ -227,11 +227,11 @@ are developing here. There are some C libraries available that we can use to read and parse PNG files. The most famous and used of all is `libpng`, which is the "official library" for reading and writing -PNG files. Although this library is available on most operating system, it is well known +PNG files. Although this library is available on most operating system, it's well known for being complex and hard to use. That is why, I'm going to use a more modern alternative here in this project, which is the `libspng` library. -I choose to use this C library here, because it is much, much simpler to use than `libpng`, +I choose to use this C library here, because it's much, much simpler to use than `libpng`, and it also offers very good performance for all operations. You can checkout the [official website of the library](https://libspng.org/)[^libspng] to know more about it. You will also find there some documentation that might help you to understand and @@ -506,7 +506,7 @@ $${#eq-grayscale} This @eq-grayscale is the formula to calculate the linear luminance of a pixel. It's worth noting that this formula works only for images whose pixels are using the sRGB color space, which is the standard color space for the web. Thus, ideally, all images on the web should use this color space. Luckily, -this is our case here, i.e. the `pedro_pascal.png` image is using this sRGB color space, and, as consequence, +this is our case here, i.e., the `pedro_pascal.png` image is using this sRGB color space, and, as consequence, we can use the @eq-grayscale. You can read more about this formula at the Wikipedia page for grayscale [@wiki_grayscale]. The `apply_image_filter()` function exposed below summarises the necessary steps to diff --git a/Chapters/14-threads.qmd b/Chapters/14-threads.qmd index addac8e4..d6876769 100644 --- a/Chapters/14-threads.qmd +++ b/Chapters/14-threads.qmd @@ -54,13 +54,13 @@ with the other tab where Google Docs is running. Without threads, the other alternative would be to run each tab as a completely separate process in your computer. But that would be a bad choice because just a few tabs would already consume -too much power and resources from your computer. In other words, it is very expensive to create a completely new process, +too much power and resources from your computer. In other words, it's very expensive to create a completely new process, compared to creating a new thread of execution. Also, the chances of you experiencing lag and overhead while using the browser would be significant. Threads are faster to create, and they also consume much, much less resources from the computer, especially because they share some resources with the main process. -Therefore, it is the use of threads in modern web browsers that allow you to hear the podcast +Therefore, it's the use of threads in modern web browsers that allow you to hear the podcast at the same time while you are writing something on Google Docs. Without threads, a web browser would probably be limited to just one single tab. @@ -120,7 +120,7 @@ so the waiter spends almost no time worrying about the order, and just move on and tries to get the next order from the clients. Inside the new thread created, the order gets cooked by a chef, and when the -food is ready, it is delivered to the client's table. +food is ready, it's delivered to the client's table. ```{zig} @@ -180,7 +180,7 @@ same memory space on the heap and global data section. In more details, each thread that you create have a separate stack frame reserved just for that thread, which essentially means that each local object that you create inside this thread, is local to that -thread, i.e. the other threads cannot see this local object. Unless this object that you have created +thread, i.e., the other threads cannot see this local object. Unless this object that you have created is an object that lives on the heap. In other words, if the memory associated with this object is on the heap, then, the other threads can potentially access this object. @@ -320,7 +320,7 @@ pub fn main() !void { Because we have joined this new thread inside the `main()` scope, we have a guarantee that this new thread will finish before the end of the execution of `main()`. -Because it is guaranteed that `main()` will wait for the thread to finish its tasks. +Because it's guaranteed that `main()` will wait for the thread to finish its tasks. In the example above, there are no more expressions after the `join()` call. We just have the end of the `main()`'s scope, and, therefore, the execution of our program just ends after the thread finishes its tasks, @@ -336,7 +336,7 @@ The idea behind this example is that the last `join()` call is executed only after the first thread finishes its task (i.e., the first `join()` call), and the two-second delay. If you compile and run this example, you will notice that most messages are quickly printed to `stdout`, -i.e. they appear almost instantly on your screen. +i.e., they appear almost instantly on your screen. However, the last message ("Joining thread 2") takes around 2 seconds to appear on the screen. @@ -532,8 +532,8 @@ try pool.spawn(print_id, .{&id1}); try pool.spawn(print_id, .{&id2}); ``` -This limitation should probably not exist, and, in fact, it is already on the radar of the -Zig team to fix this issue, and it is being tracked on an [open issue](https://github.com/ziglang/zig/issues/18810)[^issue]. +This limitation should probably not exist, and, in fact, it's already on the radar of the +Zig team to fix this issue, and it's being tracked in an [open issue](https://github.com/ziglang/zig/issues/18810)[^issue]. So, if you do need to provide a function that might return an error as the task to be performed by the threads in the thread pool, then, you are either limited to: @@ -555,7 +555,7 @@ and, therefore, major bugs and undefined behaviour that are usually difficult to The main idea behind a mutex is to help us to control the execution of a particular section of the code, and to prevent two or more threads from executing this particular section of the code at the same time. Many programmers like to compare a mutex to a bathroom door (which typically has a lock). -When a thread locks its own mutex object, it is like if the bathroom door was locked. +When a thread locks its own mutex object, it's like if the bathroom door was locked. Therefore, other people (in this case, other threads) who want to use the same bathroom at the same time must be patient and simply wait for the current occupant (or thread) to unlock the door and get out of the bathroom. @@ -624,7 +624,7 @@ suffer from a data race problem. Therefore, programmers sometimes use an atomic to protect themselves from data race problems in their code. When you have an operation that is compiled into just one single assembly instruction, this operation might be atomic, -because it is just one assembly instruction. But this is not guaranteed. This is usually true for old CPU architectures +because it's just one assembly instruction. But this is not guaranteed. This is usually true for old CPU architectures (such as `x86`). But nowadays, most assembly instructions in modern CPU architectures are broken down into multiple micro-tasks, which inherently makes the operation non-atomic, even if it consists of a single assembly instruction. @@ -633,7 +633,7 @@ In this module, you will find a public and generic function called `Value()`. Wi a value that contains some native atomic operations, most notably, a `load()` and a `fetchAdd()` operation. If you have experience with multithreading in C++, you probably have recognized this pattern. So yes, this generic "atomic object" in Zig is essentially identical to the template struct `std::atomic` from the C++ Standard Library. -It's important to emphasize that only primitive data types (i.e. the types presented in @sec-primitive-data-types) +It's important to emphasize that only primitive data types (i.e., the types presented in @sec-primitive-data-types) are supported by these atomic operations in Zig. @@ -819,7 +819,7 @@ pub fn main() !void { ## Read/Write locks -Mutexes are normally used when it is not always safe for two or more threads running the same +Mutexes are normally used when it's not always safe for two or more threads running the same piece of code at the same time. In contrast, read/write locks are normally used in situations where you have a mixture of scenarios, i.e., there are some pieces of the codebase that are safe to run in parallel, and other pieces that are not safe. @@ -840,7 +840,7 @@ You could also say that there are types of operations that are susceptible to ra and there are other types of operations that are not. A read/write lock is a type of lock that acknowledges the existence of this specific scenario, and you can -use this type of lock to control which parts of the codebase are safe to run in parallel and which parts are not. +use this type of lock to control which parts of the codebase are safe to run in parallel and which parts are not. @@ -876,9 +876,9 @@ the execution of this thread is instantly blocked, i.e., paused. This thread wil read lock, and its execution will be unblocked (or unpaused) only after this thread successfully acquires the read lock. If you think deeply about this dynamic between read locks versus write locks, you might notice that a read lock is basically a safety mechanism. -More specifically, it is a way for us to +More specifically, it's a way for us to allow a particular thread to run together with the other threads only when it's safe to. In other words, if there is currently -a thread with a write lock running, then it is very likely not safe for the thread that is trying to acquire the read lock to run now. +a thread with a write lock running, then it's very likely not safe for the thread that is trying to acquire the read lock to run now. As a consequence, the read lock protects this thread from running into dangerous waters, and patiently waits for the "write lock" thread to finishes its tasks before it continues. @@ -1063,7 +1063,7 @@ control over the thread, and its resources are never freed When we think about the `pthreads` C library, there is a possible way to asynchronously kill or cancel a thread, which is by sending a `SIGTERM` signal to the thread through the `pthread_kill()` function. -But canceling a thread like this is bad. It is dangerously bad. As a consequence, the Zig implementation +But canceling a thread like this is bad. It's dangerously bad. As a consequence, the Zig implementation of threads does not have a similar function, or, a similar way to asynchronously cancel or kill a thread. diff --git a/Chapters/14-zig-c-interop.qmd b/Chapters/14-zig-c-interop.qmd index dd184bbc..d38ad83e 100644 --- a/Chapters/14-zig-c-interop.qmd +++ b/Chapters/14-zig-c-interop.qmd @@ -241,9 +241,9 @@ converted into C strings as well, especially because the `zig` compiler does not a specific Zig data type into a string literal at first glance, unless you store this string literal into a Zig object, and explicitly annotate the data type of this object. -Thus, with string literal values, the `zig` compiler have more freedom to infer which is the appropriate data type +Thus, with string literal values, the `zig` compiler has more freedom to infer which is the appropriate data type to be used in each situation. You could say that the string literal value "inherits its data type" depending on the context that -it is used. Most of the times, this data type is going to be the type that we commonly associate with Zig strings (`[]const u8`). +it's used in. Most of the times, this data type is going to be the type that we commonly associate with Zig strings (`[]const u8`). But it might be a different type depending on the situation. When the `zig` compiler detects that you are providing a string literal value as input to some C function, the compiler automatically interprets this string literal as a C string value. @@ -406,14 +406,14 @@ while using the `fopen()` C function. ``` This strategy works because this pointer to the underlying array found in the `ptr` property, -is semantically identical to a C pointer to an array of bytes, i.e. a C object of type `*unsigned char`. +is semantically identical to a C pointer to an array of bytes, i.e., a C object of type `*unsigned char`. This is why this option also solves the problem of converting the Zig string into a C string. Another option is to explicitly convert the Zig string object into a C pointer by using the built-in function `@ptrCast()`. With this function we can convert an object of type `[]const u8` into an object of type `[*c]const u8`. As I described at the previous section, the `[*c]` portion of the type -means that it is a C pointer. This strategy is not-recommended. But it is +means that it's a C pointer. This strategy is not-recommended. But it's useful to demonstrate the use of `@ptrCast()`. You may recall of `@as()` and `@ptrCast()` from @sec-type-cast. Just as a recap, @@ -465,7 +465,7 @@ a new object with type `User`. These steps are reproduced in the code example be Notice that I have used the keyword `undefined` in this example. This allows me to create the `new_user` object without the need to provide an initial value to the object. As consequence, the underlying memory associated with this `new_user` object is uninitialized, -i.e. the memory is currently populated with "garbage" values. +i.e., the memory is currently populated with "garbage" values. Thus, this expression have the exact same effect of the expression `User new_user;` in C, which means "declare a new object named `new_user` of type `User`". diff --git a/Chapters/15-vectors.qmd b/Chapters/15-vectors.qmd index f191ec39..99fb35e0 100644 --- a/Chapters/15-vectors.qmd +++ b/Chapters/15-vectors.qmd @@ -20,7 +20,7 @@ knitr::opts_chunk$set( # Introducing Vectors and SIMD {#sec-vectors-simd} In this chapter, I want to discuss vectors in Zig, which are -related to SIMD operations (i.e. they have no relationship with the `std::vector` class +related to SIMD operations (i.e., they have no relationship with the `std::vector` class from C++). ## What is SIMD? @@ -32,7 +32,7 @@ was only used on "supercomputer models". Most modern CPU models (from AMD, Intel, etc.) these days (either in a desktop or in a notebook model) have support for SIMD operations. So, if you have a very old CPU model installed in your -computer, then, it is possible that you have no support for SIMD operations in your computer. +computer, then, it's possible that you have no support for SIMD operations in your computer. Why have people started using SIMD in their software? The answer is performance. But what does SIMD precisely do to achieve better performance? Well, in essence, SIMD operations are a different @@ -156,7 +156,7 @@ try stdout.print("{any}\n", .{v1}); As I described in @sec-what-vectors, each vector object is usually a small block of 128, 256 or 512 bits. This means that a vector object is usually small in size, and when you try to go in the opposite direction, -by creating a vector object that is very big in size (i.e. sizes that are close to $2^{20}$), +by creating a vector object that is very big in size (i.e., sizes that are close to $2^{20}$), you usually end up with crashes and loud errors from the compiler. For example, if you try to compile the program below, you will likely face segmentation faults, or LLVM errors during diff --git a/README.md b/README.md index 567e904d..b8eb409c 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ If you do have a Revolut account, you can scan the following QR code: ## About this book -This is an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/), +This is an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/), which is a new general purpose, and low-level programming language for building optimal and robust software. Official repository of the book: . diff --git a/index.qmd b/index.qmd index f7e81492..a63df77b 100644 --- a/index.qmd +++ b/index.qmd @@ -70,7 +70,7 @@ If you do have a Revolut account, you can scan the following QR code: ## About this book {.unnumbered} -This an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/), +This an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/), which is a new general purpose, and low-level programming language for building optimal and robust software. Official repository of the book: . @@ -184,5 +184,3 @@ for (i in seq_len(n)) { } cat(paste(vec, collapse = ", "), sep = "\n") ``` - - diff --git a/zig_engine.R b/zig_engine.R index 9471c870..1f76d880 100644 --- a/zig_engine.R +++ b/zig_engine.R @@ -236,7 +236,7 @@ get_build_type <- function(options) { #' @param options The list of code block options. #' #' @return The knitr engine output, which contains the output of the Zig code -#' (i.e. the output of the executable compiled from this Zig code). +#' (i.e., the output of the executable compiled from this Zig code). zig_engine <- function(options) { code <- str_flatten(options$code, "\n") if (!options$eval) { @@ -297,7 +297,7 @@ write_zig <- function(zig_code) { #' @param options The list of code block options. #' #' @return The knitr engine output, which contains the output of the Zig code -#' (i.e. the output of the executable compiled from this Zig code). +#' (i.e., the output of the executable compiled from this Zig code). zig_run <- function(zig_code, options) { if (get_auto_main(options)) { zig_code <- generate_main(zig_code) @@ -348,7 +348,7 @@ zig_build_lib <- function(zig_code, options) { #' @param options The list of code block options. #' #' @return The knitr engine output, which contains the output of the Zig code -#' (i.e. the output of the executable compiled from this Zig code). +#' (i.e., the output of the executable compiled from this Zig code). zig_test <- function(zig_code, options) { file_path <- write_zig(zig_code) output <- zig_compile_file(file_path, "test") @@ -361,7 +361,7 @@ zig_test <- function(zig_code, options) { #' Check syntax of Zig code with ast-check. #' #' This function is normally used only on code blocks that are not evaluated -#' (i.e. `eval: false`). This function receives some Zig source code as input, +#' (i.e., `eval: false`). This function receives some Zig source code as input, #' and then, it writes this source code to a Zig file (`*.zig`), then, it checks #' if the syntax of the source code in this file is correct, by using the #' `zig ast-check` command @@ -370,7 +370,7 @@ zig_test <- function(zig_code, options) { #' @param options The list of code block options. #' #' @return The knitr engine output, which contains the output of the Zig code -#' (i.e. the output of the executable compiled from this Zig code). +#' (i.e., the output of the executable compiled from this Zig code). zig_ast_check <- function(zig_code, options) { if (get_auto_main(options)) { zig_code <- generate_main(zig_code) From e14bced2ecb27765a6fca0ca1c44ecdc9b0584df Mon Sep 17 00:00:00 2001 From: Pedro Faria <69123925+pedropark99@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:10:53 -0300 Subject: [PATCH 106/151] Update Chapters/03-structs.qmd --- Chapters/03-structs.qmd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Chapters/03-structs.qmd b/Chapters/03-structs.qmd index 999845d4..59280306 100644 --- a/Chapters/03-structs.qmd +++ b/Chapters/03-structs.qmd @@ -1212,7 +1212,8 @@ test { ``` This is the general way to perform type casting in Zig. But remember, `@as()` works only when casting -is unambiguous and safe—there are situations where these assumptions do not hold. For example, +is unambiguous and safe. There are many situations where these assumptions do not hold. For example, + when casting an integer value into a float value, or vice-versa, it's not clear to the compiler how to perform this conversion safely. From 754af9002fbd78e832bd556077e58537ce655884 Mon Sep 17 00:00:00 2001 From: Pedro Faria <69123925+pedropark99@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:11:02 -0300 Subject: [PATCH 107/151] Update Chapters/01-base64.qmd --- Chapters/01-base64.qmd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Chapters/01-base64.qmd b/Chapters/01-base64.qmd index 7a831bb7..caca28bd 100644 --- a/Chapters/01-base64.qmd +++ b/Chapters/01-base64.qmd @@ -168,7 +168,8 @@ Taking the string "Hi" as an example, we have 2 bytes, or, 16 bits in total. So, to complete the window of 24 bits that the base64 algorithm likes to work on. The first thing that the algorithm does, is to check how to divide the input bytes into groups of 6 bits. -If the algorithm notices that there is a group of 6 bits that have some bits in it, but, at the same time it's +If the algorithm notices that there is a group of 6 bits that it's not complete, meaning that, this group contains $nbits$, where $0 < nbits < 6$, + not full—lacking some bits to fill the 6-bits requirement ($0 < nbits < 6$, being $nbits$ the number of bits), the algorithm simply adds extra zeros in this group to fill the space that it needs. That is why in @fig-base64-algo1, in the third group after the 6-bit transformation, From 2299abf8fad3777e91bcf763acd67ca84df69f26 Mon Sep 17 00:00:00 2001 From: Pedro Faria <69123925+pedropark99@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:11:12 -0300 Subject: [PATCH 108/151] Update Chapters/01-base64.qmd --- Chapters/01-base64.qmd | 1 - 1 file changed, 1 deletion(-) diff --git a/Chapters/01-base64.qmd b/Chapters/01-base64.qmd index caca28bd..d2c4f28e 100644 --- a/Chapters/01-base64.qmd +++ b/Chapters/01-base64.qmd @@ -170,7 +170,6 @@ the algorithm does, is to check how to divide the input bytes into groups of 6 b If the algorithm notices that there is a group of 6 bits that it's not complete, meaning that, this group contains $nbits$, where $0 < nbits < 6$, -not full—lacking some bits to fill the 6-bits requirement ($0 < nbits < 6$, being $nbits$ the number of bits), the algorithm simply adds extra zeros in this group to fill the space that it needs. That is why in @fig-base64-algo1, in the third group after the 6-bit transformation, 2 extra zeros were added to fill the gap. From 267b8f6700f2c0c713057790d7de3e2ccb289b64 Mon Sep 17 00:00:00 2001 From: Pedro Faria <69123925+pedropark99@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:11:20 -0300 Subject: [PATCH 109/151] Update Chapters/01-zig-weird.qmd --- Chapters/01-zig-weird.qmd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Chapters/01-zig-weird.qmd b/Chapters/01-zig-weird.qmd index a05d7747..27370753 100644 --- a/Chapters/01-zig-weird.qmd +++ b/Chapters/01-zig-weird.qmd @@ -52,7 +52,8 @@ with tons of features, and also, there are lots of different "flavors of C++". T are what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction. Zig is a very simple language, more closely related to other simple languages such as C and Go. -The phrase above is still important for C programmers too. Because, even if C is a simple +The phrase above is still important for C programmers too. Because, even C being a simple + language, it's still hard sometimes to read and understand C code. For example, pre-processor macros in C are a frequent source of confusion. They sometimes really make it hard to debug C programs. Because macros are essentially a second language embedded in C that obscures From 8210952b84fcc6ace7bcba4f711b2015d6edaf13 Mon Sep 17 00:00:00 2001 From: Pedro Faria <69123925+pedropark99@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:11:27 -0300 Subject: [PATCH 110/151] Update Chapters/01-zig-weird.qmd --- Chapters/01-zig-weird.qmd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Chapters/01-zig-weird.qmd b/Chapters/01-zig-weird.qmd index 27370753..eb58a6ed 100644 --- a/Chapters/01-zig-weird.qmd +++ b/Chapters/01-zig-weird.qmd @@ -55,7 +55,8 @@ Zig is a very simple language, more closely related to other simple languages su The phrase above is still important for C programmers too. Because, even C being a simple language, it's still hard sometimes to read and understand C code. For example, pre-processor macros in -C are a frequent source of confusion. They sometimes really make it hard to debug +C are a frequent source of confusion. Sometimes, they really make it hard to debug + C programs. Because macros are essentially a second language embedded in C that obscures your C code. With macros, you are no longer 100% sure about which pieces of the code are being sent to the compiler, i.e. From 9e918261a26ae0cea9abb454266dd9e12dd890a6 Mon Sep 17 00:00:00 2001 From: Pedro Faria <69123925+pedropark99@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:11:35 -0300 Subject: [PATCH 111/151] Update Chapters/01-zig-weird.qmd --- Chapters/01-zig-weird.qmd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Chapters/01-zig-weird.qmd b/Chapters/01-zig-weird.qmd index eb58a6ed..4c9d4f68 100644 --- a/Chapters/01-zig-weird.qmd +++ b/Chapters/01-zig-weird.qmd @@ -450,7 +450,8 @@ Hello ``` You can read more details about this Windows-specific limitation in a couple of -GitHub issues opened the official Zig repository. More specifically, the issues +GitHub issues opened at the official Zig repository. More specifically, the issues + 17186 [^cissue1] and 19864 [^cissue2]. [^cissue1]: From 00a184129e336f1f30c7ffa604167e7bcada729d Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Thu, 6 Mar 2025 14:41:50 -0300 Subject: [PATCH 112/151] Add runtime length example --- ZigExamples/zig-basics/runtime-slices-length.zig | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 ZigExamples/zig-basics/runtime-slices-length.zig diff --git a/ZigExamples/zig-basics/runtime-slices-length.zig b/ZigExamples/zig-basics/runtime-slices-length.zig new file mode 100644 index 00000000..8d0147de --- /dev/null +++ b/ZigExamples/zig-basics/runtime-slices-length.zig @@ -0,0 +1,13 @@ +const std = @import("std"); +const builtin = @import("builtin"); + +pub fn main() !void { + comptime var n: usize = 0; + if (builtin.target.os.tag == .windows) { + n = 10; + } else { + n = 12; + } + const buffer: [n]u8 = undefined; + _ = buffer; +} From c2d31ccbf4587f2c17b37d8e9d4390108992f544 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Thu, 6 Mar 2025 17:50:49 -0300 Subject: [PATCH 113/151] Recompile book with changes --- .../01-base64/execute-results/html.json | 8 +- .../01-memory/execute-results/html.json | 8 +- .../01-zig-weird/execute-results/html.json | 8 +- .../02-debugging/execute-results/html.json | 8 +- .../03-structs/execute-results/html.json | 8 +- .../03-unittests/execute-results/html.json | 8 +- .../04-http-server/execute-results/html.json | 8 +- .../05-pointers/execute-results/html.json | 8 +- .../07-build-system/execute-results/html.json | 8 +- .../execute-results/html.json | 8 +- .../execute-results/html.json | 8 +- .../execute-results/html.json | 8 +- .../12-file-op/execute-results/html.json | 8 +- .../13-image-filter/execute-results/html.json | 8 +- .../14-threads/execute-results/html.json | 8 +- .../execute-results/html.json | 8 +- .../15-vectors/execute-results/html.json | 8 +- _freeze/index/execute-results/html.json | 4 +- contributors.txt | 2 + docs/Chapters/01-base64.html | 51 ++--- docs/Chapters/01-memory.html | 40 ++-- docs/Chapters/01-zig-weird.html | 109 +++++----- docs/Chapters/02-debugging.html | 18 +- docs/Chapters/03-structs.html | 47 ++--- docs/Chapters/03-unittests.html | 18 +- docs/Chapters/04-http-server.html | 46 ++--- docs/Chapters/05-pointers.html | 20 +- docs/Chapters/07-build-system.html | 46 ++--- docs/Chapters/09-data-structures.html | 68 +++---- docs/Chapters/09-error-handling.html | 44 ++--- docs/Chapters/10-stack-project.html | 58 +++--- docs/Chapters/12-file-op.html | 64 +++--- docs/Chapters/13-image-filter.html | 28 +-- docs/Chapters/14-threads.html | 158 +++++++-------- docs/Chapters/14-zig-c-interop.html | 32 +-- docs/Chapters/15-vectors.html | 16 +- docs/index.html | 8 +- docs/search.json | 186 +++++++++--------- 38 files changed, 620 insertions(+), 579 deletions(-) diff --git a/_freeze/Chapters/01-base64/execute-results/html.json b/_freeze/Chapters/01-base64/execute-results/html.json index 7a805424..78be8b28 100644 --- a/_freeze/Chapters/01-base64/execute-results/html.json +++ b/_freeze/Chapters/01-base64/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "f1304b563ed8036a5bbeaa9b658cfdf0", + "hash": "d5c0ae1b8bb17e483184003ae042e212", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 1 - Building a base64 encoder/decoder {#sec-base64}\n\nAs our first small project, I want to implement a base64 encoder/decoder with you.\nBase64 is an encoding system which translates binary data to text.\nA big chunk of the web uses base64 to deliver binary data to systems\nthat can only read text data.\n\nThe most common example of a modern use case for base64 is essentially any email system,\nlike GMail, Outlook, etc. Because email systems normally use\nthe Simple Mail Transfer Protocol (SMTP), which is a web protocol\nthat supports only text data. So, if you need, for any reason, to\nsend a binary file (like for example, a PDF, or an Excel file) as\nan attachment in your email, these binary files are normally\nconverted to base64, before they are included in the SMTP message.\nSo, the base64 encoding is largely used in these email systems to include\nbinary data into the SMTP message.\n\n\n\n\n\n\n## How the base64 algorithm work?\n\nBut how exactly does the algorithm behind the base64 encoding work? Let's discuss that. First, I will\nexplain the base64 scale, which is the 64-character scale that is the basis for\nthe base64 encoding system.\n\nAfter that, I explain the algorithm behind a base64 encoder, which is the part of the algorithm that is responsible for encoding messages\ninto the base64 encoding system. Then, after that, I explain the algorithm behind a base64 decoder, which is\nthe part of the algorithm that is responsible for translating base64 messages back into their original meaning.\n\nIf you are unsure about the differences between an \"encoder\" and a \"decoder\",\ntake a look at @sec-encode-vs-decode.\n\n\n### The base64 scale {#sec-base64-scale}\n\nThe base64 encoding system is based on a scale that goes from 0 to 63 (hence the name).\nEach index in this scale is represented by a character (it is a scale of 64 characters).\nSo, in order to convert some binary data, to the base64 encoding, we need to convert each binary number to the corresponding\ncharacter in this \"scale of 64 characters\".\n\nThe base64 scale starts with all ASCII uppercase letters (A to Z) which represents\nthe first 25 indexes in this scale (0 to 25). After that, we have all ASCII lowercase letters\n(a to z), which represents the range 26 to 51 in the scale. After that, we\nhave the one digit numbers (0 to 9), which represents the indexes from 52 to 61 in the scale.\nFinally, the last two indexes in the scale (62 and 63) are represented by the characters `+` and `/`,\nrespectively.\n\nThese are the 64 characters that compose the base64 scale. The equal sign character (`=`) is not part of the scale itself,\nbut it is a special character in the base64 encoding system. This character is used solely as a suffix, to mark the end of the character sequence,\nor, to mark the end of meaningful characters in the sequence.\n\nThe bullet points below summarises the base64 scale:\n\n- range 0 to 25 is represented by: ASCII uppercase letters `-> [A-Z]`;\n- range 26 to 51 is represented by: ASCII lowercase letters `-> [a-z]`;\n- range 52 to 61 is represented by: one digit numbers `-> [0-9]`;\n- index 62 and 63 are represented by the characters `+` and `/`, respectively;\n- the character `=` represents the end of meaningful characters in the sequence;\n\n\n\n\n### Creating the scale as a lookup table {#sec-base64-table}\n\nThe best way to represent this scale in code, is to represent it as a *lookup table*.\nLookup tables are a classic strategy in computer science to speed up calculations. The basic idea\nis to replace a runtime calculation (which can take a long time to be done) with a basic array indexing\noperation.\n\nInstead of calculating the results everytime you need them, you calculate all possible results at once, and then, you store them in an array\n(which behaves lake a \"table\"). Then, every time you need to use one of the characters in the base64 scale, instead of\nusing many resources to calculate the exact character to be used, you simply retrieve this character\nfrom the array where you stored all the possible characters in the base64 scale.\nWe retrieve the character that we need directly from memory.\n\nWe can start building a Zig struct to store our base64 decoder/encoder logic.\nWe start with the `Base64` struct below. For now, we only have one single data member in this\nstruct, i.e. the member `_table`, which represents our lookup table. We also have an `init()` method,\nto create a new instance of a `Base64` object, and, a `_char_at()` method, which is a\n\"get character at index $x$\" type of function.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Base64 = struct {\n _table: *const [64]u8,\n\n pub fn init() Base64 {\n const upper = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n const lower = \"abcdefghijklmnopqrstuvwxyz\";\n const numbers_symb = \"0123456789+/\";\n return Base64{\n ._table = upper ++ lower ++ numbers_symb,\n };\n }\n\n pub fn _char_at(self: Base64, index: usize) u8 {\n return self._table[index];\n }\n};\n```\n:::\n\n\n\n\n\nIn other words, the `_char_at()` method is responsible for getting the character in the lookup\ntable (i.e. the `_table` struct data member) that corresponds to a particular index in the\n\"base64 scale\". So, in the example below, we know that the character that corresponds to the\nindex 28 in the \"base64 scale\" is the character \"c\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst base64 = Base64.init();\ntry stdout.print(\n \"Character at index 28: {c}\\n\",\n .{base64._char_at(28)}\n);\n```\n:::\n\n\n\n\n```\nCharacter at index 28: c\n```\n\n\n\n### A base64 encoder {#sec-base64-encoder-algo}\n\nThe algorithm behind a base64 encoder usually works on a window of 3 bytes. Because each byte has\n8 bits, so, 3 bytes forms a set of $8 \\times 3 = 24$ bits. This is desirable for the base64 algorithm, because\n24 bits is divisible by 6, which forms $24 / 6 = 4$ groups of 6 bits each.\n\nTherefore, the base64 algorithm works by converting 3 bytes at a time\ninto 4 characters from the base64 scale. It keeps iterating through the input string,\n3 bytes at a time, and converting them into the base64 scale, producing 4 characters\nper iteration. It keeps iterating, and producing these \"new characters\"\nuntil it hits the end of the input string.\n\nNow, you may think, what if you have a particular string that have a number of bytes\nthat is not divisible by 3? What happens? For example, if you have a string\nthat contains only two characters/bytes, such as \"Hi\". How the\nalgorithm would behave in such situation? You find the answer at @fig-base64-algo1.\nYou can see at @fig-base64-algo1 that the string \"Hi\", when converted to base64,\nbecomes the string \"SGk=\":\n\n![The logic behind a base64 encoder](./../Figures/base64-encoder-flow.png){#fig-base64-algo1}\n\nTaking the string \"Hi\" as an example, we have 2 bytes, or, 16 bits in total. So, we lack a full byte (8 bits)\nto complete the window of 24 bits that the base64 algorithm likes to work on. The first thing that\nthe algorithm does, is to check how to divide the input bytes into groups of 6 bits.\n\nIf the algorithm notices that there is a group of 6 bits that, have some bits in it, but, at the same time, it is not full\n(in other words, $0 < nbits < 6$, being $nbits$ the number of bits), meaning that, it lacks\nsome bits to fill the 6-bits requirement, the algorithm simply add extra zeros in this group\nto fill the space that it needs. That is why at @fig-base64-algo1, on the third group after the 6-bit transformation,\n2 extra zeros were added to fill the gap in this group.\n\nWhen we have a 6-bit group that is not completely full, like the third group, extra zeros\nare added to fill the gap. But what about when an entire 6-bit group is empty, or, it\nsimply doesn't exist? This is the case of the fourth 6-bit group exposed at\n@fig-base64-algo1.\n\nThis fourth group is necessary, because the algorithm works on 4 groups of 6 bits.\nBut the input string does not have enough bytes to create a fourth 6-bit group.\nEvery time this happens, where an entire group of 6 bits is empty,\nthis group becomes a \"padding group\". Every \"padding group\" is mapped to\nthe character `=` (equal sign), which represents \"null\", or, the end\nof meaningful characters in the sequence. Hence, everytime that the algorithm produces a\n\"padding group\", this group is automatically mapped to `=`.\n\nAs another example, if you give the string \"0\" as input to a base64 encoder, this string is\ntranslated into the base64 sequence \"MA==\".\nThe character \"0\" is, in binary, the sequence `00110000`[^zero-note]. So, with the 6-bit transformation\nexposed at @fig-base64-algo1, this single character would produce these two 6-bit groups: `001100`, `000000`.\nThe remaining two 6-bit groups become \"padding groups\". That is why the last\ntwo characters in the output sequence (MA==) are `==`.\n\n\n[^zero-note]: Notice that, the character \"0\" is different than the actual number 0, which is simply zero in binary.\n\n### A base64 decoder {#sec-base64-decoder-algo}\n\nThe algorithm behind a base64 decoder is essentially the inverse process of a base64 encoder.\nA base64 decoder needs to translate base64 messages back into their original meaning,\ni.e. into the original sequence of binary data.\n\nA base64 decoder usually works on a window of 4 bytes. Because it wants to convert these 4 bytes\nback into the original sequence of 3 bytes, that was converted into 4 groups of 6 bits by the\nbase64 encoder. Remember, in a base64 decoder we are essentially reverting the process made\nby the base64 encoder.\n\nEach byte in the input string (the base64 encoded string) normally contributes to re-create\ntwo different bytes in the output (the original binary data).\nIn other words, each byte that comes out of a base64 decoder is created by transforming merging two different\nbytes in the input together. You can visualize this relationship at @fig-base64-algo2:\n\n![The logic behind a base64 decoder](./../Figures/base64-decoder-flow.png){#fig-base64-algo2}\n\nThe exact transformations, or, the exact steps applied to each byte from the input to transform them\ninto the bytes of the output, are a bit tricky to visualize in a figure like this. Because of that, I have\nsummarized these transformations as \"Some bit shifting and additions ...\" in the figure. These transformations\nwill be described in depth later.\n\nBesides that, if you look again at @fig-base64-algo2, you will notice that the character `=` was completely\nignored by the algorithm. Remember, this is just a special character that marks the end of meaningful characters\nin the base64 sequence. So, every `=` character in a base64 encoded sequence should be ignored by a base64 decoder.\n\n\n## Difference between encode and decode {#sec-encode-vs-decode}\n\nIf you don't have any previous experience with base64, you might not understand the differences\nbetween \"encode\" and \"decode\". Essentially, the terms \"encode\" and \"decode\" here\nhave the exact same meaning as they have in the field of encryption (i.e. they mean the same thing as \"encode\" and \"decode\" in hashing\nalgorithms, like the MD5 algorithm).\n\nThus, \"encode\" means that we want to encode, or, in other words, we want to translate some message into\nthe base64 encoding system. We want to produce the sequence of base64 characters that represent this\noriginal message in the base64 encoding system.\n\nIn contrast, \"decode\" represents the inverse process.\nWe want to decode, or, in other words, translate a base64 message back to its original content.\nSo, in this process we get a sequence of base64 characters as input, and produce as output,\nthe binary data that is represented by this sequence of base64 characters.\n\nAny base64 library is normally composed of these two parts: 1) the encoder, which is a function that encodes\n(i.e. it converts) any sequence of binary data into a sequence of base64 characters; 2) the decoder, which is a function\nthat converts a sequence of base64 characters back into the original sequence of binary data.\n\n\n\n## Calculating the size of the output {#sec-base64-length-out}\n\nOne task that we need to do is to calculate how much space we need to reserve for the\noutput, both of the encoder and decoder. This is simple math, and can be done easily in Zig\nbecause every array has its length (its number of elements) easily accesible by consulting\nthe `.len` property of the array.\n\nFor the encoder, the logic is the following: for each 3 bytes that we find in the input,\n4 new bytes are created in the output. So, we take the number of bytes in the input, divide it\nby 3, use a ceiling function, then, we multiply the result by 4. That way, we get the total\nnumber of bytes that will be produced by the encoder in its output.\n\nThe `_calc_encode_length()` function below encapsulates this logic.\nInside this function, we take the length of the input array,\nwe divide it by 3, and apply a ceil operation over the result by using the\n`divCeil()` function from the Zig Standard Library. Lastly, we multiply\nthe end result by 4 to get the answer we need.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_encode_length(input: []const u8) !usize {\n if (input.len < 3) {\n const n_output: usize = 4;\n return n_output;\n }\n const n_output: usize = try std.math.divCeil(\n usize, input.len, 3\n );\n return n_output * 4;\n}\n```\n:::\n\n\n\n\n\nAlso, you might have notice that, if the input length is less than 3 bytes, then, the output length of the encoder is\nalways 4 bytes. This is the case for every input with less than 3 bytes, because, as I described at @sec-base64-encoder-algo,\nthe algorithm always produces enough \"padding-groups\" in the end result, to complete the 4 bytes window.\n\nNow, for the decoder, we just need to apply the inverse logic: for each 4 bytes in the input, 3 bytes\nwill be produced in the output of the decoder. I mean, this is roughly true, because we also need to\ntake the `=` character into account, which is always ignored by the decoder, as we described at @sec-base64-decoder-algo, and,\nat @fig-base64-algo2. But we can ignore this fact for now, just to keep things simple.\n\nThe function `_calc_decode_length()` exposed below summarizes this logic that we described. It is very similar\nto the function `_calc_encode_length()`. Only the division part is twisted, and also, in the special\ncase where we have less than 4 bytes in the input to work on. Also notice that this time, we apply\na floor operation over the output of the division, by using the `divFloor()`\nfunction (instead of a ceiling operation with `divCeil()`).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_decode_length(input: []const u8) !usize {\n if (input.len < 4) {\n const n_output: usize = 3;\n return n_output;\n }\n const n_output: usize = try std.math.divFloor(\n usize, input.len, 4\n );\n return n_output * 3;\n}\n```\n:::\n\n\n\n\n\n## Building the encoder logic {#sec-encoder-logic}\n\nIn this section, we can start building the logic behind the `encode()` function, which\nwill be responsible for encoding messages into the base64 encoding system.\nIf you are an anxious person, and you want to see now the full source code of the implementation\nfor this base64 encoder/decoder, you can find it at the `ZigExamples` folder in the official repository of\nthis book[^zig-base64-algo].\n\n[^zig-base64-algo]: .\n\n\n\n### The 6-bit transformation {#sec-6bit-transf}\n\nThe 6-bit transformation presented at @fig-base64-algo1 is the core part of the base64 encoder algorithm.\nBy understanding how this transformation is made in code, the rest of the algorithm becomes much simpler\nto comprehend.\n\nIn essence, this 6-bit transformation is made with the help of bitwise operators.\nBitwise operators are essential to any type of low-level operation that is done at the bit-level. For the specific case of the base64 algorithm,\nthe operators *bif shift to the left* (`<<`), *bit shift to the right* (`>>`), and the *bitwise and* (`&`) are used. They\nare the core solution for the 6-bit transformation.\n\nThere are 3 different scenarios that we need to take into account in this transformation. First, is the perfect scenario,\nwhere we have the perfect window of 3 bytes to work on. Second, we have the scenario where we have a window of only\ntwo bytes to work with. And last, we have the scenario where we have a window of one single byte.\n\nIn each of these 3 scenarios, the 6-bit transformation works a bit differently. To make the explanation\neasier, I will use the variable `output` to refer to the bytes in the output of the base64 encoder,\nand the variable `input` to refer to the bytes in the input of the encoder.\n\n\nSo, if you have the perfect window of 3 bytes, these are steps for the 6-bit transformation:\n\n1. `output[0]` is produced by moving the bits from `input[0]` two positions to the right.\n1. `output[1]` is produced by summing two components. First, take the last two bits from `input[0]`, then, move them four positions to the left. Second, move the bits from `input[1]` four positions to the right. Sum these two components.\n1. `output[2]` is produced by summing two components. First, take the last four bits from `input[1]`, then, move them two positions to the left. Second, move the bits from `input[2]` six positions to the right. Sum these two components.\n1. `output[3]` is produced by taking the last six bits from `input[2]`.\n\n\nThis is the perfect scenario, where we have a full window of 3 bytes to work on.\nJust to make things as clear as possible, the @fig-encoder-bitshift demonstrates visually how\nthe step 2 mentioned above works. So the 2nd byte in the `output` of the encoder, is made by taking the 1st byte (dark purple)\nand the 2nd byte (orange) from the input. You can see that, at the end of the process, we get a new\nbyte that contains the last 2 bits from the 1st byte in the `input`, and the first 4 bits\nfrom the 2nd byte in the `input`.\n\n![How the 2nd byte in the output of the encoder is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input.](../Figures/base64-encoder-bit-shift.png){#fig-encoder-bitshift}\n\nOn the other hand, we must be prepared for the instances where we do not have the perfect window of 3 bytes.\nIf you have a window of 2 bytes, then, the steps 3 and 4, which produces the bytes `output[2]` and `output[3]`, change a little bit,\nand they become:\n\n- `output[2]` is produced by taking the last 4 bits from `input[1]`, then, move them two positions to the left.\n- `output[3]` is the character `'='`.\n\n\nFinally, if you have a window of a single byte, then, the steps 2 to 4, which produces the bytes `output[1]`, `output[2]` and `output[3]` change,\nbecoming:\n\n- `output[1]` is produced by taking the last two bits from `input[0]`, then, move them four positions to the left.\n- `output[2]` and `output[3]` are the character `=`.\n\n\nIf these bullet points were a bit confusing for you, you may find the @tbl-transf-6bit more intuitive.\nThis table unifies all this logic into a simple table. Notice that\nthis table also provides the exact expression in Zig that creates the corresponding\nbyte in the output.\n\n\n::: {#tbl-transf-6bit}\n\n| Number of bytes in the window | Byte index in the output | In code |\n|-------------------------------|--------------------------|--------------------------------------------|\n| 3 | 0 | input[0] >> 2 |\n| 3 | 1 | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 3 | 2 | ((input[1] & 0x0f) << 2) + (input[2] >> 6) |\n| 3 | 3 | input[2] & 0x3f |\n| 2 | 0 | input[0] >> 2 |\n| 2 | 1 | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 2 | 2 | ((input[1] & 0x0f) << 2) |\n| 2 | 3 | '=' |\n| 1 | 0 | input[0] >> 2 |\n| 1 | 1 | ((input[0] & 0x03) << 4) |\n| 1 | 2 | '=' |\n| 1 | 3 | '=' |\n\n: How the 6-bit transformation translates into code in different window settings.\n\n:::\n\n\n\n\n\n\n### Bit-shifting in Zig\n\nBit-shifting in Zig works similarly to bit-shifting in C.\nAll bitwise operators that exist in C are available in Zig.\nHere, in the base64 encoder algorithm, they are essential\nto produce the result we want.\n\nFor those who are not familiar with these operators, they are\noperators that operates at the bit-level of your values.\nThis means that these operators takes the bits that form the value\nyou have, and change them in some way. This ultimately also changes\nthe value itself, because the binary representation of this value\nchanges.\n\nWe have already seen at @fig-encoder-bitshift the effect produced by a bit-shift.\nBut let's use the first byte in the output of the base64 encoder as another example of what\nbit-shifting means. This is the easiest byte of the 4 bytes in the output\nto build. Because we only need to move the bits from the first byte in the input two positions to the right,\nwith the *bit shift to the right* (`>>`) operator.\n\nIf we take the string \"Hi\" that we used at @fig-base64-algo1 as an example, the first byte in\nthis string is \"H\", which is the sequence `01001000` in binary.\nIf we move the bits of this byte, two places to the right, we get the sequence `00010010` as result.\nThis binary sequence is the value `18` in decimal, and also, the value `0x12` in hexadecimal.\nNotice that the first 6 bits of \"H\" were moved to the end of the byte.\nWith this operation, we get the first byte of the output.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const input = \"Hi\";\n try stdout.print(\"{d}\\n\", .{input[0] >> 2});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n18\n```\n\n\n:::\n:::\n\n\n\n\nIf you recall @fig-base64-algo1, the first byte present in the output should\nbe equivalent to the 6-bit group `010010`. Although being visually different, the\nsequences `010010` and `00010010` are semantically equal. They mean the same thing.\nThey both represent the number 18 in decimal, and the value `0x12` in hexadecimal.\n\nSo, don't take the \"6-bit group\" factor so seriously. We do not need necessarily to\nget a 6-bit sequence as result. As long as the meaning of the 8-bit sequence we get is the same\nof the 6-bit sequence, we are in the clear.\n\n\n\n### Selecting specific bits with the `&` operator\n\nIf you comeback to @sec-6bit-transf, you will see that, in order to produce\nthe second and third bytes in the output, we need to select specific\nbits from the first and second bytes in the input string. But how\ncan we do that? The answer relies on the *bitwise and* (`&`) operator.\n\nThe @fig-encoder-bitshift already showed you what effect this `&` operator\nproduces in the bits of its operands. But let's make a clear description of it.\n\nIn summary, the `&` operator performs a logical conjunction operation\nbetween the bits of its operands. In more details, the operator `&`\ncompares each bit of the first operand to the corresponding bit of the second operand.\nIf both bits are 1, the corresponding result bit is set to 1.\nOtherwise, the corresponding result bit is set to 0 [@microsoftbitwiseand].\n\nSo, if we apply this operator to the binary sequences `1000100` and `00001101`\nthe result of this operation is the binary sequence `00000100`. Because only\nat the sixth position in both binary sequences we had a 1 value. So any\nposition where we do not have both binary sequences setted to 1, we get\na 0 bit in the resulting binary sequence.\n\nWe lose information about the original bit values\nfrom both sequences in this case. Because we no longer know\nif this 0 bit in the resulting binary sequence was produced by\ncombining 0 with 0, or 1 with 0, or 0 with 1.\n\nAs an example, suppose you have the binary sequence `10010111`, which is the number 151 in decimal. How\ncan we get a new binary sequence which contains only the third and\nfourth bits of this sequence?\n\nWe just need to combine this sequence with `00110000` (is `0x30` in hexadecimal) using the `&` operator.\nNotice that only the third and fourth positions in this binary sequence is setted to 1. As a consequence, only the\nthird and fourth values of both binary sequences are potentially preserved in the output. All the remaining positions\nare setted to zero in the output sequence, which is `00010000` (is the number 16 in decimal).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const bits = 0b10010111;\n try stdout.print(\"{d}\\n\", .{bits & 0b00110000});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n16\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Allocating space for the output\n\nAs I described at @sec-stack, to store an object in the stack,\nthis object needs to have a known and fixed length at compile-time. This is an important\nlimitation for our base64 encoder/decoder case. Because the size of\nthe output (from both the encoder and decoder) depends\ndirectly on the size of the input.\n\nHaving this in mind, we cannot know at compile time which is\nthe size of the output for both the encoder and decoder.\nSo, if we can't know the size of the output at compile time,\nthis means that we cannot store the output for both the encoder\nand decoder in the stack.\n\nConsequently, we need to store this output on the heap,\nand, as I commented at @sec-heap, we can only\nstore objects in the heap by using allocator objects.\nSo, one the arguments to both the `encode()` and `decode()`\nfunctions, needs to be an allocator object, because\nwe know for sure that, at some point inside the body of these\nfunctions, we need to allocate space on the heap to\nstore the output of these functions.\n\nThat is why, both the `encode()` and `decode()` functions that I\npresent in this book, have an argument called `allocator`,\nwhich receives a allocator object as input, identified by\nthe type `std.mem.Allocator` from the Zig Standard Library.\n\n\n\n### Writing the `encode()` function\n\nNow that we have a basic understanding on how the bitwise operators work, and how\nexactly they help us to achieve the result we want to achieve. We can now encapsulate\nall the logic that we have described at @fig-base64-algo1 and @tbl-transf-6bit into a nice\nfunction that we can add to our `Base64` struct definition, that we started at @sec-base64-table.\n\nYou can find the `encode()` function below. Notice that the first argument of this function,\nis the `Base64` struct itself. Therefore, this argument clearly signals\nthat this function is a method from the `Base64` struct.\n\nBecause the `encode()` function itself is fairly long,\nI intentionally omitted the `Base64` struct definition in this source code,\njust for brevity reasons. So, just remember that this function is a public function (or a public method) from the\n`Base64` struct.\n\nFurthermore, this `encode()` function has two other arguments:\n\n1. `input` is the input sequence of characters that you want to encode in base64;\n1. `allocator` is an allocator object to use in the necessary memory allocations.\n\nI described everything you need to know about allocator objects at @sec-allocators.\nSo, if you are not familiar with them, I highly recommend you to comeback to\nthat section, and read it.\nBy looking at the `encode()` function, you will see that we use this\nallocator object to allocate enough memory to store the output of\nthe encoding process.\n\nThe main for loop in the function is responsible for iterating through the entire input string.\nIn every iteration, we use a `count` variable to count how many iterations we had at the\nmoment. When `count` reaches 3, then, we try to encode the 3 characters (or bytes) that we have accumulated\nin the temporary buffer object (`buf`).\n\nAfter encoding these 3 characters and storing the result in the `output` variable, we reset\nthe `count` variable to zero, and start to count again on the next iteration of the loop.\nIf the loop hits the end of the string, and, the `count` variable is less than 3, then, it means that\nthe temporary buffer contains the last 1 or 2 bytes from the input.\nThat is why we have two `if` statements after the for loop. To deal which each possible case.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn encode(self: Base64,\n allocator: std.mem.Allocator,\n input: []const u8) ![]u8 {\n\n if (input.len == 0) {\n return \"\";\n }\n\n const n_out = try _calc_encode_length(input);\n var out = try allocator.alloc(u8, n_out);\n var buf = [3]u8{ 0, 0, 0 };\n var count: u8 = 0;\n var iout: u64 = 0;\n\n for (input, 0..) |_, i| {\n buf[count] = input[i];\n count += 1;\n if (count == 3) {\n out[iout] = self._char_at(buf[0] >> 2);\n out[iout + 1] = self._char_at(\n ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n );\n out[iout + 2] = self._char_at(\n ((buf[1] & 0x0f) << 2) + (buf[2] >> 6)\n );\n out[iout + 3] = self._char_at(buf[2] & 0x3f);\n iout += 4;\n count = 0;\n }\n }\n\n if (count == 1) {\n out[iout] = self._char_at(buf[0] >> 2);\n out[iout + 1] = self._char_at(\n (buf[0] & 0x03) << 4\n );\n out[iout + 2] = '=';\n out[iout + 3] = '=';\n }\n\n if (count == 2) {\n out[iout] = self._char_at(buf[0] >> 2);\n out[iout + 1] = self._char_at(\n ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n );\n out[iout + 2] = self._char_at(\n (buf[1] & 0x0f) << 2\n );\n out[iout + 3] = '=';\n iout += 4;\n }\n\n return out;\n}\n```\n:::\n\n\n\n\n\n\n## Building the decoder logic {#sec-decoder-logic}\n\nNow, we can focus on writing the base64 decoder logic. Remember from @fig-base64-algo2 that,\na base64 decoder does the inverse process of an encoder. So, all we need to do, is to\nwrite a `decode()` function that performs the inverse process that I exposed at @sec-encoder-logic.\n\n\n### Mapping base64 characters to their indexes {#sec-map-base64-index}\n\nOne thing that we need to do, in order to decode a base64-encoded message, is to calculate\nthe index in the base64 scale of every base64 character that we encounter in the decoder input.\n\nIn other words, the decoder receives as input, a sequence of base64 characters. We need\nto translate this sequence of characters into a sequence of indexes. These indexes\nare the index of each character in the base64 scale. This way, we get the value/byte\nthat was calculated in the 6-bit transformation step of the encoder process.\n\nThere are probably better/faster ways to calculate this, especially using a \"divide and conquer\"\ntype of strategy. But for now, I am satisfied with a simple and \"brute force\" type of strategy.\nThe `_char_index()` function below contains this strategy.\n\nWe are essentially looping through the *lookup table* with the base64 scale,\nand comparing the character we got with each character in the base64 scale.\nIf these characters match, then, we return the index of this character in the\nbase64 scale as the result.\n\nNotice that, if the input character is `'='`, the function returns the index 64, which is\n\"out of range\" in the scale. But, as I described at @sec-base64-scale,\nthe character `'='` does not belong to the base64 scale itself.\nIt is a special and meaningless character in base64.\n\nAlso notice that this `_char_index()` function is a method from our `Base64` struct,\nbecause of the `self` argument. Again, I have omitted the `Base64` struct definition in this example\nfor brevity reasons.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn _char_index(self: Base64, char: u8) u8 {\n if (char == '=')\n return 64;\n var index: u8 = 0;\n for (0..63) |i| {\n if (self._char_at(i) == char)\n break;\n index += 1;\n }\n\n return index;\n}\n```\n:::\n\n\n\n\n\n\n### The 6-bit transformation\n\nOnce again, the core part of the algorithm is the 6-bit transformation.\nIf we understand the necessary steps to perform this transformation, the rest\nof the algorithm becomes much easier.\n\nFirst of all, before we actually go to the 6-bit transformation,\nwe need to make sure that we use `_char_index()` to convert the sequence of base64 characters\ninto a sequence of indexes. So the snippet below is important for the job that will be done.\nThe result of `_char_index()` is stored in a temporary buffer, and this temporary buffer\nis what we are going to use in the 6-bit transformation, instead of the actual `input` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (0..input.len) |i| {\n buf[i] = self._char_index(input[i]);\n}\n```\n:::\n\n\n\n\nNow, instead of producing 4 bytes (or 4 characters) as output per each window of 3 characters in the input,\na base64 decoder produces 3 bytes (or 3 characters) as output per each window of 4 characters in the input.\nOnce again, is the inverse process.\n\nSo, the steps to produce the 3 bytes in the output are:\n\n1. `output[0]` is produced by summing two components. First, move the bits from `buf[0]` two positions to the left. Second, move the bits from `buf[1]` 4 positions to the right. Then, sum these two components.\n1. `output[1]` is produced by summing two components. First, move the bits from `buf[1]` four positions to the left. Second, move the bits from `buf[2]` 2 positions to the right. Then, sum these two components.\n1. `output[2]` is produced by summing two components. First, move the bits from `buf[2]` six positions to the left. Then, you sum the result with `buf[3]`.\n\n\nBefore we continue, let's try to visualize how these transformations make the original bytes that we had\nbefore the encoding process. First, think back to the 6-bit transformation performed by the encoder exposed at @sec-encoder-logic.\nThe first byte in the output of the encoder is produced by moving the bits in the first byte of the input two positions to the right.\n\nIf for example the first byte in the input of the encoder was the sequence `ABCDEFGH`, then, the first byte in the output of the encoder would be\n`00ABCDEF` (this sequence would be the first byte in the input of the decoder). Now, if the second byte in the input of the encoder was the sequence\n`IJKLMNOP`, then, the second byte in the encoder output would be `00GHIJKL` (as we demonstrated at @fig-encoder-bitshift).\n\nHence, if the sequences `00ABCDEF` and `00GHIJKL` are the first and second bytes, respectively, in the input of the decoder, the\n@fig-decoder-bitshift demonstrates visually how these two bytes are transformed into the first byte of the output of the decoder.\nNotice that the output byte is the sequence `ABCDEFGH`, which is the original byte from the input of the encoder.\n\n![How the 1st byte in the decoder output is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input](../Figures/base64-decoder-bit-shift.png){#fig-decoder-bitshift}\n\nThe @tbl-6bit-decode presents how the three steps described earlier translate into Zig code:\n\n\n\n::: {#tbl-6bit-decode}\n\n| Byte index in the output | In code |\n|--------------------------|-------------------------------|\n| 0 | (buf[0] << 2) + (buf[1] >> 4) |\n| 1 | (buf[1] << 4) + (buf[2] >> 2) |\n| 2 | (buf[2] << 6) + buf[3] |\n\n: The necessary steps for the 6-transformation in the decode process.\n\n\n:::\n\n\n\n\n\n\n\n### Writing the `decode()` function\n\nThe `decode()` function below contains the entire decoding process.\nWe first calculate the size of the output, with\n`_calc_decode_length()`, then, we allocate enough memory for this output with\nthe allocator object.\n\nThree temporary variables are created: 1) `count`, to hold the window count\nin each iteration of the for loop; 2) `iout`, to hold the current index in the output;\n3) `buf`, which is the temporary buffer that holds the base64 indexes to be\nconverted through the 6-bit transformation.\n\nThen, in each iteration of the for loop we fill the temporary buffer with the current\nwindow of bytes. When `count` hits the number 4, then, we have a full window of\nindexes in `buf` to be converted, and then, we apply the 6-bit transformation\nover the temporary buffer.\n\nNotice that we check if the indexes 2 and 3 in the temporary buffer are the number 64, which, if you recall\nfrom @sec-map-base64-index, is when the `_calc_index()` function receives a `'='` character\nas input. So, if these indexes are equal to the number 64, the `decode()` function knows\nthat it can simply ignore these indexes. They are not converted because, as I described before,\nthe character `'='` has no meaning, despite being the end of meaningful characters in the sequence.\nSo we can safely ignore them when they appear in the sequence.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn decode(self: Base64,\n allocator: std.mem.Allocator,\n input: []const u8) ![]u8 {\n\n if (input.len == 0) {\n return \"\";\n }\n const n_output = try _calc_decode_length(input);\n var output = try allocator.alloc(u8, n_output);\n var count: u8 = 0;\n var iout: u64 = 0;\n var buf = [4]u8{ 0, 0, 0, 0 };\n\n for (0..input.len) |i| {\n buf[count] = self._char_index(input[i]);\n count += 1;\n if (count == 4) {\n output[iout] = (buf[0] << 2) + (buf[1] >> 4);\n if (buf[2] != 64) {\n output[iout + 1] = (buf[1] << 4) + (buf[2] >> 2);\n }\n if (buf[3] != 64) {\n output[iout + 2] = (buf[2] << 6) + buf[3];\n }\n iout += 3;\n count = 0;\n }\n }\n\n return output;\n}\n```\n:::\n\n\n\n\n\n## The end result\n\nNow that we have both `decode()` and `encode()` implemented. We have a fully functioning\nbase64 encoder/decoder implemented in Zig. Here is an usage example of our\n`Base64` struct with the `encode()` and `decode()` methods that we have implemented.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar memory_buffer: [1000]u8 = undefined;\nvar fba = std.heap.FixedBufferAllocator.init(\n &memory_buffer\n);\nconst allocator = fba.allocator();\n\nconst text = \"Testing some more stuff\";\nconst etext = \"VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=\";\nconst base64 = Base64.init();\nconst encoded_text = try base64.encode(\n allocator, text\n);\nconst decoded_text = try base64.decode(\n allocator, etext\n);\ntry stdout.print(\n \"Encoded text: {s}\\n\", .{encoded_text}\n);\ntry stdout.print(\n \"Decoded text: {s}\\n\", .{decoded_text}\n);\n```\n:::\n\n\n\n\n```\nEncoded text: VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=\nDecoded text: Testing some more stuff\n```\n\nYou can also see the full source code at once, by visiting the official repository of this book[^repo].\nMore precisely inside the `ZigExamples` folder[^zig-base64-algo].\n\n[^repo]: \n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 1 - Building a base64 encoder/decoder {#sec-base64}\n\nAs our first small project, I want to implement a base64 encoder/decoder with you.\nBase64 is an encoding system which translates binary data to text.\nA big chunk of the web uses base64 to deliver binary data to systems\nthat can only read text data.\n\nThe most common example of a modern use case for base64 is essentially any email system,\nlike GMail, Outlook, etc. Because email systems normally use\nthe Simple Mail Transfer Protocol (SMTP), which is a web protocol\nthat supports only text data. So, if you need, for any reason, to\nsend a binary file (like for example, a PDF, or an Excel file) as\nan attachment in your email, these binary files are normally\nconverted to base64, before they are included in the SMTP message.\nSo, the base64 encoding is largely used in these email systems to include\nbinary data into the SMTP message.\n\n\n\n\n\n\n## How the base64 algorithm work?\n\nBut how exactly does the algorithm behind the base64 encoding work? Let's discuss that. First, I will\nexplain the base64 scale, which is the 64-character scale that is the basis for\nthe base64 encoding system.\n\nAfter that, I explain the algorithm behind a base64 encoder, which is the part of the algorithm that is responsible for encoding messages\ninto the base64 encoding system. Then, after that, I explain the algorithm behind a base64 decoder, which is\nthe part of the algorithm that is responsible for translating base64 messages back into their original meaning.\n\nIf you are unsure about the differences between an \"encoder\" and a \"decoder\",\ntake a look at @sec-encode-vs-decode.\n\n\n### The base64 scale {#sec-base64-scale}\n\nThe base64 encoding system is based on a scale that goes from 0 to 63 (hence the name).\nEach index in this scale is represented by a character (it's a scale of 64 characters).\nSo, in order to convert some binary data, to the base64 encoding, we need to convert each binary number to the corresponding\ncharacter in this \"scale of 64 characters\".\n\nThe base64 scale starts with all ASCII uppercase letters (A to Z) which represents\nthe first 25 indexes in this scale (0 to 25). After that, we have all ASCII lowercase letters\n(a to z), which represents the range 26 to 51 in the scale. After that, we\nhave the one digit numbers (0 to 9), which represents the indexes from 52 to 61 in the scale.\nFinally, the last two indexes in the scale (62 and 63) are represented by the characters `+` and `/`,\nrespectively.\n\nThese are the 64 characters that compose the base64 scale. The equal sign character (`=`) is not part of the scale itself,\nbut it is a special character in the base64 encoding system. This character is used solely as a suffix, to mark the end of the character sequence,\nor, to mark the end of meaningful characters in the sequence.\n\nThe bullet points below summarises the base64 scale:\n\n- range 0 to 25 is represented by: ASCII uppercase letters `-> [A-Z]`;\n- range 26 to 51 is represented by: ASCII lowercase letters `-> [a-z]`;\n- range 52 to 61 is represented by: one digit numbers `-> [0-9]`;\n- index 62 and 63 are represented by the characters `+` and `/`, respectively;\n- the character `=` represents the end of meaningful characters in the sequence;\n\n\n\n\n### Creating the scale as a lookup table {#sec-base64-table}\n\nThe best way to represent this scale in code, is to represent it as a *lookup table*.\nLookup tables are a classic strategy in computer science to speed up calculations. The basic idea\nis to replace a runtime calculation (which can take a long time to be done) with a basic array indexing\noperation.\n\nInstead of calculating the results everytime you need them, you calculate all possible results at once, and then, you store them in an array\n(which behaves lake a \"table\"). Then, every time you need to use one of the characters in the base64 scale, instead of\nusing many resources to calculate the exact character to be used, you simply retrieve this character\nfrom the array where you stored all the possible characters in the base64 scale.\nWe retrieve the character that we need directly from memory.\n\nWe can start building a Zig struct to store our base64 decoder/encoder logic.\nWe start with the `Base64` struct below. For now, we only have one single data member in this\nstruct, i.e., the member `_table`, which represents our lookup table. We also have an `init()` method,\nto create a new instance of a `Base64` object, and, a `_char_at()` method, which is a\n\"get character at index $x$\" type of function.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Base64 = struct {\n _table: *const [64]u8,\n\n pub fn init() Base64 {\n const upper = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n const lower = \"abcdefghijklmnopqrstuvwxyz\";\n const numbers_symb = \"0123456789+/\";\n return Base64{\n ._table = upper ++ lower ++ numbers_symb,\n };\n }\n\n pub fn _char_at(self: Base64, index: usize) u8 {\n return self._table[index];\n }\n};\n```\n:::\n\n\n\n\n\nIn other words, the `_char_at()` method is responsible for getting the character in the lookup\ntable (i.e., the `_table` struct data member) that corresponds to a particular index in the\n\"base64 scale\". So, in the example below, we know that the character that corresponds to the\nindex 28 in the \"base64 scale\" is the character \"c\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst base64 = Base64.init();\ntry stdout.print(\n \"Character at index 28: {c}\\n\",\n .{base64._char_at(28)}\n);\n```\n:::\n\n\n\n\n```\nCharacter at index 28: c\n```\n\n\n\n### A base64 encoder {#sec-base64-encoder-algo}\n\nThe algorithm behind a base64 encoder usually works on a window of 3 bytes. Because each byte has\n8 bits, so, 3 bytes forms a set of $8 \\times 3 = 24$ bits. This is desirable for the base64 algorithm, because\n24 bits is divisible by 6, which forms $24 / 6 = 4$ groups of 6 bits each.\n\nTherefore, the base64 algorithm works by converting 3 bytes at a time\ninto 4 characters from the base64 scale. It keeps iterating through the input string,\n3 bytes at a time, and converting them into the base64 scale, producing 4 characters\nper iteration. It keeps iterating, and producing these \"new characters\"\nuntil it hits the end of the input string.\n\nNow you may think, what if you have a particular string that has a number of bytes\nthat is not divisible by 3 - what happens? For example, if you have a string\nthat contains only two characters/bytes, such as \"Hi\". How would the algorithm\nbehave in such situation? You find the answer in @fig-base64-algo1.\nYou can see in @fig-base64-algo1 that the string \"Hi\", when converted to base64,\nbecomes the string \"SGk=\":\n\n![The logic behind a base64 encoder](./../Figures/base64-encoder-flow.png){#fig-base64-algo1}\n\nTaking the string \"Hi\" as an example, we have 2 bytes, or, 16 bits in total. So, we lack a full byte (8 bits)\nto complete the window of 24 bits that the base64 algorithm likes to work on. The first thing that\nthe algorithm does, is to check how to divide the input bytes into groups of 6 bits.\n\nIf the algorithm notices that there is a group of 6 bits that it's not complete, meaning that, this group contains $nbits$, where $0 < nbits < 6$,\n\nthe algorithm simply adds extra zeros in this group to fill the space that it needs.\nThat is why in @fig-base64-algo1, in the third group after the 6-bit transformation,\n2 extra zeros were added to fill the gap.\n\nWhen we have a 6-bit group that is not completely full, like the third group, extra zeros\nare added to fill the gap. But what about when an entire 6-bit group is empty, or, it\nsimply doesn't exist? This is the case of the fourth 6-bit group exposed at\n@fig-base64-algo1.\n\nThis fourth group is necessary, because the algorithm works on 4 groups of 6 bits.\nBut the input string does not have enough bytes to create a fourth 6-bit group.\nEvery time this happens, where an entire group of 6 bits is empty,\nthis group becomes a \"padding group\". Every \"padding group\" is mapped to\nthe character `=` (equal sign), which represents \"null\", or, the end\nof meaningful characters in the sequence. Hence, everytime that the algorithm produces a\n\"padding group\", this group is automatically mapped to `=`.\n\nAs another example, if you give the string \"0\" as input to a base64 encoder, this string is\ntranslated into the base64 sequence \"MA==\".\nThe character \"0\" is, in binary, the sequence `00110000`[^zero-note]. So, with the 6-bit transformation\nexposed in @fig-base64-algo1, this single character would produce these two 6-bit groups: `001100`, `000000`.\nThe remaining two 6-bit groups become \"padding groups\". That is why the last\ntwo characters in the output sequence (MA==) are `==`.\n\n\n[^zero-note]: Notice that, the character \"0\" is different than the actual number 0, which is simply zero in binary.\n\n### A base64 decoder {#sec-base64-decoder-algo}\n\nThe algorithm behind a base64 decoder is essentially the inverse process of a base64 encoder.\nA base64 decoder needs to translate base64 messages back into their original meaning,\ni.e., into the original sequence of binary data.\n\nA base64 decoder usually works on a window of 4 bytes. Because it wants to convert these 4 bytes\nback into the original sequence of 3 bytes, that was converted into 4 groups of 6 bits by the\nbase64 encoder. Remember, in a base64 decoder we are essentially reverting the process made\nby the base64 encoder.\n\nEach byte in the input string (the base64 encoded string) normally contributes to re-create\ntwo different bytes in the output (the original binary data).\nIn other words, each byte that comes out of a base64 decoder is created by transforming merging two different\nbytes in the input together. You can visualize this relationship in @fig-base64-algo2:\n\n![The logic behind a base64 decoder](./../Figures/base64-decoder-flow.png){#fig-base64-algo2}\n\nThe exact transformations, or, the exact steps applied to each byte from the input to transform them\ninto the bytes of the output, are a bit tricky to visualize in a figure like this. Because of that, I have\nsummarized these transformations as \"Some bit shifting and additions ...\" in the figure. These transformations\nwill be described in depth later.\n\nBesides that, if you look again in @fig-base64-algo2, you will notice that the character `=` was completely\nignored by the algorithm. Remember, this is just a special character that marks the end of meaningful characters\nin the base64 sequence. So, every `=` character in a base64 encoded sequence should be ignored by a base64 decoder.\n\n\n## Difference between encode and decode {#sec-encode-vs-decode}\n\nIf you don't have any previous experience with base64, you might not understand the differences\nbetween \"encode\" and \"decode\". Essentially, the terms \"encode\" and \"decode\" here\nhave the exact same meaning as they have in the field of encryption (i.e., they mean the same thing as \"encode\" and \"decode\" in hashing\nalgorithms, like the MD5 algorithm).\n\nThus, \"encode\" means that we want to encode, or, in other words, we want to translate some message into\nthe base64 encoding system. We want to produce the sequence of base64 characters that represent this\noriginal message in the base64 encoding system.\n\nIn contrast, \"decode\" represents the inverse process.\nWe want to decode, or, in other words, translate a base64 message back to its original content.\nSo, in this process we get a sequence of base64 characters as input, and produce as output,\nthe binary data that is represented by this sequence of base64 characters.\n\nAny base64 library is normally composed of these two parts: 1) the encoder, which is a function that encodes\n(i.e., it converts) any sequence of binary data into a sequence of base64 characters; 2) the decoder, which is a function\nthat converts a sequence of base64 characters back into the original sequence of binary data.\n\n\n\n## Calculating the size of the output {#sec-base64-length-out}\n\nOne task that we need to do is to calculate how much space we need to reserve for the\noutput, both of the encoder and decoder. This is simple math, and can be done easily in Zig\nbecause every array has its length (its number of elements) easily accesible by consulting\nthe `.len` property of the array.\n\nFor the encoder, the logic is the following: for each 3 bytes that we find in the input,\n4 new bytes are created in the output. So, we take the number of bytes in the input, divide it\nby 3, use a ceiling function, then, we multiply the result by 4. That way, we get the total\nnumber of bytes that will be produced by the encoder in its output.\n\nThe `_calc_encode_length()` function below encapsulates this logic.\nInside this function, we take the length of the input array,\nwe divide it by 3, and apply a ceil operation over the result by using the\n`divCeil()` function from the Zig Standard Library. Lastly, we multiply\nthe end result by 4 to get the answer we need.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_encode_length(input: []const u8) !usize {\n if (input.len < 3) {\n const n_output: usize = 4;\n return n_output;\n }\n const n_output: usize = try std.math.divCeil(\n usize, input.len, 3\n );\n return n_output * 4;\n}\n```\n:::\n\n\n\n\n\nAlso, you might have notice that, if the input length is less than 3 bytes, then, the output length of the encoder is\nalways 4 bytes. This is the case for every input with less than 3 bytes, because, as I described in @sec-base64-encoder-algo,\nthe algorithm always produces enough \"padding-groups\" in the end result, to complete the 4 bytes window.\n\nNow, for the decoder, we just need to apply the inverse logic: for each 4 bytes in the input, 3 bytes\nwill be produced in the output of the decoder. I mean, this is roughly true, because we also need to\ntake the `=` character into account, which is always ignored by the decoder, as we described in @sec-base64-decoder-algo, and,\nin @fig-base64-algo2. But we can ignore this fact for now, just to keep things simple.\n\nThe function `_calc_decode_length()` exposed below summarizes this logic that we described. It's very similar\nto the function `_calc_encode_length()`. Only the division part is twisted, and also, in the special\ncase where we have less than 4 bytes in the input to work on. Also notice that this time, we apply\na floor operation over the output of the division, by using the `divFloor()`\nfunction (instead of a ceiling operation with `divCeil()`).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_decode_length(input: []const u8) !usize {\n if (input.len < 4) {\n const n_output: usize = 3;\n return n_output;\n }\n const n_output: usize = try std.math.divFloor(\n usize, input.len, 4\n );\n return n_output * 3;\n}\n```\n:::\n\n\n\n\n\n## Building the encoder logic {#sec-encoder-logic}\n\nIn this section, we can start building the logic behind the `encode()` function, which\nwill be responsible for encoding messages into the base64 encoding system.\nIf you are an anxious person, and you want to see now the full source code of the implementation\nfor this base64 encoder/decoder, you can find it at the `ZigExamples` folder in the official repository of\nthis book[^zig-base64-algo].\n\n[^zig-base64-algo]: .\n\n\n\n### The 6-bit transformation {#sec-6bit-transf}\n\nThe 6-bit transformation presented in @fig-base64-algo1 is the core part of the base64 encoder algorithm.\nBy understanding how this transformation is made in code, the rest of the algorithm becomes much simpler\nto comprehend.\n\nIn essence, this 6-bit transformation is made with the help of bitwise operators.\nBitwise operators are essential to any type of low-level operation that is done at the bit-level. For the specific case of the base64 algorithm,\nthe operators *bif shift to the left* (`<<`), *bit shift to the right* (`>>`), and the *bitwise and* (`&`) are used. They\nare the core solution for the 6-bit transformation.\n\nThere are 3 different scenarios that we need to take into account in this transformation. First, is the perfect scenario,\nwhere we have the perfect window of 3 bytes to work on. Second, we have the scenario where we have a window of only\ntwo bytes to work with. And last, we have the scenario where we have a window of one single byte.\n\nIn each of these 3 scenarios, the 6-bit transformation works a bit differently. To make the explanation\neasier, I will use the variable `output` to refer to the bytes in the output of the base64 encoder,\nand the variable `input` to refer to the bytes in the input of the encoder.\n\n\nSo, if you have the perfect window of 3 bytes, these are steps for the 6-bit transformation:\n\n1. `output[0]` is produced by moving the bits from `input[0]` two positions to the right.\n1. `output[1]` is produced by summing two components. First, take the last two bits from `input[0]`, then, move them four positions to the left. Second, move the bits from `input[1]` four positions to the right. Sum these two components.\n1. `output[2]` is produced by summing two components. First, take the last four bits from `input[1]`, then, move them two positions to the left. Second, move the bits from `input[2]` six positions to the right. Sum these two components.\n1. `output[3]` is produced by taking the last six bits from `input[2]`.\n\n\nThis is the perfect scenario, where we have a full window of 3 bytes to work on.\nJust to make things as clear as possible, the @fig-encoder-bitshift demonstrates visually how\nthe step 2 mentioned above works. So the 2nd byte in the `output` of the encoder, is made by taking the 1st byte (dark purple)\nand the 2nd byte (orange) from the input. You can see that, at the end of the process, we get a new\nbyte that contains the last 2 bits from the 1st byte in the `input`, and the first 4 bits\nfrom the 2nd byte in the `input`.\n\n![How the 2nd byte in the output of the encoder is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input.](../Figures/base64-encoder-bit-shift.png){#fig-encoder-bitshift}\n\nOn the other hand, we must be prepared for the instances where we do not have the perfect window of 3 bytes.\nIf you have a window of 2 bytes, then, the steps 3 and 4, which produces the bytes `output[2]` and `output[3]`, change a little bit,\nand they become:\n\n- `output[2]` is produced by taking the last 4 bits from `input[1]`, then, move them two positions to the left.\n- `output[3]` is the character `'='`.\n\n\nFinally, if you have a window of a single byte, then, the steps 2 to 4, which produces the bytes `output[1]`, `output[2]` and `output[3]` change,\nbecoming:\n\n- `output[1]` is produced by taking the last two bits from `input[0]`, then, move them four positions to the left.\n- `output[2]` and `output[3]` are the character `=`.\n\n\nIf these bullet points were a bit confusing for you, you may find the @tbl-transf-6bit more intuitive.\nThis table unifies all this logic into a simple table. Notice that\nthis table also provides the exact expression in Zig that creates the corresponding\nbyte in the output.\n\n\n::: {#tbl-transf-6bit}\n\n| Number of bytes in the window | Byte index in the output | In code |\n|-------------------------------|--------------------------|--------------------------------------------|\n| 3 | 0 | input[0] >> 2 |\n| 3 | 1 | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 3 | 2 | ((input[1] & 0x0f) << 2) + (input[2] >> 6) |\n| 3 | 3 | input[2] & 0x3f |\n| 2 | 0 | input[0] >> 2 |\n| 2 | 1 | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 2 | 2 | ((input[1] & 0x0f) << 2) |\n| 2 | 3 | '=' |\n| 1 | 0 | input[0] >> 2 |\n| 1 | 1 | ((input[0] & 0x03) << 4) |\n| 1 | 2 | '=' |\n| 1 | 3 | '=' |\n\n: How the 6-bit transformation translates into code in different window settings.\n\n:::\n\n\n\n\n\n\n### Bit-shifting in Zig\n\nBit-shifting in Zig works similarly to bit-shifting in C.\nAll bitwise operators that exist in C are available in Zig.\nHere, in the base64 encoder algorithm, they are essential\nto produce the result we want.\n\nFor those who are not familiar with these operators, they are\noperators that operates at the bit-level of your values.\nThis means that these operators takes the bits that form the value\nyou have, and change them in some way. This ultimately also changes\nthe value itself, because the binary representation of this value\nchanges.\n\nWe have already seen in @fig-encoder-bitshift the effect produced by a bit-shift.\nBut let's use the first byte in the output of the base64 encoder as another example of what\nbit-shifting means. This is the easiest byte of the 4 bytes in the output\nto build. Because we only need to move the bits from the first byte in the input two positions to the right,\nwith the *bit shift to the right* (`>>`) operator.\n\nIf we take the string \"Hi\" that we used in @fig-base64-algo1 as an example, the first byte in\nthis string is \"H\", which is the sequence `01001000` in binary.\nIf we move the bits of this byte, two places to the right, we get the sequence `00010010` as result.\nThis binary sequence is the value `18` in decimal, and also, the value `0x12` in hexadecimal.\nNotice that the first 6 bits of \"H\" were moved to the end of the byte.\nWith this operation, we get the first byte of the output.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const input = \"Hi\";\n try stdout.print(\"{d}\\n\", .{input[0] >> 2});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n18\n```\n\n\n:::\n:::\n\n\n\n\nIf you recall @fig-base64-algo1, the first byte present in the output should\nbe equivalent to the 6-bit group `010010`. Although being visually different, the\nsequences `010010` and `00010010` are semantically equal. They mean the same thing.\nThey both represent the number 18 in decimal, and the value `0x12` in hexadecimal.\n\nSo, don't take the \"6-bit group\" factor so seriously. We do not need necessarily to\nget a 6-bit sequence as result. As long as the meaning of the 8-bit sequence we get is the same\nof the 6-bit sequence, we are in the clear.\n\n\n\n### Selecting specific bits with the `&` operator\n\nIf you comeback to @sec-6bit-transf, you will see that, in order to produce\nthe second and third bytes in the output, we need to select specific\nbits from the first and second bytes in the input string. But how\ncan we do that? The answer relies on the *bitwise and* (`&`) operator.\n\nThe @fig-encoder-bitshift already showed you what effect this `&` operator\nproduces in the bits of its operands. But let's make a clear description of it.\n\nIn summary, the `&` operator performs a logical conjunction operation\nbetween the bits of its operands. In more details, the operator `&`\ncompares each bit of the first operand to the corresponding bit of the second operand.\nIf both bits are 1, the corresponding result bit is set to 1.\nOtherwise, the corresponding result bit is set to 0 [@microsoftbitwiseand].\n\nSo, if we apply this operator to the binary sequences `1000100` and `00001101`\nthe result of this operation is the binary sequence `00000100`. Because only\nat the sixth position in both binary sequences we had a 1 value. So any\nposition where we do not have both binary sequences setted to 1, we get\na 0 bit in the resulting binary sequence.\n\nWe lose information about the original bit values\nfrom both sequences in this case. Because we no longer know\nif this 0 bit in the resulting binary sequence was produced by\ncombining 0 with 0, or 1 with 0, or 0 with 1.\n\nAs an example, suppose you have the binary sequence `10010111`, which is the number 151 in decimal. How\ncan we get a new binary sequence which contains only the third and\nfourth bits of this sequence?\n\nWe just need to combine this sequence with `00110000` (is `0x30` in hexadecimal) using the `&` operator.\nNotice that only the third and fourth positions in this binary sequence is setted to 1. As a consequence, only the\nthird and fourth values of both binary sequences are potentially preserved in the output. All the remaining positions\nare setted to zero in the output sequence, which is `00010000` (is the number 16 in decimal).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const bits = 0b10010111;\n try stdout.print(\"{d}\\n\", .{bits & 0b00110000});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n16\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Allocating space for the output\n\nAs I described in @sec-stack, to store an object in the stack,\nthis object needs to have a known and fixed length at compile-time. This is an important\nlimitation for our base64 encoder/decoder case. Because the size of\nthe output (from both the encoder and decoder) depends\ndirectly on the size of the input.\n\nHaving this in mind, we cannot know at compile time which is\nthe size of the output for both the encoder and decoder.\nSo, if we can't know the size of the output at compile time,\nthis means that we cannot store the output for both the encoder\nand decoder in the stack.\n\nConsequently, we need to store this output on the heap,\nand, as I commented in @sec-heap, we can only\nstore objects in the heap by using allocator objects.\nSo, one the arguments to both the `encode()` and `decode()`\nfunctions, needs to be an allocator object, because\nwe know for sure that, at some point inside the body of these\nfunctions, we need to allocate space on the heap to\nstore the output of these functions.\n\nThat is why, both the `encode()` and `decode()` functions that I\npresent in this book, have an argument called `allocator`,\nwhich receives a allocator object as input, identified by\nthe type `std.mem.Allocator` from the Zig Standard Library.\n\n\n\n### Writing the `encode()` function\n\nNow that we have a basic understanding on how the bitwise operators work, and how\nexactly they help us to achieve the result we want to achieve. We can now encapsulate\nall the logic that we have described in @fig-base64-algo1 and @tbl-transf-6bit into a nice\nfunction that we can add to our `Base64` struct definition, that we started in @sec-base64-table.\n\nYou can find the `encode()` function below. Notice that the first argument of this function,\nis the `Base64` struct itself. Therefore, this argument clearly signals\nthat this function is a method from the `Base64` struct.\n\nBecause the `encode()` function itself is fairly long,\nI intentionally omitted the `Base64` struct definition in this source code,\njust for brevity reasons. So, just remember that this function is a public function (or a public method) from the\n`Base64` struct.\n\nFurthermore, this `encode()` function has two other arguments:\n\n1. `input` is the input sequence of characters that you want to encode in base64;\n1. `allocator` is an allocator object to use in the necessary memory allocations.\n\nI described everything you need to know about allocator objects in @sec-allocators.\nSo, if you are not familiar with them, I highly recommend you to comeback to\nthat section, and read it.\nBy looking at the `encode()` function, you will see that we use this\nallocator object to allocate enough memory to store the output of\nthe encoding process.\n\nThe main for loop in the function is responsible for iterating through the entire input string.\nIn every iteration, we use a `count` variable to count how many iterations we had at the\nmoment. When `count` reaches 3, then, we try to encode the 3 characters (or bytes) that we have accumulated\nin the temporary buffer object (`buf`).\n\nAfter encoding these 3 characters and storing the result in the `output` variable, we reset\nthe `count` variable to zero, and start to count again on the next iteration of the loop.\nIf the loop hits the end of the string, and, the `count` variable is less than 3, then, it means that\nthe temporary buffer contains the last 1 or 2 bytes from the input.\nThat is why we have two `if` statements after the for loop. To deal which each possible case.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn encode(self: Base64,\n allocator: std.mem.Allocator,\n input: []const u8) ![]u8 {\n\n if (input.len == 0) {\n return \"\";\n }\n\n const n_out = try _calc_encode_length(input);\n var out = try allocator.alloc(u8, n_out);\n var buf = [3]u8{ 0, 0, 0 };\n var count: u8 = 0;\n var iout: u64 = 0;\n\n for (input, 0..) |_, i| {\n buf[count] = input[i];\n count += 1;\n if (count == 3) {\n out[iout] = self._char_at(buf[0] >> 2);\n out[iout + 1] = self._char_at(\n ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n );\n out[iout + 2] = self._char_at(\n ((buf[1] & 0x0f) << 2) + (buf[2] >> 6)\n );\n out[iout + 3] = self._char_at(buf[2] & 0x3f);\n iout += 4;\n count = 0;\n }\n }\n\n if (count == 1) {\n out[iout] = self._char_at(buf[0] >> 2);\n out[iout + 1] = self._char_at(\n (buf[0] & 0x03) << 4\n );\n out[iout + 2] = '=';\n out[iout + 3] = '=';\n }\n\n if (count == 2) {\n out[iout] = self._char_at(buf[0] >> 2);\n out[iout + 1] = self._char_at(\n ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n );\n out[iout + 2] = self._char_at(\n (buf[1] & 0x0f) << 2\n );\n out[iout + 3] = '=';\n iout += 4;\n }\n\n return out;\n}\n```\n:::\n\n\n\n\n\n\n## Building the decoder logic {#sec-decoder-logic}\n\nNow, we can focus on writing the base64 decoder logic. Remember from @fig-base64-algo2 that,\na base64 decoder does the inverse process of an encoder. So, all we need to do, is to\nwrite a `decode()` function that performs the inverse process that I exposed in @sec-encoder-logic.\n\n\n### Mapping base64 characters to their indexes {#sec-map-base64-index}\n\nOne thing that we need to do, in order to decode a base64-encoded message, is to calculate\nthe index in the base64 scale of every base64 character that we encounter in the decoder input.\n\nIn other words, the decoder receives as input, a sequence of base64 characters. We need\nto translate this sequence of characters into a sequence of indexes. These indexes\nare the index of each character in the base64 scale. This way, we get the value/byte\nthat was calculated in the 6-bit transformation step of the encoder process.\n\nThere are probably better/faster ways to calculate this, especially using a \"divide and conquer\"\ntype of strategy. But for now, I am satisfied with a simple and \"brute force\" type of strategy.\nThe `_char_index()` function below contains this strategy.\n\nWe are essentially looping through the *lookup table* with the base64 scale,\nand comparing the character we got with each character in the base64 scale.\nIf these characters match, then, we return the index of this character in the\nbase64 scale as the result.\n\nNotice that, if the input character is `'='`, the function returns the index 64, which is\n\"out of range\" in the scale. But, as I described in @sec-base64-scale,\nthe character `'='` does not belong to the base64 scale itself.\nIt's a special and meaningless character in base64.\n\nAlso notice that this `_char_index()` function is a method from our `Base64` struct,\nbecause of the `self` argument. Again, I have omitted the `Base64` struct definition in this example\nfor brevity reasons.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn _char_index(self: Base64, char: u8) u8 {\n if (char == '=')\n return 64;\n var index: u8 = 0;\n for (0..63) |i| {\n if (self._char_at(i) == char)\n break;\n index += 1;\n }\n\n return index;\n}\n```\n:::\n\n\n\n\n\n\n### The 6-bit transformation\n\nOnce again, the core part of the algorithm is the 6-bit transformation.\nIf we understand the necessary steps to perform this transformation, the rest\nof the algorithm becomes much easier.\n\nFirst of all, before we actually go to the 6-bit transformation,\nwe need to make sure that we use `_char_index()` to convert the sequence of base64 characters\ninto a sequence of indexes. So the snippet below is important for the job that will be done.\nThe result of `_char_index()` is stored in a temporary buffer, and this temporary buffer\nis what we are going to use in the 6-bit transformation, instead of the actual `input` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (0..input.len) |i| {\n buf[i] = self._char_index(input[i]);\n}\n```\n:::\n\n\n\n\nNow, instead of producing 4 bytes (or 4 characters) as output per each window of 3 characters in the input,\na base64 decoder produces 3 bytes (or 3 characters) as output per each window of 4 characters in the input.\nOnce again, is the inverse process.\n\nSo, the steps to produce the 3 bytes in the output are:\n\n1. `output[0]` is produced by summing two components. First, move the bits from `buf[0]` two positions to the left. Second, move the bits from `buf[1]` 4 positions to the right. Then, sum these two components.\n1. `output[1]` is produced by summing two components. First, move the bits from `buf[1]` four positions to the left. Second, move the bits from `buf[2]` 2 positions to the right. Then, sum these two components.\n1. `output[2]` is produced by summing two components. First, move the bits from `buf[2]` six positions to the left. Then, you sum the result with `buf[3]`.\n\n\nBefore we continue, let's try to visualize how these transformations make the original bytes that we had\nbefore the encoding process. First, think back to the 6-bit transformation performed by the encoder exposed in @sec-encoder-logic.\nThe first byte in the output of the encoder is produced by moving the bits in the first byte of the input two positions to the right.\n\nIf for example the first byte in the input of the encoder was the sequence `ABCDEFGH`, then, the first byte in the output of the encoder would be\n`00ABCDEF` (this sequence would be the first byte in the input of the decoder). Now, if the second byte in the input of the encoder was the sequence\n`IJKLMNOP`, then, the second byte in the encoder output would be `00GHIJKL` (as we demonstrated in @fig-encoder-bitshift).\n\nHence, if the sequences `00ABCDEF` and `00GHIJKL` are the first and second bytes, respectively, in the input of the decoder, the\n@fig-decoder-bitshift demonstrates visually how these two bytes are transformed into the first byte of the output of the decoder.\nNotice that the output byte is the sequence `ABCDEFGH`, which is the original byte from the input of the encoder.\n\n![How the 1st byte in the decoder output is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input](../Figures/base64-decoder-bit-shift.png){#fig-decoder-bitshift}\n\nThe @tbl-6bit-decode presents how the three steps described earlier translate into Zig code:\n\n\n\n::: {#tbl-6bit-decode}\n\n| Byte index in the output | In code |\n|--------------------------|-------------------------------|\n| 0 | (buf[0] << 2) + (buf[1] >> 4) |\n| 1 | (buf[1] << 4) + (buf[2] >> 2) |\n| 2 | (buf[2] << 6) + buf[3] |\n\n: The necessary steps for the 6-transformation in the decode process.\n\n\n:::\n\n\n\n\n\n\n\n### Writing the `decode()` function\n\nThe `decode()` function below contains the entire decoding process.\nWe first calculate the size of the output, with\n`_calc_decode_length()`, then, we allocate enough memory for this output with\nthe allocator object.\n\nThree temporary variables are created: 1) `count`, to hold the window count\nin each iteration of the for loop; 2) `iout`, to hold the current index in the output;\n3) `buf`, which is the temporary buffer that holds the base64 indexes to be\nconverted through the 6-bit transformation.\n\nThen, in each iteration of the for loop we fill the temporary buffer with the current\nwindow of bytes. When `count` hits the number 4, then, we have a full window of\nindexes in `buf` to be converted, and then, we apply the 6-bit transformation\nover the temporary buffer.\n\nNotice that we check if the indexes 2 and 3 in the temporary buffer are the number 64, which, if you recall\nfrom @sec-map-base64-index, is when the `_calc_index()` function receives a `'='` character\nas input. So, if these indexes are equal to the number 64, the `decode()` function knows\nthat it can simply ignore these indexes. They are not converted because, as I described before,\nthe character `'='` has no meaning, despite being the end of meaningful characters in the sequence.\nSo we can safely ignore them when they appear in the sequence.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn decode(self: Base64,\n allocator: std.mem.Allocator,\n input: []const u8) ![]u8 {\n\n if (input.len == 0) {\n return \"\";\n }\n const n_output = try _calc_decode_length(input);\n var output = try allocator.alloc(u8, n_output);\n var count: u8 = 0;\n var iout: u64 = 0;\n var buf = [4]u8{ 0, 0, 0, 0 };\n\n for (0..input.len) |i| {\n buf[count] = self._char_index(input[i]);\n count += 1;\n if (count == 4) {\n output[iout] = (buf[0] << 2) + (buf[1] >> 4);\n if (buf[2] != 64) {\n output[iout + 1] = (buf[1] << 4) + (buf[2] >> 2);\n }\n if (buf[3] != 64) {\n output[iout + 2] = (buf[2] << 6) + buf[3];\n }\n iout += 3;\n count = 0;\n }\n }\n\n return output;\n}\n```\n:::\n\n\n\n\n\n## The end result\n\nNow that we have both `decode()` and `encode()` implemented. We have a fully functioning\nbase64 encoder/decoder implemented in Zig. Here is an usage example of our\n`Base64` struct with the `encode()` and `decode()` methods that we have implemented.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar memory_buffer: [1000]u8 = undefined;\nvar fba = std.heap.FixedBufferAllocator.init(\n &memory_buffer\n);\nconst allocator = fba.allocator();\n\nconst text = \"Testing some more stuff\";\nconst etext = \"VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=\";\nconst base64 = Base64.init();\nconst encoded_text = try base64.encode(\n allocator, text\n);\nconst decoded_text = try base64.decode(\n allocator, etext\n);\ntry stdout.print(\n \"Encoded text: {s}\\n\", .{encoded_text}\n);\ntry stdout.print(\n \"Decoded text: {s}\\n\", .{decoded_text}\n);\n```\n:::\n\n\n\n\n```\nEncoded text: VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=\nDecoded text: Testing some more stuff\n```\n\nYou can also see the full source code at once, by visiting the official repository of this book[^repo].\nMore precisely inside the `ZigExamples` folder[^zig-base64-algo].\n\n[^repo]: \n", + "supporting": [ + "01-base64_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/01-memory/execute-results/html.json b/_freeze/Chapters/01-memory/execute-results/html.json index eec3bc03..269c7d87 100644 --- a/_freeze/Chapters/01-memory/execute-results/html.json +++ b/_freeze/Chapters/01-memory/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "6d9a92b4e90ed5229b91d3e433ba3d4c", + "hash": "55899a376e1db53689b78790e55a518d", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Memory and Allocators\n\n\nIn this chapter, we will talk about memory. How does Zig control memory? What\ncommon tools are used? Are there any important aspects that make memory\ndifferent/special in Zig? You will find the answers here.\n\nComputers fundamentally rely on memory to function. This memory acts as a temporary storage\nspace for the data and values generated during computations. Without memory, the core\nconcepts of \"variables\" and \"objects\" in programming languages would be impossible.\n\n\n\n\n## Memory spaces\n\nEvery object that you create in your Zig source code needs to be stored somewhere,\nin your computer's memory. Depending on where and how you define your object, Zig\nwill use a different \"memory space\", or a different\ntype of memory to store this object.\n\nEach type of memory normally serves for different purposes.\nIn Zig, there are 3 types of memory (or 3 different memory spaces) that we care about. They are:\n\n- Global data register (or the \"global data section\");\n- Stack;\n- Heap;\n\n\n### Compile-time known versus runtime known {#sec-compile-time}\n\nOne strategy that Zig uses to decide where it will store each object that you declare, is by looking\nat the value of this particular object. More specifically, by investigating if this value is\nknown at \"compile-time\" or at \"runtime\".\n\nWhen you write a program in Zig, the values of some of the objects that you write in your program are *known\nat compile time*. Meaning that, when you compile your Zig source code, during the compilation process,\nthe `zig` compiler can figure out the exact value of a particular object\nthat exists in your source code.\nKnowing the length (or the size) of each object is also important. So the length (or the size) of each object that you write in your program is,\nin some cases, *known at compile time*.\n\nThe `zig` compiler cares more about knowing the length (or the size) of a particular object\n, than to know its actual value. But, if the `zig` compiler knows the value of the object, then, it\nautomatically knows the size of this object. Because it can simply calculate the\nsize of the object by looking at the size of the value.\n\nTherefore, the priority for the `zig` compiler is to discover the size of each object in your source code.\nIf the value of the object in question is known at compile-time, then, the `zig` compiler\nautomatically knows the size/length of this object. But if the value of this object is not\nknown at compile-time, then, the size of this object is only known at compile-time if,\nand only if, the type of this object has a known fixed size.\n\nIn order for a type to have a known fixed size, this type must have data members whose size is fixed.\nIf this type includes, for example, a variable sized array in it, then, this type does not have a known\nfixed size. Because this array can have any size at runtime\n(i.e. it can be an array of 2 elements, or 50 elements, or 1 thousand elements, etc.).\n\nFor example, a string object, which internally is an array of constant u8 values (`[]const u8`)\nhas a variable size. It can be a string object with 100 or 500 characters in it. If we do not\nknow at compile-time, which exact string will be stored inside this string object, then, we cannot calculate\nthe size of this string object at compile-time. So, any type, or any struct declaration that you make, that\nincludes a string data member that does not have an explicit fixed size, makes this type, or this\nnew struct that you are declaring, a type that does not have a known fixed size at compile-time.\n\nIn contrast, if the type of this struct that you are declaring, includes a data member that is an array,\nbut this array has a known fixed size, like `[60]u8` (which declares an array of 60 `u8` values), then,\nthis type, or, this struct that you are declaring, becomes a type with a known fixed size at compile-time.\nAnd because of that, in this case, the `zig` compiler does not need to know at compile-time the exact value of\nany object of this type. Since the compiler can find the necessary size to store this object by\nlooking at the size of its type.\n\n\nLet's look at an example. In the source code below, we have two constant objects (`name` and `array`) declared.\nBecause the values of these particular objects are written down, in the source code itself (`\"Pedro\"`\nand the number sequence from 1 to 4), the `zig` compiler can easily discover the values of these constant\nobjects (`name` and `array`) during the compilation process.\nThis is what \"known at compile time\" means. It refers to any object that you have in your Zig source code\nwhose value can be identified at compile time.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn input_length(input: []const u8) usize {\n const n = input.len;\n return n;\n}\n\npub fn main() !void {\n const name = \"Pedro\";\n const array = [_]u8{1, 2, 3, 4};\n _ = name; _ = array;\n}\n```\n:::\n\n\n\n\nThe other side of the spectrum are objects whose values are not known at compile time.\nFunction arguments are a classic example of this. Because the value of each function\nargument depends on the value that you assign to this particular argument,\nwhen you call the function.\n\nFor example, the function `input_length()` contains an argument named `input`, which is an array of constant `u8` integers (`[]const u8`).\nIt is impossible to know the value of this particular argument at compile time. And it also is impossible to know the size/length\nof this particular argument. Because it is an array that do not have a fixed size specified explicitly in the argument type annotation.\n\nSo, we know that this `input` argument will be an array of `u8` integers. But we do not know at compile-time, its value, and neither its size.\nThis information is known only at runtime, which is the period of time when you program is executed.\nAs a consequence, the value of the expression `input.len` is also known only at runtime.\nThis is an intrinsic characteristic of any function. Just remember that the value of function arguments is usually not \"compile-time known\".\n\nHowever, as I mentioned earlier, what really matters to the compiler is to know the size of the object\nat compile-time, and not necessarily its value. So, although we don't know the value of the object `n`, which is the result of the expression\n`input.len`, at compile-time, we do know its size. Because the expression `input.len` always returns a value of type `usize`,\nand the type `usize` has a known fixed size.\n\n\n\n### Global data register\n\nThe global data register is a specific section of the executable of your Zig program, that is responsible\nfor storing any value that is known at compile time.\n\nEvery constant object whose value is known at compile time that you declare in your source code,\nis stored in the global data register. Also, every literal value that you write in your source code,\nsuch as the string `\"this is a string\"`, or the integer `10`, or a boolean value such as `true`,\nis also stored in the global data register.\n\nHonestly, you don't need to care much about this memory space. Because you can't control it,\nyou can't deliberately access it or use it for your own purposes.\nAlso, this memory space does not affect the logic of your program.\nIt simply exists in your program.\n\n\n### Stack vs Heap\n\nIf you are familiar with systems programming, or just low-level programming in general, you\nprobably have heard of the \"duel\" between Stack vs Heap. These are two different types of memory,\nor different memory spaces, which are both available in Zig.\n\nThese two types of memory don't actually duel with\neach other. This is a common mistake that beginners have, when seeing \"x vs y\" styles of\ntabloid headlines. These two types of memory are actually complementary to each other.\nSo, in almost every Zig program that you ever write, you will likely use a combination of both.\nI will describe each memory space in detail over the next sections. But for now, I just want to\nstablish the main difference between these two types of memory.\n\nIn essence, the stack memory is normally used to store values whose length is fixed and known\nat compile time. In contrast, the heap memory is a *dynamic* type of memory space, meaning that, it is\nused to store values whose length might grow during the execution (runtime) of your program [@jenny2022].\n\nLengths that grow during runtime are intrinsically associated with \"runtime known\" type of values.\nIn other words, if you have an object whose length might grow during runtime, then, the length\nof this object becomes not known at compile time. If the length is not known at compile-time,\nthe value of this object also becomes not known at compile-time.\nThese types of objects should be stored in the heap memory space, which is\na dynamic memory space, which can grow or shrink to fit the size of your objects.\n\n\n\n### Stack {#sec-stack}\n\nThe stack is a type of memory that uses the power of the *stack data structure*, hence the name.\nA \"stack\" is a type of *data structure* that uses a \"last in, first out\" (LIFO) mechanism to store the values\nyou give it to. I imagine you are familiar with this data structure.\nBut, if you are not, the [Wikipedia page](https://en.wikipedia.org/wiki/Stack_(abstract_data_type))[^wiki-stack]\n, or, the [Geeks For Geeks page](https://www.geeksforgeeks.org/stack-data-structure/)[^geek-stack] are both\nexcellent and easy resources to fully understand how this data structure works.\n\n[^wiki-stack]: \n[^geek-stack]: \n\nSo, the stack memory space is a type of memory that stores values using a stack data structure.\nIt adds and removes values from the memory by following a \"last in, first out\" (LIFO) principle.\n\nEvery time you make a function call in Zig, an amount of space in the stack is\nreserved for this particular function call [@jenny2022; @zigdocs].\nThe value of each function argument given to the function in this function call is stored in this\nstack space. Also, every local object that you declare inside the function scope is\nusually stored in this same stack space.\n\n\nLooking at the example below, the object `result` is a local object declared inside the scope of the `add()`\nfunction. Because of that, this object is stored inside the stack space reserved for the `add()` function.\nThe `r` object (which is declared outside of the `add()` function scope) is also stored in the stack.\nBut since it is declared in the \"outer\" scope, this object is stored in the\nstack space that belongs to this outer scope.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn add(x: u8, y: u8) u8 {\n const result = x + y;\n return result;\n}\n\npub fn main() !void {\n const r = add(5, 27);\n _ = r;\n}\n```\n:::\n\n\n\n\n\nSo, any object that you declare inside the scope of a function is always stored inside\nthe space that was reserved for that particular function in the stack memory. This\nalso counts for any object declared inside the scope of your `main()` function for example.\nAs you would expect, in this case, they\nare stored inside the stack space reserved for the `main()` function.\n\nOne very important detail about the stack memory is that **it frees itself automatically**.\nThis is very important, remember that. When objects are stored in the stack memory,\nyou don't have the work (or the responsibility) of freeing/destroying these objects.\nBecause they will be automatically destroyed once the stack space is freed at the end of the function scope.\n\nSo, once the function call returns (or ends, if you prefer to call it this way)\nthe space that was reserved in the stack is destroyed, and all of the objects that were in that space goes away with it.\nThis mechanism exists because this space, and the objects within it, are not necessary anymore,\nsince the function \"finished its business\".\nUsing the `add()` function that we exposed above as an example, it means that the object `result` is automatically\ndestroyed once the function returns.\n\n::: {.callout-important}\nLocal objects that are stored in the stack space of a function are automatically\nfreed/destroyed at the end of the function scope.\n:::\n\n\nThis same logic applies to any other special structure in Zig that has its own scope by surrounding\nit with curly braces (`{}`).\nFor loops, while loops, if else statements, etc. For example, if you declare any local\nobject in the scope of a for loop, this local object is accessible only within the scope\nof this particular for loop. Because once the scope of this for loop ends, the space in the stack\nreserved for this for loop is freed.\nThe example below demonstrates this idea.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This does not compile successfully!\nconst a = [_]u8{0, 1, 2, 3, 4};\nfor (0..a.len) |i| {\n const index = i;\n _ = index;\n}\n// Trying to use an object that was\n// declared in the for loop scope,\n// and that does not exist anymore.\nstd.debug.print(\"{d}\\n\", .{index});\n```\n:::\n\n\n\n\n\n\nOne important consequence of this mechanism is that, once the function returns, you can no longer access any memory\naddress that was inside the space in the stack reserved for this particular function. Because this space was\ndestroyed. This means that, if this local object is stored in the stack,\nyou cannot make a function that **returns a pointer to this object**.\n\nThink about that for a second. If all local objects in the stack are destroyed at the end of the function scope, why\nwould you even consider returning a pointer to one of these objects? This pointer is at best,\ninvalid, or, more likely, \"undefined\".\n\nConclusion, it is totally fine to write a function that returns the local object\nitself as result, because then, you return the value of that object as the result.\nBut, if this local object is stored in the stack, you should never write a function\nthat returns a pointer to this local object. Because the memory address pointed by the pointer\nno longer exists.\n\n\nSo, using again the `add()` function as an example, if you rewrite this function so that it\nreturns a pointer to the local object `result`, the `zig` compiler will actually compile\nyour program, with no warnings or errors. At first glance, it looks that this is good code\nthat works as expected. But this is a lie!\n\nIf you try to take a look at the value inside of the `r` object,\nor, if you try to use this `r` object in another expression\nor function call, then, you would have undefined behaviour, and major\nbugs in your program [@zigdocs, see \"Lifetime and Ownership\"[^life] and \"Undefined Behaviour\"[^undef] sections].\n\n[^life]: \n[^undef]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn add(x: u8, y: u8) *const u8 {\n const result = x + y;\n return &result;\n}\n\npub fn main() !void {\n // This code compiles successfully. But it has\n // undefined behaviour. Never do this!!!\n // The `r` object is undefined!\n const r = add(5, 27); _ = r;\n}\n```\n:::\n\n\n\n\nThis \"invalid pointer to stack variable\" problem is well known across many programming language communities.\nIf you try to do the same thing, for example, in a C or C++ program (i.e. returning an address to\na local object stored in the stack), you would also get undefined behaviour\nin the program.\n\n::: {.callout-important}\nIf a local object in your function is stored in the stack, you should never\nreturn a pointer to this local object from the function. Because\nthis pointer will always become undefined after the function returns, since the stack space of the function\nis destroyed at the end of its scope.\n:::\n\nBut what if you really need to use this local object in some way after your function returns?\nHow can you do this? The answer is: \"in the same way you would do if this were a C or C++ program. By returning\nan address to an object stored in the heap\". The heap memory has a much more flexible lifecycle,\nand allows you to get a valid pointer to a local object of a function that already returned\nfrom its scope.\n\n\n### Heap {#sec-heap}\n\nOne important limitation of the stack, is that, only objects whose length/size is known at compile-time can be\nstored in it. In contrast, the heap is a much more dynamic\n(and flexible) type of memory. It is the perfect type of memory to use\nfor objects whose size/length might grow during the execution of your program.\n\nVirtually any application that behaves as a server is a classic use case of the heap.\nA HTTP server, a SSH server, a DNS server, a LSP server, ... any type of server.\nIn summary, a server is a type of application that runs for long periods of time,\nand that serves (or \"deals with\") any incoming request that reaches this particular server.\n\nThe heap is a good choice for this type of system, mainly because the server does not know upfront\nhow many requests it will receive from users, while it is active. It could be a single request,\n5 thousand requests, or even zero requests.\nThe server needs to have the ability to allocate and manage its memory according to how many requests it receives.\n\nAnother key difference between the stack and the heap, is that the heap is a type\nof memory that you, the programmer, have complete control over. This makes the heap a\nmore flexible type of memory, but it also makes it harder to work with. Because you,\nthe programmer, is responsible for managing everything related to it. Including where the memory is allocated,\nhow much memory is allocated, and where this memory is freed.\n\n> Unlike stack memory, heap memory is allocated explicitly by programmers and it won’t be deallocated until it is explicitly freed [@jenny2022].\n\nTo store an object in the heap, you, the programmer, needs to explicitly tells Zig to do so,\nby using an allocator to allocate some space in the heap. At @sec-allocators, I will present how you can use allocators to allocate memory\nin Zig.\n\n::: {.callout-important}\nEvery memory you allocate in the heap needs to be explicitly freed by you, the programmer.\n:::\n\nThe majority of allocators in Zig do allocate memory on the heap. But some exceptions to this rule are\n`ArenaAllocator()` and `FixedBufferAllocator()`. The `ArenaAllocator()` is a special\ntype of allocator that works in conjunction with a second type of allocator.\nOn the other side, the `FixedBufferAllocator()` is an allocator that works based on\nbuffer objects created on the stack. This means that the `FixedBufferAllocator()` makes\nallocations only on the stack.\n\n\n\n\n### Summary\n\nAfter discussing all of these boring details, we can quickly recap what we learned.\nIn summary, the Zig compiler will use the following rules to decide where each\nobject you declare is stored:\n\n1. every literal value (such as `\"this is string\"`, `10`, or `true`) is stored in the global data section.\n1. every constant object (`const`) whose value **is known at compile-time** is also stored in the global data section.\n1. every object (constant or not) whose length/size **is known at compile time** is stored in the stack space for the current scope.\n1. if an object is created with the method `alloc()` or `create()` of an allocator object, this object is stored in the memory space used by this particular allocator object. Most of allocators available in Zig use the heap memory, so, this object is likely stored in the heap (`FixedBufferAllocator()` is an exception to that).\n1. the heap can only be accessed through allocators. If your object was not created through the `alloc()` or `create()` methods of an allocator object, then, it is most certainly not an object stored in the heap.\n\n\n## Stack overflows {#sec-stack-overflow}\n\nAllocating memory on the stack is generally faster than allocating it on the heap.\nBut this better performance comes with many restrictions. We have already discussed\nmany of these restrictions of the stack at @sec-stack. But there is one more important\nlimitation that I want to talk about, which is the size of the stack itself.\n\nThe stack is limited in size. This size varies from computer to computer, and it depends on\na lot of things (the computer architecture, the operating system, etc.). Nevertheless, this size is usually\nnot that big. This is why we normally use the stack to store only temporary and small objects in memory.\n\nIn essence, if you try to make an allocation on the stack, that is so big that exceeds the stack size limit,\na *stack overflow* happens, and your program just crashes as a result of that. In other words, a stack overflow happens when\nyou attempt to use more space than is available on the stack.\n\nThis type of problem is very similar to a *buffer overflow*, i.e. you are trying to use more space\nthan is available in the \"buffer object\". However, a stack overflow always causes your program to crash,\nwhile a buffer overflow does not always cause your program to crash (although it often does).\n\nYou can see an example of a stack overflow in the example below. We are trying to allocate a very big array of `u64` values\non the stack. You can see below that this program does not run successfully, because it crashed\nwith a \"segmentation fault\" error message.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar very_big_alloc: [1000 * 1000 * 24]u64 = undefined;\n@memset(very_big_alloc[0..], 0);\n```\n:::\n\n\n\n\n```\nSegmentation fault (core dumped)\n```\n\nThis segmentation fault error is a result of the stack overflow that was caused by the big\nmemory allocation made on the stack, to store the `very_big_alloc` object.\nThis is why very big objects are usually stored on the heap, instead of the stack.\n\n\n\n## Allocators {#sec-allocators}\n\nOne key aspect about Zig, is that there are \"no hidden-memory allocations\" in Zig.\nWhat that really means, is that \"no allocations happen behind your back in the standard library\" [@zigguide].\n\nThis is a known problem, especially in C++. Because in C++, there are some operators that do allocate\nmemory behind the scene, and there is no way for you to know that, until you actually read the\nsource code of these operators, and find the memory allocation calls.\nMany programmers find this behaviour annoying and hard to keep track of.\n\nBut, in Zig, if a function, an operator, or anything from the standard library\nneeds to allocate some memory during its execution, then, this function/operator needs to receive (as input) an allocator\nprovided by the user, to actually be able to allocate the memory it needs.\n\nThis creates a clear distinction between functions that \"do not\" from those that \"actually do\"\nallocate memory. Just look at the arguments of this function.\nIf a function, or operator, has an allocator object as one of its inputs/arguments, then, you know for\nsure that this function/operator will allocate some memory during its execution.\n\nAn example is the `allocPrint()` function from the Zig Standard Library. With this function, you can\nwrite a new string using format specifiers. So, this function is, for example, very similar to the function `sprintf()` in C.\nIn order to write such a new string, the `allocPrint()` function needs to allocate some memory to store the\noutput string.\n\nThat is why, the first argument of this function is an allocator object that you, the user/programmer, gives\nas input to the function. In the example below, I am using the `GeneralPurposeAllocator()` as my allocator\nobject. But I could easily use any other type of allocator object from the Zig Standard Library.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nconst name = \"Pedro\";\nconst output = try std.fmt.allocPrint(\n allocator,\n \"Hello {s}!!!\",\n .{name}\n);\ntry stdout.print(\"{s}\\n\", .{output});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello Pedro!!!\n```\n\n\n:::\n:::\n\n\n\n\n\nYou get a lot of control over where and how much memory this function can allocate.\nBecause it is you, the user/programmer, that provides the allocator for the function to use.\nThis makes \"total control\" over memory management easier to achieve in Zig.\n\n### What are allocators?\n\nAllocators in Zig are objects that you can use to allocate memory for your program.\nThey are similar to the memory allocating functions in C, like `malloc()` and `calloc()`.\nSo, if you need to use more memory than you initially have, during the execution of your program, you can simply ask\nfor more memory by using an allocator object.\n\nZig offers different types of allocators, and they are usually available through the `std.heap` module of\nthe standard library. Thus, just import the Zig Standard Library into your Zig module (with `@import(\"std\")`), and you can start\nusing these allocators in your code.\n\nFurthermore, every allocator object is built on top of the `Allocator` interface in Zig.\nThis means that, every allocator object you find in Zig must have the methods `alloc()`,\n`create()`, `free()` and `destroy()`. So, you can change the type of allocator you are using,\nbut you don't need to change the function calls to the methods that do the memory allocation\n(and the free memory operations) for your program.\n\n### Why you need an allocator?\n\nAs we described at @sec-stack, everytime you make a function call in Zig,\na space in the stack is reserved for this function call. But the stack\nhas a key limitation which is: every object stored in the stack has a\nknown fixed length.\n\nBut in reality, there are two very common instances where this \"fixed length limitation\" of the stack is a deal braker:\n\n1. the objects that you create inside your function might grow in size during the execution of the function.\n1. sometimes, it is impossible to know upfront how many inputs you will receive, or how big this input will be.\n\nAlso, there is another instance where you might want to use an allocator, which is when you want to write a function that returns a pointer\nto a local object. As I described at @sec-stack, you cannot do that if this local object is stored in the\nstack. However, if this object is stored in the heap, then, you can return a pointer to this object at the\nend of the function. Because you (the programmer) control the lifetime of any heap memory that you allocate. You decide\nwhen this memory gets destroyed/freed.\n\nThese are common situations for which the stack is not good. \nThat is why you need a different memory management strategy to\nstore these objects inside your function. You need to use\na memory type that can grow together with your objects, or that you\ncan control the lifetime of this memory.\nThe heap fits this description.\n\nAllocating memory on the heap is commonly known as dynamic memory management. As the objects you create grow in size\nduring the execution of your program, you grow the amount of memory\nyou have by allocating more memory in the heap to store these objects.\nAnd you do that in Zig, by using an allocator object.\n\n\n### The different types of allocators\n\n\nAt the moment of the writing of this book, in Zig, we have 6 different\nallocators available in the standard library:\n\n- `GeneralPurposeAllocator()`.\n- `page_allocator()`.\n- `FixedBufferAllocator()` and `ThreadSafeFixedBufferAllocator()`.\n- `ArenaAllocator()`.\n- `c_allocator()` (requires you to link to libc).\n\n\nEach allocator has its own perks and limitations. All allocators, except `FixedBufferAllocator()` and `ArenaAllocator()`,\nare allocators that use the heap memory. So any memory that you allocate with\nthese allocators, will be placed in the heap.\n\n### General-purpose allocators\n\nThe `GeneralPurposeAllocator()`, as the name suggests, is a \"general purpose\" allocator. You can use it for every type\nof task. In the example below, I'm allocating enough space to store a single integer in the object `some_number`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const some_number = try allocator.create(u32);\n defer allocator.destroy(some_number);\n\n some_number.* = @as(u32, 45);\n}\n```\n:::\n\n\n\n\n\nWhile useful, you might want to use the `c_allocator()`, which is a alias to the C standard allocator `malloc()`. So, yes, you can use\n`malloc()` in Zig if you want to. Just use the `c_allocator()` from the Zig standard library. However,\nif you do use `c_allocator()`, you must link to Libc when compiling your source code with the\n`zig` compiler, by including the flag `-lc` in your compilation process.\nIf you do not link your source code to Libc, Zig will not be able to find the\n`malloc()` implementation in your system.\n\n### Page allocator\n\nThe `page_allocator()` is an allocator that allocates full pages of memory in the heap. In other words,\nevery time you allocate memory with `page_allocator()`, a full page of memory in the heap is allocated,\ninstead of just a small piece of it.\n\nThe size of this page depends on the system you are using.\nMost systems use a page size of 4KB in the heap, so, that is the amount of memory that is normally\nallocated in each call by `page_allocator()`. That is why, `page_allocator()` is considered a\nfast, but also \"wasteful\" allocator in Zig. Because it allocates a big amount of memory\nin each call, and you most likely will not need that much memory in your program.\n\n### Buffer allocators\n\nThe `FixedBufferAllocator()` and `ThreadSafeFixedBufferAllocator()` are allocator objects that\nwork with a fixed sized buffer object at the back. In other words, they use a fixed sized buffer\nobject as the basis for the memory. When you ask these allocator objects to allocate some memory for you,\nthey are essentially reserving some amount of space inside this fixed sized buffer object for you to use.\n\nThis means that, in order to use these allocators, you must first create a buffer object in your code,\nand then, give this buffer object as an input to these allocators.\n\nThis also means that, these allocator objects can allocate memory both in the stack or in the heap.\nEverything depends on where the buffer object that you provide lives. If this buffer object lives\nin the stack, then, the memory allocated is \"stack-based\". But if it lives on the heap, then,\nthe memory allocated is \"heap-based\".\n\n\nIn the example below, I'm creating a `buffer` object on the stack that is 10 elements long.\nNotice that I give this `buffer` object to the `FixedBufferAllocator()` constructor.\nNow, because this `buffer` object is 10 elements long, this means that I am limited to this space.\nI cannot allocate more than 10 elements with this allocator object. If I try to\nallocate more than that, the `alloc()` method will return an `OutOfMemory` error value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar buffer: [10]u8 = undefined;\nfor (0..buffer.len) |i| {\n buffer[i] = 0; // Initialize to zero\n}\n\nvar fba = std.heap.FixedBufferAllocator.init(&buffer);\nconst allocator = fba.allocator();\nconst input = try allocator.alloc(u8, 5);\ndefer allocator.free(input);\n```\n:::\n\n\n\n\nRemember, the memory allocated by these allocator objects can be either from\nthe stack, or, from the heap. It all depends on where the buffer object that you provide lives.\nIn the above example, the `buffer` object lives in the stack, and, therefore, the memory allocated\nis based in the stack. But what if it was based on the heap?\n\nAs we described at @sec-stack-overflow, one of the main reasons why you would use the heap,\ninstead of the stack, is to allocate huge amounts of space to store very big objects.\nThus, let's suppose you wanted to use a very big buffer object as the basis for your\nallocator objects. You would have to allocate this very big buffer object on the heap.\nThe example below demonstrates this case.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst heap = std.heap.page_allocator;\nconst memory_buffer = try heap.alloc(\n u8, 100 * 1024 * 1024 // 100 MB memory\n);\ndefer heap.free(memory_buffer);\nvar fba = std.heap.FixedBufferAllocator.init(\n memory_buffer\n);\nconst allocator = fba.allocator();\n\nconst input = try allocator.alloc(u8, 1000);\ndefer allocator.free(input);\n```\n:::\n\n\n\n\n\n\n### Arena allocator {#sec-arena-allocator}\n\nThe `ArenaAllocator()` is an allocator object that takes a child allocator as input. The idea behind the `ArenaAllocator()` in Zig\nis similar to the concept of \"arenas\" in the programming language Go[^go-arena]. It is an allocator object that allows you\nto allocate memory as many times you want, but free all memory only once.\nIn other words, if you have, for example, called 5 times the method `alloc()` of an `ArenaAllocator()` object, you can\nfree all the memory you allocated over these 5 calls at once, by simply calling the `deinit()` method of the same `ArenaAllocator()` object.\n\n[^go-arena]: \n\nIf you give, for example, a `GeneralPurposeAllocator()` object as input to the `ArenaAllocator()` constructor, like in the example below, then, the allocations\nyou perform with `alloc()` will actually be made with the underlying object `GeneralPurposeAllocator()` that was passed.\nSo, with an arena allocator, any new memory you ask for is allocated by the child allocator. The only thing that an arena allocator\nreally does is help you to free all the memory you allocated multiple times with just a single command. In the example\nbelow, I called `alloc()` 3 times. So, if I did not use an arena allocator, then, I would need to call\n`free()` 3 times to free all the allocated memory.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nvar aa = std.heap.ArenaAllocator.init(gpa.allocator());\ndefer aa.deinit();\nconst allocator = aa.allocator();\n\nconst in1 = try allocator.alloc(u8, 5);\nconst in2 = try allocator.alloc(u8, 10);\nconst in3 = try allocator.alloc(u8, 15);\n_ = in1; _ = in2; _ = in3;\n```\n:::\n\n\n\n\n\n\n### The `alloc()` and `free()` methods\n\nIn the code example below, we are accessing the `stdin`, which is\nthe standard input channel, to receive an input from the\nuser. We read the input given by the user with the `readUntilDelimiterOrEof()`\nmethod.\n\nNow, after reading the input of the user, we need to store this input somewhere in\nour program. That is why I use an allocator in this example. I use it to allocate some\namount of memory to store this input given by the user. More specifically, the method `alloc()`\nof the allocator object is used to allocate an array capable of storing 50 `u8` values.\n\nNotice that this `alloc()` method receives two inputs. The first one, is a type.\nThis defines what type of values the allocated array will store. In the example\nbelow, we are allocating an array of unsigned 8-bit integers (`u8`). But\nyou can create an array to store any type of value you want. Next, on the second argument, we\ndefine the size of the allocated array, by specifying how many elements\nthis array will contain. In the case below, we are allocating an array of 50 elements.\n\nAt @sec-zig-strings we described that strings in Zig are simply arrays of characters.\nEach character is represented by a `u8` value. So, this means that the array that\nwas allocated in the object `input` is capable of storing a string that is\n50-characters long.\n\nSo, in essence, the expression `var input: [50]u8 = undefined` would create\nan array for 50 `u8` values in the stack of the current scope. But, you\ncan allocate the same array in the heap by using the expression `var input = try allocator.alloc(u8, 50)`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdin = std.io.getStdIn();\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var input = try allocator.alloc(u8, 50);\n defer allocator.free(input);\n for (0..input.len) |i| {\n input[i] = 0; // initialize all fields to zero.\n }\n // read user input\n const input_reader = stdin.reader();\n _ = try input_reader.readUntilDelimiterOrEof(\n input,\n '\\n'\n );\n std.debug.print(\"{s}\\n\", .{input});\n}\n```\n:::\n\n\n\n\nAlso, notice that in this example, we use the `defer` keyword (which I described at @sec-defer) to run a small\npiece of code at the end of the current scope, which is the expression `allocator.free(input)`.\nWhen you execute this expression, the allocator will free the memory that it allocated\nfor the `input` object.\n\nWe have talked about this at @sec-heap. You **should always** explicitly free any memory that you allocate\nusing an allocator! You do that by using the `free()` method of the same allocator object you\nused to allocate this memory. The `defer` keyword is used in this example only to help us execute\nthis free operation at the end of the current scope.\n\n\n### The `create()` and `destroy()` methods\n\nWith the `alloc()` and `free()` methods, you can allocate memory to store multiple elements\nat once. In other words, with these methods, we always allocate an array to store multiple elements at once.\nBut what if you need enough space to store just a single item? Should you\nallocate an array of a single element through `alloc()`?\n\nThe answer is no! In this case,\nyou should use the `create()` method of the allocator object.\nEvery allocator object offers the `create()` and `destroy()` methods,\nwhich are used to allocate and free memory for a single item, respectively.\n\nSo, in essence, if you want to allocate memory to store an array of elements, you\nshould use `alloc()` and `free()`. But if you need to store just a single item,\nthen, the `create()` and `destroy()` methods are ideal for you.\n\nIn the example below, I'm defining a struct to represent an user of some sort.\nIt could be a user for a game, or software to manage resources, it doesn't mater.\nNotice that I use the `create()` method this time, to store a single `User` object\nin the program. Also notice that I use the `destroy()` method to free the memory\nused by this object at the end of the scope.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst User = struct {\n id: usize,\n name: []const u8,\n\n pub fn init(id: usize, name: []const u8) User {\n return .{ .id = id, .name = name };\n }\n};\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const user = try allocator.create(User);\n defer allocator.destroy(user);\n\n user.* = User.init(0, \"Pedro\");\n}\n```\n:::\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Memory and Allocators\n\n\nIn this chapter, we will talk about memory. How does Zig control memory? What\ncommon tools are used? Are there any important aspects that make memory\ndifferent/special in Zig? You will find the answers here.\n\nComputers fundamentally rely on memory to function. This memory acts as a temporary storage\nspace for the data and values generated during computations. Without memory, the core\nconcepts of \"variables\" and \"objects\" in programming languages would be impossible.\n\n\n\n\n## Memory spaces\n\nEvery object that you create in your Zig source code needs to be stored somewhere,\nin your computer's memory. Depending on where and how you define your object, Zig\nwill use a different \"memory space\", or a different\ntype of memory to store this object.\n\nEach type of memory normally serves for different purposes.\nIn Zig, there are 3 types of memory (or 3 different memory spaces) that we care about. They are:\n\n- Global data register (or the \"global data section\");\n- Stack;\n- Heap;\n\n\n### Compile-time known versus runtime known {#sec-compile-time}\n\nOne strategy that Zig uses to decide where it will store each object that you declare, is by looking\nat the value of this particular object. More specifically, by investigating if this value is\nknown at \"compile-time\" or at \"runtime\".\n\nWhen you write a program in Zig, the values of some of the objects that you write in your program are *known\nat compile time*. Meaning that, when you compile your Zig source code, during the compilation process,\nthe `zig` compiler can figure out the exact value of a particular object\nthat exists in your source code.\nKnowing the length (or the size) of each object is also important. So the length (or the size) of each object that you write in your program is,\nin some cases, *known at compile time*.\n\nThe `zig` compiler cares more about knowing the length (or the size) of a particular object\n, than to know its actual value. But, if the `zig` compiler knows the value of the object, then, it\nautomatically knows the size of this object. Because it can simply calculate the\nsize of the object by looking at the size of the value.\n\nTherefore, the priority for the `zig` compiler is to discover the size of each object in your source code.\nIf the value of the object in question is known at compile-time, then, the `zig` compiler\nautomatically knows the size/length of this object. But if the value of this object is not\nknown at compile-time, then, the size of this object is only known at compile-time if,\nand only if, the type of this object has a known fixed size.\n\nIn order for a type to have a known fixed size, this type must have data members whose size is fixed.\nIf this type includes, for example, a variable sized array in it, then, this type does not have a known\nfixed size. Because this array can have any size at runtime\n(i.e., it can be an array of 2 elements, or 50 elements, or 1 thousand elements, etc.).\n\nFor example, a string object, which internally is an array of constant u8 values (`[]const u8`)\nhas a variable size. It can be a string object with 100 or 500 characters in it. If we do not\nknow at compile-time, which exact string will be stored inside this string object, then, we cannot calculate\nthe size of this string object at compile-time. So, any type, or any struct declaration that you make, that\nincludes a string data member that does not have an explicit fixed size, makes this type, or this\nnew struct that you are declaring, a type that does not have a known fixed size at compile-time.\n\nIn contrast, if the type of this struct that you are declaring, includes a data member that is an array,\nbut this array has a known fixed size, like `[60]u8` (which declares an array of 60 `u8` values), then,\nthis type, or, this struct that you are declaring, becomes a type with a known fixed size at compile-time.\nAnd because of that, in this case, the `zig` compiler does not need to know at compile-time the exact value of\nany object of this type. Since the compiler can find the necessary size to store this object by\nlooking at the size of its type.\n\n\nLet's look at an example. In the source code below, we have two constant objects (`name` and `array`) declared.\nBecause the values of these particular objects are written down, in the source code itself (`\"Pedro\"`\nand the number sequence from 1 to 4), the `zig` compiler can easily discover the values of these constant\nobjects (`name` and `array`) during the compilation process.\nThis is what \"known at compile time\" means. It refers to any object that you have in your Zig source code\nwhose value can be identified at compile time.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn input_length(input: []const u8) usize {\n const n = input.len;\n return n;\n}\n\npub fn main() !void {\n const name = \"Pedro\";\n const array = [_]u8{1, 2, 3, 4};\n _ = name; _ = array;\n}\n```\n:::\n\n\n\n\nThe other side of the spectrum are objects whose values are not known at compile time.\nFunction arguments are a classic example of this. Because the value of each function\nargument depends on the value that you assign to this particular argument,\nwhen you call the function.\n\nFor example, the function `input_length()` contains an argument named `input`, which is an array of constant `u8` integers (`[]const u8`).\nIt's impossible to know the value of this particular argument at compile time. And it also is impossible to know the size/length\nof this particular argument. Because it's an array that does not have a fixed size specified explicitly in the argument type annotation.\n\nSo, we know that this `input` argument will be an array of `u8` integers. But we do not know at compile-time, its value, and neither its size.\nThis information is known only at runtime, which is the period of time when you program is executed.\nAs a consequence, the value of the expression `input.len` is also known only at runtime.\nThis is an intrinsic characteristic of any function. Just remember that the value of function arguments is usually not \"compile-time known\".\n\nHowever, as I mentioned earlier, what really matters to the compiler is to know the size of the object\nat compile-time, and not necessarily its value. So, although we don't know the value of the object `n`, which is the result of the expression\n`input.len`, at compile-time, we do know its size. Because the expression `input.len` always returns a value of type `usize`,\nand the type `usize` has a known fixed size.\n\n\n\n### Global data register\n\nThe global data register is a specific section of the executable of your Zig program, that is responsible\nfor storing any value that is known at compile time.\n\nEvery constant object whose value is known at compile time that you declare in your source code,\nis stored in the global data register. Also, every literal value that you write in your source code,\nsuch as the string `\"this is a string\"`, or the integer `10`, or a boolean value such as `true`,\nis also stored in the global data register.\n\nHonestly, you don't need to care much about this memory space. Because you can't control it,\nyou can't deliberately access it or use it for your own purposes.\nAlso, this memory space does not affect the logic of your program.\nIt simply exists in your program.\n\n\n### Stack vs Heap\n\nIf you are familiar with systems programming, or just low-level programming in general, you\nprobably have heard of the \"duel\" between Stack vs Heap. These are two different types of memory,\nor different memory spaces, which are both available in Zig.\n\nThese two types of memory don't actually duel with\neach other. This is a common mistake that beginners have, when seeing \"x vs y\" styles of\ntabloid headlines. These two types of memory are actually complementary to each other.\nSo, in almost every Zig program that you ever write, you will likely use a combination of both.\nI will describe each memory space in detail over the next sections. But for now, I just want to\nstablish the main difference between these two types of memory.\n\nIn essence, the stack memory is normally used to store values whose length is fixed and known\nat compile time. In contrast, the heap memory is a *dynamic* type of memory space, meaning that, it's\nused to store values whose length might grow during the execution (runtime) of your program [@jenny2022].\n\nLengths that grow during runtime are intrinsically associated with \"runtime known\" type of values.\nIn other words, if you have an object whose length might grow during runtime, then, the length\nof this object becomes not known at compile time. If the length is not known at compile-time,\nthe value of this object also becomes not known at compile-time.\nThese types of objects should be stored in the heap memory space, which is\na dynamic memory space, which can grow or shrink to fit the size of your objects.\n\n\n\n### Stack {#sec-stack}\n\nThe stack is a type of memory that uses the power of the *stack data structure*, hence the name.\nA \"stack\" is a type of *data structure* that uses a \"last in, first out\" (LIFO) mechanism to store the values\nyou give it to. I imagine you are familiar with this data structure.\nBut, if you are not, the [Wikipedia page](https://en.wikipedia.org/wiki/Stack_(abstract_data_type))[^wiki-stack]\n, or, the [Geeks For Geeks page](https://www.geeksforgeeks.org/stack-data-structure/)[^geek-stack] are both\nexcellent and easy resources to fully understand how this data structure works.\n\n[^wiki-stack]: \n[^geek-stack]: \n\nSo, the stack memory space is a type of memory that stores values using a stack data structure.\nIt adds and removes values from the memory by following a \"last in, first out\" (LIFO) principle.\n\nEvery time you make a function call in Zig, an amount of space in the stack is\nreserved for this particular function call [@jenny2022; @zigdocs].\nThe value of each function argument given to the function in this function call is stored in this\nstack space. Also, every local object that you declare inside the function scope is\nusually stored in this same stack space.\n\n\nLooking at the example below, the object `result` is a local object declared inside the scope of the `add()`\nfunction. Because of that, this object is stored inside the stack space reserved for the `add()` function.\nThe `r` object (which is declared outside of the `add()` function scope) is also stored in the stack.\nBut since it's declared in the \"outer\" scope, this object is stored in the\nstack space that belongs to this outer scope.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn add(x: u8, y: u8) u8 {\n const result = x + y;\n return result;\n}\n\npub fn main() !void {\n const r = add(5, 27);\n _ = r;\n}\n```\n:::\n\n\n\n\n\nSo, any object that you declare inside the scope of a function is always stored inside\nthe space that was reserved for that particular function in the stack memory. This\nalso counts for any object declared inside the scope of your `main()` function for example.\nAs you would expect, in this case, they\nare stored inside the stack space reserved for the `main()` function.\n\nOne very important detail about the stack memory is that **it frees itself automatically**.\nThis is very important, remember that. When objects are stored in the stack memory,\nyou don't have the work (or the responsibility) of freeing/destroying these objects.\nBecause they will be automatically destroyed once the stack space is freed at the end of the function scope.\n\nSo, once the function call returns (or ends, if you prefer to call it this way)\nthe space that was reserved in the stack is destroyed, and all of the objects that were in that space goes away with it.\nThis mechanism exists because this space, and the objects within it, are not necessary anymore,\nsince the function \"finished its business\".\nUsing the `add()` function that we exposed above as an example, it means that the object `result` is automatically\ndestroyed once the function returns.\n\n::: {.callout-important}\nLocal objects that are stored in the stack space of a function are automatically\nfreed/destroyed at the end of the function scope.\n:::\n\n\nThis same logic applies to any other special structure in Zig that has its own scope by surrounding\nit with curly braces (`{}`).\nFor loops, while loops, if else statements, etc. For example, if you declare any local\nobject in the scope of a for loop, this local object is accessible only within the scope\nof this particular for loop. Because once the scope of this for loop ends, the space in the stack\nreserved for this for loop is freed.\nThe example below demonstrates this idea.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This does not compile successfully!\nconst a = [_]u8{0, 1, 2, 3, 4};\nfor (0..a.len) |i| {\n const index = i;\n _ = index;\n}\n// Trying to use an object that was\n// declared in the for loop scope,\n// and that does not exist anymore.\nstd.debug.print(\"{d}\\n\", .{index});\n```\n:::\n\n\n\n\n\n\nOne important consequence of this mechanism is that, once the function returns, you can no longer access any memory\naddress that was inside the space in the stack reserved for this particular function. Because this space was\ndestroyed. This means that, if this local object is stored in the stack,\nyou cannot make a function that **returns a pointer to this object**.\n\nThink about that for a second. If all local objects in the stack are destroyed at the end of the function scope, why\nwould you even consider returning a pointer to one of these objects? This pointer is at best,\ninvalid, or, more likely, \"undefined\".\n\nIn conclusion, it's totally fine to write a function that returns the local object\nitself as result, because then, you return the value of that object as the result.\nBut, if this local object is stored in the stack, you should never write a function\nthat returns a pointer to this local object. Because the memory address pointed by the pointer\nno longer exists.\n\n\nSo, using again the `add()` function as an example, if you rewrite this function so that it\nreturns a pointer to the local object `result`, the `zig` compiler will actually compile\nyour program, with no warnings or errors. At first glance, it looks like this is good code\nthat works as expected. But this is a lie!\n\nIf you try to take a look at the value inside of the `r` object,\nor, if you try to use this `r` object in another expression\nor function call, then, you would have undefined behaviour, and major\nbugs in your program [@zigdocs, see \"Lifetime and Ownership\"[^life] and \"Undefined Behaviour\"[^undef] sections].\n\n[^life]: \n[^undef]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn add(x: u8, y: u8) *const u8 {\n const result = x + y;\n return &result;\n}\n\npub fn main() !void {\n // This code compiles successfully. But it has\n // undefined behaviour. Never do this!!!\n // The `r` object is undefined!\n const r = add(5, 27); _ = r;\n}\n```\n:::\n\n\n\n\nThis \"invalid pointer to stack variable\" problem is well known across many programming language communities.\nIf you try to do the same thing, for example, in a C or C++ program (i.e., returning an address to\na local object stored in the stack), you would also get undefined behaviour\nin the program.\n\n::: {.callout-important}\nIf a local object in your function is stored in the stack, you should never\nreturn a pointer to this local object from the function. Because\nthis pointer will always become undefined after the function returns, since the stack space of the function\nis destroyed at the end of its scope.\n:::\n\nBut what if you really need to use this local object in some way after your function returns?\nHow can you do this? The answer is: \"in the same way you would do if this were a C or C++ program. By returning\nan address to an object stored in the heap\". The heap memory has a much more flexible lifecycle,\nand allows you to get a valid pointer to a local object of a function that already returned\nfrom its scope.\n\n\n### Heap {#sec-heap}\n\nOne important limitation of the stack, is that, only objects whose length/size is known at compile-time can be\nstored in it. In contrast, the heap is a much more dynamic\n(and flexible) type of memory. It's the perfect type of memory to use\nfor objects whose size/length might grow during the execution of your program.\n\nVirtually any application that behaves as a server is a classic use case of the heap.\nA HTTP server, a SSH server, a DNS server, a LSP server, ... any type of server.\nIn summary, a server is a type of application that runs for long periods of time,\nand that serves (or \"deals with\") any incoming request that reaches this particular server.\n\nThe heap is a good choice for this type of system, mainly because the server does not know upfront\nhow many requests it will receive from users, while it is active. It could be a single request,\n5 thousand requests, or even zero requests.\nThe server needs to have the ability to allocate and manage its memory according to how many requests it receives.\n\nAnother key difference between the stack and the heap, is that the heap is a type\nof memory that you, the programmer, have complete control over. This makes the heap a\nmore flexible type of memory, but it also makes it harder to work with. Because you,\nthe programmer, is responsible for managing everything related to it. Including where the memory is allocated,\nhow much memory is allocated, and where this memory is freed.\n\n> Unlike stack memory, heap memory is allocated explicitly by programmers and it won’t be deallocated until it is explicitly freed [@jenny2022].\n\nTo store an object in the heap, you, the programmer, needs to explicitly tells Zig to do so,\nby using an allocator to allocate some space in the heap. In @sec-allocators, I will present how you can use allocators to allocate memory\nin Zig.\n\n::: {.callout-important}\nEvery memory you allocate in the heap needs to be explicitly freed by you, the programmer.\n:::\n\nThe majority of allocators in Zig do allocate memory on the heap. But some exceptions to this rule are\n`ArenaAllocator()` and `FixedBufferAllocator()`. The `ArenaAllocator()` is a special\ntype of allocator that works in conjunction with a second type of allocator.\nOn the other side, the `FixedBufferAllocator()` is an allocator that works based on\nbuffer objects created on the stack. This means that the `FixedBufferAllocator()` makes\nallocations only on the stack.\n\n\n\n\n### Summary\n\nAfter discussing all of these boring details, we can quickly recap what we learned.\nIn summary, the Zig compiler will use the following rules to decide where each\nobject you declare is stored:\n\n1. every literal value (such as `\"this is string\"`, `10`, or `true`) is stored in the global data section.\n1. every constant object (`const`) whose value **is known at compile-time** is also stored in the global data section.\n1. every object (constant or not) whose length/size **is known at compile time** is stored in the stack space for the current scope.\n1. if an object is created with the method `alloc()` or `create()` of an allocator object, this object is stored in the memory space used by this particular allocator object. Most of allocators available in Zig use the heap memory, so, this object is likely stored in the heap (`FixedBufferAllocator()` is an exception to that).\n1. the heap can only be accessed through allocators. If your object was not created through the `alloc()` or `create()` methods of an allocator object, then, it is most certainly not an object stored in the heap.\n\n\n## Stack overflows {#sec-stack-overflow}\n\nAllocating memory on the stack is generally faster than allocating it on the heap.\nBut this better performance comes with many restrictions. We have already discussed\nmany of these restrictions of the stack in @sec-stack. But there is one more important\nlimitation that I want to talk about, which is the size of the stack itself.\n\nThe stack is limited in size. This size varies from computer to computer, and it depends on\na lot of things (the computer architecture, the operating system, etc.). Nevertheless, this size is usually\nnot that big. This is why we normally use the stack to store only temporary and small objects in memory.\n\nIn essence, if you try to make an allocation on the stack, that is so big that exceeds the stack size limit,\na *stack overflow* happens, and your program just crashes as a result of that. In other words, a stack overflow happens when\nyou attempt to use more space than is available on the stack.\n\nThis type of problem is very similar to a *buffer overflow*, i.e., you are trying to use more space\nthan is available in the \"buffer object\". However, a stack overflow always causes your program to crash,\nwhile a buffer overflow does not always cause your program to crash (although it often does).\n\nYou can see an example of a stack overflow in the example below. We are trying to allocate a very big array of `u64` values\non the stack. You can see below that this program does not run successfully, because it crashed\nwith a \"segmentation fault\" error message.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar very_big_alloc: [1000 * 1000 * 24]u64 = undefined;\n@memset(very_big_alloc[0..], 0);\n```\n:::\n\n\n\n\n```\nSegmentation fault (core dumped)\n```\n\nThis segmentation fault error is a result of the stack overflow that was caused by the big\nmemory allocation made on the stack, to store the `very_big_alloc` object.\nThis is why very big objects are usually stored on the heap, instead of the stack.\n\n\n\n## Allocators {#sec-allocators}\n\nOne key aspect about Zig, is that there are \"no hidden-memory allocations\" in Zig.\nWhat that really means, is that \"no allocations happen behind your back in the standard library\" [@zigguide].\n\nThis is a known problem, especially in C++. Because in C++, there are some operators that do allocate\nmemory behind the scene, and there is no way for you to know that, until you actually read the\nsource code of these operators, and find the memory allocation calls.\nMany programmers find this behaviour annoying and hard to keep track of.\n\nBut, in Zig, if a function, an operator, or anything from the standard library\nneeds to allocate some memory during its execution, then, this function/operator needs to receive (as input) an allocator\nprovided by the user, to actually be able to allocate the memory it needs.\n\nThis creates a clear distinction between functions that \"do not\" from those that \"actually do\"\nallocate memory. Just look at the arguments of this function.\nIf a function, or operator, has an allocator object as one of its inputs/arguments, then, you know for\nsure that this function/operator will allocate some memory during its execution.\n\nAn example is the `allocPrint()` function from the Zig Standard Library. With this function, you can\nwrite a new string using format specifiers. So, this function is, for example, very similar to the function `sprintf()` in C.\nIn order to write such a new string, the `allocPrint()` function needs to allocate some memory to store the\noutput string.\n\nThat is why, the first argument of this function is an allocator object that you, the user/programmer, gives\nas input to the function. In the example below, I am using the `GeneralPurposeAllocator()` as my allocator\nobject. But I could easily use any other type of allocator object from the Zig Standard Library.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nconst name = \"Pedro\";\nconst output = try std.fmt.allocPrint(\n allocator,\n \"Hello {s}!!!\",\n .{name}\n);\ntry stdout.print(\"{s}\\n\", .{output});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello Pedro!!!\n```\n\n\n:::\n:::\n\n\n\n\n\nYou get a lot of control over where and how much memory this function can allocate.\nBecause it is you, the user/programmer, that provides the allocator for the function to use.\nThis makes \"total control\" over memory management easier to achieve in Zig.\n\n### What are allocators?\n\nAllocators in Zig are objects that you can use to allocate memory for your program.\nThey are similar to the memory allocating functions in C, like `malloc()` and `calloc()`.\nSo, if you need to use more memory than you initially have, during the execution of your program, you can simply ask\nfor more memory by using an allocator object.\n\nZig offers different types of allocators, and they are usually available through the `std.heap` module of\nthe standard library. Thus, just import the Zig Standard Library into your Zig module (with `@import(\"std\")`), and you can start\nusing these allocators in your code.\n\nFurthermore, every allocator object is built on top of the `Allocator` interface in Zig.\nThis means that, every allocator object you find in Zig must have the methods `alloc()`,\n`create()`, `free()` and `destroy()`. So, you can change the type of allocator you are using,\nbut you don't need to change the function calls to the methods that do the memory allocation\n(and the free memory operations) for your program.\n\n### Why you need an allocator?\n\nAs we described in @sec-stack, everytime you make a function call in Zig,\na space in the stack is reserved for this function call. But the stack\nhas a key limitation which is: every object stored in the stack has a\nknown fixed length.\n\nBut in reality, there are two very common instances where this \"fixed length limitation\" of the stack is a deal braker:\n\n1. the objects that you create inside your function might grow in size during the execution of the function.\n1. sometimes, it's impossible to know upfront how many inputs you will receive, or how big this input will be.\n\nAlso, there is another instance where you might want to use an allocator, which is when you want to write a function that returns a pointer\nto a local object. As I described in @sec-stack, you cannot do that if this local object is stored in the\nstack. However, if this object is stored in the heap, then, you can return a pointer to this object at the\nend of the function. Because you (the programmer) control the lifetime of any heap memory that you allocate. You decide\nwhen this memory gets destroyed/freed.\n\nThese are common situations for which the stack is not good.\nThat is why you need a different memory management strategy to\nstore these objects inside your function. You need to use\na memory type that can grow together with your objects, or that you\ncan control the lifetime of this memory.\nThe heap fits this description.\n\nAllocating memory on the heap is commonly known as dynamic memory management. As the objects you create grow in size\nduring the execution of your program, you grow the amount of memory\nyou have by allocating more memory in the heap to store these objects.\nAnd you do that in Zig, by using an allocator object.\n\n\n### The different types of allocators\n\n\nAt the moment of the writing of this book, in Zig, we have 6 different\nallocators available in the standard library:\n\n- `GeneralPurposeAllocator()`.\n- `page_allocator()`.\n- `FixedBufferAllocator()` and `ThreadSafeFixedBufferAllocator()`.\n- `ArenaAllocator()`.\n- `c_allocator()` (requires you to link to libc).\n\n\nEach allocator has its own perks and limitations. All allocators, except `FixedBufferAllocator()` and `ArenaAllocator()`,\nare allocators that use the heap memory. So any memory that you allocate with\nthese allocators, will be placed in the heap.\n\n### General-purpose allocators\n\nThe `GeneralPurposeAllocator()`, as the name suggests, is a \"general purpose\" allocator. You can use it for every type\nof task. In the example below, I'm allocating enough space to store a single integer in the object `some_number`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const some_number = try allocator.create(u32);\n defer allocator.destroy(some_number);\n\n some_number.* = @as(u32, 45);\n}\n```\n:::\n\n\n\n\n\nWhile useful, you might want to use the `c_allocator()`, which is a alias to the C standard allocator `malloc()`. So, yes, you can use\n`malloc()` in Zig if you want to. Just use the `c_allocator()` from the Zig standard library. However,\nif you do use `c_allocator()`, you must link to Libc when compiling your source code with the\n`zig` compiler, by including the flag `-lc` in your compilation process.\nIf you do not link your source code to Libc, Zig will not be able to find the\n`malloc()` implementation in your system.\n\n### Page allocator\n\nThe `page_allocator()` is an allocator that allocates full pages of memory in the heap. In other words,\nevery time you allocate memory with `page_allocator()`, a full page of memory in the heap is allocated,\ninstead of just a small piece of it.\n\nThe size of this page depends on the system you are using.\nMost systems use a page size of 4KB in the heap, so, that is the amount of memory that is normally\nallocated in each call by `page_allocator()`. That is why, `page_allocator()` is considered a\nfast, but also \"wasteful\" allocator in Zig. Because it allocates a big amount of memory\nin each call, and you most likely will not need that much memory in your program.\n\n### Buffer allocators\n\nThe `FixedBufferAllocator()` and `ThreadSafeFixedBufferAllocator()` are allocator objects that\nwork with a fixed sized buffer object at the back. In other words, they use a fixed sized buffer\nobject as the basis for the memory. When you ask these allocator objects to allocate some memory for you,\nthey are essentially reserving some amount of space inside this fixed sized buffer object for you to use.\n\nThis means that, in order to use these allocators, you must first create a buffer object in your code,\nand then, give this buffer object as an input to these allocators.\n\nThis also means that, these allocator objects can allocate memory both in the stack or in the heap.\nEverything depends on where the buffer object that you provide lives. If this buffer object lives\nin the stack, then, the memory allocated is \"stack-based\". But if it lives on the heap, then,\nthe memory allocated is \"heap-based\".\n\n\nIn the example below, I'm creating a `buffer` object on the stack that is 10 elements long.\nNotice that I give this `buffer` object to the `FixedBufferAllocator()` constructor.\nNow, because this `buffer` object is 10 elements long, this means that I am limited to this space.\nI cannot allocate more than 10 elements with this allocator object. If I try to\nallocate more than that, the `alloc()` method will return an `OutOfMemory` error value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar buffer: [10]u8 = undefined;\nfor (0..buffer.len) |i| {\n buffer[i] = 0; // Initialize to zero\n}\n\nvar fba = std.heap.FixedBufferAllocator.init(&buffer);\nconst allocator = fba.allocator();\nconst input = try allocator.alloc(u8, 5);\ndefer allocator.free(input);\n```\n:::\n\n\n\n\nRemember, the memory allocated by these allocator objects can be either from\nthe stack, or, from the heap. It all depends on where the buffer object that you provide lives.\nIn the above example, the `buffer` object lives in the stack, and, therefore, the memory allocated\nis based in the stack. But what if it was based on the heap?\n\nAs we described in @sec-stack-overflow, one of the main reasons why you would use the heap,\ninstead of the stack, is to allocate huge amounts of space to store very big objects.\nThus, let's suppose you wanted to use a very big buffer object as the basis for your\nallocator objects. You would have to allocate this very big buffer object on the heap.\nThe example below demonstrates this case.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst heap = std.heap.page_allocator;\nconst memory_buffer = try heap.alloc(\n u8, 100 * 1024 * 1024 // 100 MB memory\n);\ndefer heap.free(memory_buffer);\nvar fba = std.heap.FixedBufferAllocator.init(\n memory_buffer\n);\nconst allocator = fba.allocator();\n\nconst input = try allocator.alloc(u8, 1000);\ndefer allocator.free(input);\n```\n:::\n\n\n\n\n\n\n### Arena allocator {#sec-arena-allocator}\n\nThe `ArenaAllocator()` is an allocator object that takes a child allocator as input. The idea behind the `ArenaAllocator()` in Zig\nis similar to the concept of \"arenas\" in the programming language Go[^go-arena]. It's an allocator object that allows you\nto allocate memory as many times you want, but free all memory only once.\nIn other words, if you have, for example, called 5 times the method `alloc()` of an `ArenaAllocator()` object, you can\nfree all the memory you allocated over these 5 calls at once, by simply calling the `deinit()` method of the same `ArenaAllocator()` object.\n\n[^go-arena]: \n\nIf you give, for example, a `GeneralPurposeAllocator()` object as input to the `ArenaAllocator()` constructor, like in the example below, then, the allocations\nyou perform with `alloc()` will actually be made with the underlying object `GeneralPurposeAllocator()` that was passed.\nSo, with an arena allocator, any new memory you ask for is allocated by the child allocator. The only thing that an arena allocator\nreally does is help you to free all the memory you allocated multiple times with just a single command. In the example\nbelow, I called `alloc()` 3 times. So, if I did not use an arena allocator, then, I would need to call\n`free()` 3 times to free all the allocated memory.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nvar aa = std.heap.ArenaAllocator.init(gpa.allocator());\ndefer aa.deinit();\nconst allocator = aa.allocator();\n\nconst in1 = try allocator.alloc(u8, 5);\nconst in2 = try allocator.alloc(u8, 10);\nconst in3 = try allocator.alloc(u8, 15);\n_ = in1; _ = in2; _ = in3;\n```\n:::\n\n\n\n\n\n\n### The `alloc()` and `free()` methods\n\nIn the code example below, we are accessing the `stdin`, which is\nthe standard input channel, to receive an input from the\nuser. We read the input given by the user with the `readUntilDelimiterOrEof()`\nmethod.\n\nNow, after reading the input of the user, we need to store this input somewhere in\nour program. That is why I use an allocator in this example. I use it to allocate some\namount of memory to store this input given by the user. More specifically, the method `alloc()`\nof the allocator object is used to allocate an array capable of storing 50 `u8` values.\n\nNotice that this `alloc()` method receives two inputs. The first one, is a type.\nThis defines what type of values the allocated array will store. In the example\nbelow, we are allocating an array of unsigned 8-bit integers (`u8`). But\nyou can create an array to store any type of value you want. Next, in the second argument, we\ndefine the size of the allocated array, by specifying how many elements\nthis array will contain. In the case below, we are allocating an array of 50 elements.\n\nIn @sec-zig-strings we described that strings in Zig are simply arrays of characters.\nEach character is represented by a `u8` value. So, this means that the array that\nwas allocated in the object `input` is capable of storing a string that is\n50-characters long.\n\nSo, in essence, the expression `var input: [50]u8 = undefined` would create\nan array for 50 `u8` values in the stack of the current scope. But, you\ncan allocate the same array in the heap by using the expression `var input = try allocator.alloc(u8, 50)`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdin = std.io.getStdIn();\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var input = try allocator.alloc(u8, 50);\n defer allocator.free(input);\n for (0..input.len) |i| {\n input[i] = 0; // initialize all fields to zero.\n }\n // read user input\n const input_reader = stdin.reader();\n _ = try input_reader.readUntilDelimiterOrEof(\n input,\n '\\n'\n );\n std.debug.print(\"{s}\\n\", .{input});\n}\n```\n:::\n\n\n\n\nAlso, notice that in this example, we use the `defer` keyword (which I described in @sec-defer) to run a small\npiece of code at the end of the current scope, which is the expression `allocator.free(input)`.\nWhen you execute this expression, the allocator will free the memory that it allocated\nfor the `input` object.\n\nWe have talked about this in @sec-heap. You **should always** explicitly free any memory that you allocate\nusing an allocator! You do that by using the `free()` method of the same allocator object you\nused to allocate this memory. The `defer` keyword is used in this example only to help us execute\nthis free operation at the end of the current scope.\n\n\n### The `create()` and `destroy()` methods\n\nWith the `alloc()` and `free()` methods, you can allocate memory to store multiple elements\nat once. In other words, with these methods, we always allocate an array to store multiple elements at once.\nBut what if you need enough space to store just a single item? Should you\nallocate an array of a single element through `alloc()`?\n\nThe answer is no! In this case,\nyou should use the `create()` method of the allocator object.\nEvery allocator object offers the `create()` and `destroy()` methods,\nwhich are used to allocate and free memory for a single item, respectively.\n\nSo, in essence, if you want to allocate memory to store an array of elements, you\nshould use `alloc()` and `free()`. But if you need to store just a single item,\nthen, the `create()` and `destroy()` methods are ideal for you.\n\nIn the example below, I'm defining a struct to represent an user of some sort.\nIt could be a user for a game, or software to manage resources, it doesn't mater.\nNotice that I use the `create()` method this time, to store a single `User` object\nin the program. Also notice that I use the `destroy()` method to free the memory\nused by this object at the end of the scope.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst User = struct {\n id: usize,\n name: []const u8,\n\n pub fn init(id: usize, name: []const u8) User {\n return .{ .id = id, .name = name };\n }\n};\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const user = try allocator.create(User);\n defer allocator.destroy(user);\n\n user.* = User.init(0, \"Pedro\");\n}\n```\n:::\n", + "supporting": [ + "01-memory_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/01-zig-weird/execute-results/html.json b/_freeze/Chapters/01-zig-weird/execute-results/html.json index 7f926500..5bdb8502 100644 --- a/_freeze/Chapters/01-zig-weird/execute-results/html.json +++ b/_freeze/Chapters/01-zig-weird/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "ba740c33772422f50c73c140fef90a2d", + "hash": "686bec0276a3623e1397e1b7ecac1bfa", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it is still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. They really make it sometimes hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscure the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that get's compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e. it is where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contain Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nTherefore, Zig contains a native build system in it, and\nwe can use this build system to write small scripts in Zig,\nwhich describes the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e. creating new objects)\nare made in Zig. You can create a new object in Zig by using the following syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). At @sec-assignments we talk more about objects in general.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n```\n:::\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that at @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIs worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt is like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portable C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig build.zig.zon main src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nIn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e. the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. Thus, if you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith a \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, operations like accessing the `stdout` (or opening a file) on Windows\ndepends on resources that are available only at *runtime* (you will learn more about compile-time\nversus runtime at @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerge from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword at @sec-comptime.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation at a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues \n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described in @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig later in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig? \nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar to our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentation.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It is a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (on YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e. identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n age = 25;\n ~~^~~\n```\n\nIn contrast, if you use `var`, then, the object created is a variable object.\nWith `var` you can declare this object in your source code, and then,\nchange the value of this object how many times you want over future points\nin your source code.\n\nSo, using the same code example exposed above, if I change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it is an \"variable object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIs important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code use this object while it is uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object. \n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e. if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n const age = 15;\n ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to a special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It is discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also get's discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig have many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e. the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\nIs worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it have the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array. \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it is a slice that\naccess all elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhave 2 elements in it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" at @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth at @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially at @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned at @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e. the start and the end of this range)\nis known at compile-time, the slice object that get's created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nat @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that get's created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e. a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can \ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n 1, 2, 3, 4, 5,\n 6, 7, 8, 9, 10\n};\n// This slice have a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n```\n:::\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat get's created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, the `slice` object have a runtime known range, because the end index of the range\nis not known at compile time. In other words, the size of the array at `buffer` is not known\nat compile time. When we execute this program, the size of the array might be 10, or, it might be 12\ndepending on where we execute it. Therefore, we don't know at compile time if\nthe slice object have a range of size 10, or, a range of size 12.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var n: usize = 0;\n if (builtin.target.os.tag == .windows) {\n n = 10;\n } else {\n n = 12;\n }\n const buffer = try allocator.alloc(u64, n);\n const slice = buffer[0..];\n _ = slice;\n}\n```\n:::\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code have its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e. a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n y += 1;\n break :add_one y;\n};\nif (x == 124 and y == 124) {\n try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nIn summary, there are two types of string values that you care about in Zig, which are:\n\n- String literal values.\n- String objects.\n\nA string literal value is just a pointer to a null-terminated array of bytes (i.e. similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string into the data type of the value itself.\nTherefore, a string literal value have a data type in the format `*const [n:0]u8`. The `n` in the data type\nindicates the size of the string.\n\nOn the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes,\nor, in other words, a slice of `u8` values (slices were presented at @sec-arrays). Thus,\na string object have a data type of `[]u8` or `[]const u8`, depending if the string object is\nmarked as constant with `const`, or as variable with `var`.\n\nBecause a string object is essentially a slice, it means that a string object always contains two things:\na pointer to an array of bytes (i.e. `u8` values) that represents the string value; and also, a length value,\nwhich specifies the size of the slice, or, how many elements there is in the slice.\nIs worth to emphasize that the array of bytes in a string object is not null-terminated, like in a\nstring literal value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n\"A literal value\";\n// This is a string object:\nconst object: []const u8 = \"A string object\";\n```\n:::\n\n\n\n\nZig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e. a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example\";\n try stdout.print(\"Bytes that represents the string object: \", .{});\n for (string_object) |byte| {\n try stdout.print(\"{X} \", .{byte});\n }\n try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n 73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n### Strings in C\n\nAt first glance, a string literal value in Zig looks very similar to how C treats strings as well.\nIn more details, string values in C are treated internally as an array of arbitrary bytes,\nand this array is also null-terminated.\n\nBut one key difference between a Zig string literal and a C string, is that Zig also stores the length of\nthe string inside the object itself. In the case of a string literal value, this length is stored in the\ndata type of the value (i.e. the `n` variable in `[n:0]u8`). While, in a string object, the length is stored\nin the `len` attribute of the slice that represents the string object. This small detail makes your code safer,\nbecause it is much easier for the Zig compiler to check if you are trying to access an element that is\n\"out of bounds\", i.e. if your trying to access memory that does not belong to you.\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n char* array = \"An example of string in C\";\n int index = 0;\n while (1) {\n if (array[index] == '\\0') {\n break;\n }\n index++;\n }\n printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible. In a string object for example, you can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example of string literal in Zig\";\n try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it is a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const simple_array = [_]i32{1, 2, 3, 4};\n const string_obj: []const u8 = \"A string object\";\n std.debug.print(\n \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n );\n std.debug.print(\n \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n );\n std.debug.print(\n \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n );\n std.debug.print(\n \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nType 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons\n st [4]i32Type 4: []const u8\n```\n\n\n:::\n:::\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIs important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"Ⱥ\";\n _ = try stdout.write(\n \"Bytes that represents the string object: \"\n );\n for (string_object) |char| {\n try stdout.print(\"{X} \", .{char});\n }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n var iterator = utf8.iterator();\n while (iterator.nextCodepointSlice()) |codepoint| {\n try stdout.print(\n \"got codepoint {}\\n\",\n .{std.fmt.fmtSliceHexUpper(codepoint)},\n );\n }\n}\n\n```\n:::\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig at @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers at @sec-root-file and especially at @sec-assignments.\n- How strings work in Zig at @sec-zig-strings.\n- How to use arrays and slices at @sec-arrays.\n- How to import functionality from other Zig modules at @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* at @sec-structs-and-oop.\n- Basic control flow syntax at @sec-zig-control-flow.\n- Enums at @sec-enum;\n- Pointers and Optionals at @sec-pointer;\n- Error handling with `try` and `catch` at @sec-error-handling;\n- Unit tests at @sec-unittests;\n- Vectors at @sec-vectors-simd;\n- Build System at @sec-build-system;\n\n\n\n\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\n\nlanguage, it's still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. Sometimes, they really make it hard to debug\n\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscure the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that gets compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e., where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contains Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nWe can use this build system to write small scripts in Zig,\nwhich describe the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e., creating new objects)\nare made in Zig. You can create a new object in Zig by using the syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). In @sec-assignments we talk more about objects in general.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n```\n:::\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that in @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIt's worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt's like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portable C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig build.zig.zon main src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nIn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e., the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. If you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith an \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, on Windows, operations like accessing the `stdout` (or opening a file) depend on\nresources that are available only at *runtime* (you will learn more about compile-time versus runtime\nin @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerges from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword in @sec-comptime.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation in a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues\n\n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described in @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig later in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig?\nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar to our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentation.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It's a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (on YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e., identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n age = 25;\n ~~^~~\n```\n\nIn contrast, if you use `var`, then, the object created is a variable object.\nWith `var` you can declare this object in your source code, and then,\nchange the value of this object how many times you want over future points\nin your source code.\n\nSo, using the same code example exposed above, if I change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it's a \"variable object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIt's important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code uses this object while it's uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object.\n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e., if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n const age = 15;\n ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to a special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It's discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also gets discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig have many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e., the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\nIt's worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it have the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it's a slice that\naccesses all elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhave 2 elements in it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" in @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth in @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially in @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned in @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e., the start and the end of this range)\nis known at compile-time, the slice object that gets created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nin @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that gets created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e., a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can\ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n 1, 2, 3, 4, 5,\n 6, 7, 8, 9, 10\n};\n// This slice have a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n```\n:::\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat gets created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, the `slice` object have a runtime known range, because the end index of the range\nis not known at compile time. In other words, the size of the array at `buffer` is not known\nat compile time. When we execute this program, the size of the array might be 10, or, it might be 12\ndepending on where we execute it. Therefore, we don't know at compile time if\nthe slice object have a range of size 10, or, a range of size 12.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var n: usize = 0;\n if (builtin.target.os.tag == .windows) {\n n = 10;\n } else {\n n = 12;\n }\n const buffer = try allocator.alloc(u64, n);\n const slice = buffer[0..];\n _ = slice;\n}\n```\n:::\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code have its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e., a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n y += 1;\n break :add_one y;\n};\nif (x == 124 and y == 124) {\n try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nIn summary, there are two types of string values that you care about in Zig, which are:\n\n- String literal values.\n- String objects.\n\nA string literal value is just a pointer to a null-terminated array of bytes (i.e., similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string into the data type of the value itself.\nTherefore, a string literal value have a data type in the format `*const [n:0]u8`. The `n` in the data type\nindicates the size of the string.\n\nOn the other hand, a string object in Zig is basically a slice to an arbitrary sequence of bytes,\nor, in other words, a slice of `u8` values (slices were presented in @sec-arrays). Thus,\na string object have a data type of `[]u8` or `[]const u8`, depending if the string object is\nmarked as constant with `const`, or as variable with `var`.\n\nBecause a string object is essentially a slice, it means that a string object always contains two things:\na pointer to an array of bytes (i.e., `u8` values) that represents the string value; and also, a length value,\nwhich specifies the size of the slice, or, how many elements there is in the slice.\nIt's worth to emphasize that the array of bytes in a string object is not null-terminated, like in a\nstring literal value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n\"A literal value\";\n// This is a string object:\nconst object: []const u8 = \"A string object\";\n```\n:::\n\n\n\n\nZig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e., a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example\";\n try stdout.print(\"Bytes that represents the string object: \", .{});\n for (string_object) |byte| {\n try stdout.print(\"{X} \", .{byte});\n }\n try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n 73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n### Strings in C\n\nAt first glance, a string literal value in Zig looks very similar to how C treats strings as well.\nIn more details, string values in C are treated internally as an array of arbitrary bytes,\nand this array is also null-terminated.\n\nBut one key difference between a Zig string literal and a C string, is that Zig also stores the length of\nthe string inside the object itself. In the case of a string literal value, this length is stored in the\ndata type of the value (i.e., the `n` variable in `[n:0]u8`). While, in a string object, the length is stored\nin the `len` attribute of the slice that represents the string object. This small detail makes your code safer,\nbecause it's much easier for the Zig compiler to check if you are trying to access an element that is\n\"out of bounds\", i.e., if your trying to access memory that does not belong to you.\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n char* array = \"An example of string in C\";\n int index = 0;\n while (1) {\n if (array[index] == '\\0') {\n break;\n }\n index++;\n }\n printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible. In a string object for example, you can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example of string literal in Zig\";\n try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it's a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const simple_array = [_]i32{1, 2, 3, 4};\n const string_obj: []const u8 = \"A string object\";\n std.debug.print(\n \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n );\n std.debug.print(\n \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n );\n std.debug.print(\n \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n );\n std.debug.print(\n \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nType 1: [4]i32Type 2: *const [16:0]u8Type 3: *cons\n st [4]i32Type 4: []const u8\n```\n\n\n:::\n:::\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIt's important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"Ⱥ\";\n _ = try stdout.write(\n \"Bytes that represents the string object: \"\n );\n for (string_object) |char| {\n try stdout.print(\"{X} \", .{char});\n }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n var iterator = utf8.iterator();\n while (iterator.nextCodepointSlice()) |codepoint| {\n try stdout.print(\n \"got codepoint {}\\n\",\n .{std.fmt.fmtSliceHexUpper(codepoint)},\n );\n }\n}\n\n```\n:::\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig in @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers in @sec-root-file and especially in @sec-assignments.\n- How strings work in Zig in @sec-zig-strings.\n- How to use arrays and slices in @sec-arrays.\n- How to import functionality from other Zig modules in @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* in @sec-structs-and-oop.\n- Basic control flow syntax in @sec-zig-control-flow.\n- Enums in @sec-enum;\n- Pointers and Optionals in @sec-pointer;\n- Error handling with `try` and `catch` in @sec-error-handling;\n- Unit tests in @sec-unittests;\n- Vectors in @sec-vectors-simd;\n- Build System in @sec-build-system;\n", + "supporting": [ + "01-zig-weird_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/02-debugging/execute-results/html.json b/_freeze/Chapters/02-debugging/execute-results/html.json index 5b18dbcb..2068b83e 100644 --- a/_freeze/Chapters/02-debugging/execute-results/html.json +++ b/_freeze/Chapters/02-debugging/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "81acc8dfbc423fbdea18f9b7f8f1ea18", + "hash": "f6eea7230762e3b8cde487458c00b745", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Debugging Zig applications\n\nBeing able to debug your applications is essential for any programmer who wants to\ndo serious programming in any language. That is why, in this chapter, we are going to talk about the\navailable strategies and tools to debug applications written in Zig.\n\n\n## Print debugging\n\nWe begin with the classic and battle-tested *print debugging* strategy.\nThe key advantage that debugging offers you is *visibility*.\nWith *print statements* you can easily see what results and objects\nare being produced by your application.\n\nThat is the essence of *print debugging*. Is to use\nprint expressions to see the values that are being generated by your program,\nand, as a result, get a much better understanding of how your program\nis behaving.\n\nMany programmers often resort to the print functions in Zig, such as the `stdout.print()`,\nor, the `std.debug.print()`, to get a better understanding of their programs.\nThis is a known and old strategy that is very simple and effective, and it is better known within\nthe programming community as *print debugging*.\nIn Zig, you can print information to the `stdout` or `stderr` streams of your system.\n\nLet's begin with `stdout`. First, you\nneed to get access to the `stdout`, by calling the `getStdOut()` method, from\nthe Zig Standard Library. This method returns a *file descriptor* object,\nand, through this object you can read/write to the `stdout`.\nI recommend you to check out all methods available in this object, by [checking the page in\nthe Zig Standard Library Official Reference for the type `File`](https://ziglang.org/documentation/master/std/#std.fs.File)[^zig-fiile-reference].\n\n[^zig-fiile-reference]: .\n\nFor our purpose here, which is to write something to the `stdout`, especially to debug our\nprogram, I recommend you to use the `writer()` method, which gives you a *writer* object.\nThis *writer* object offers some helper methods to write stuff into the file descriptor object\nthat represents the `stdout` stream. In special, the `print()` method.\n\n\nThe `print()` method from this *writer* object is a \"print formatter\" type of a function.\nIn other words, this method works exactly like the `printf()` function from C,\nor, like `println!()` from Rust.\nIn the first argument of the function, you specify a template string, and,\nin the second argument, you provide a list of values (or objects) that you want to insert\ninto your template message.\n\nIdeally, the template string in the first argument should contain some format specifier.\nEach format specifier is matched to a value (or object) that you have listed in the second argument.\nSo, if you provided 5 different objects in the second argument, then, the template string\nshould contain 5 format specifiers, one for each object provided.\n\nEach format specifier is represented by a single letter, and\nyou provide this format specifier inside a pair of curly braces. So, if you want to format\nyour object using the string specifier (`s`), then, you can insert the text `{s}` in your template string.\nHere is a quick list of the most used format specifiers:\n\n- `d`: for printing integers and floating-point numbers.\n- `c`: for printing characters.\n- `s`: for printing strings.\n- `p`: for printing memory addresses.\n- `x`: for printing hexadecimal values.\n- `any`: use any compatible format specifier (i.e. it automatically selects a format specifier for you).\n\nThe code example below gives you an example of use of this `print()` method\nwith the `d` format specifier.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn add(x: u8, y: u8) u8 {\n return x + y;\n}\n\npub fn main() !void {\n const result = add(34, 16);\n try stdout.print(\"Result: {d}\", .{result});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 50\n```\n\n\n:::\n:::\n\n\n\n\nIt is important to emphasize that, the `stdout.print()` method, as you would expect,\nprints your template string into the `stdout` stream of your system.\nHowever, you can also print your template string into the `stderr` stream\nif your prefer. All you need to do, is to replace the `stdout.print()`\ncall with the function `std.debug.print()`. Like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add(x: u8, y: u8) u8 {\n return x + y;\n}\n\npub fn main() !void {\n const result = add(34, 16);\n std.debug.print(\"Result: {d}\\n\", .{result});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 50\n```\n\n\n:::\n:::\n\n\n\n\n\nYou could also achieve the exact same result by getting a file descriptor object to `stderr`,\nthen, creating a *writer* object to `stderr`, then, using the `print()` method of this\n*writer* object, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stderr = std.io.getStdErr().writer();\n// some more lines ...\ntry stderr.print(\"Result: {d}\", .{result});\n```\n:::\n\n\n\n\n\n\n## Debugging through debuggers\n\nAlthough *print debugging* is a valid and very useful strategy,\nmost programmers prefer to use a debugger to debug their programs.\nSince Zig is a low-level language, you can use either GDB (GNU Debugger),\nor LLDB (LLVM Project Debugger) as your debugger.\n\nBoth debuggers can work with Zig code, and it's a matter of taste here.\nYou choose the debugger of your preference, and you work with it.\nIn this book, I will use LLDB as my debugger on the examples.\n\n\n### Compile your source code in debug mode {#sec-compile-debug-mode}\n\nIn order to debug your program through a debugger, you must compile\nyour source code in `Debug` mode. Because when you compile your\nsource code in other modes (such as `Release`), the compiler usually\nstrips out some essential information that is used by the debugger\nto read and track your program, like PDB (*Program Database*) files.\n\nBy compiling your source code in `Debug` mode, you ensure that the debugger\nwill find the necessary information in your program to debug it.\nBy default, the compiler uses the `Debug` mode when compiling your code.\nHaving this in mind, when you compile your program with the `build-exe`\ncommand (which was described at @sec-compile-code), if you don't specify\nan explicit mode through the `-O` command-line [^oargument]\nargument, then, the compiler will compile your code in `Debug` mode.\n\n[^oargument]: See .\n\n\n### Let's debug a program\n\nAs an example, let's use LLDB to navigate and investigate the following\npiece of Zig code:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\nfn add_and_increment(a: u8, b: u8) u8 {\n const sum = a + b;\n const incremented = sum + 1;\n return incremented;\n}\n\npub fn main() !void {\n var n = add_and_increment(2, 3);\n n = add_and_increment(n, n);\n try stdout.print(\"Result: {d}!\\n\", .{n});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 13!\n```\n\n\n:::\n:::\n\n\n\n\nThere is nothing wrong with this program. But it is\na good start for us. First, we need to compile\nthis program with the `zig build-exe` command.\nFor this example, suppose that I have compiled the above\nZig code into a binary executable called `add_program`.\n\n```bash\nzig build-exe add_program.zig\n```\n\nNow, we can start LLDB with `add_program`, like this:\n\n```bash\nlldb add_program\n```\n\nFrom now on, LLDB is started, and you can know that I'm\nexecuting LLDB commands by looking at the prefix `(lldb)`.\nIf something is prefixed with `(lldb)`, then you know\nthat it is a LLDB command.\n\nThe first thing I will do, is to set a breakpoint at\nthe `main()` function, by executing `b main`.\nAfter that, I just start the execution of the program\nwith `run`.\nYou can see in the output below, that the execution\nstopped at the first line in the function `main()`, as we expected.\n\n```bash\n(lldb) b main\nBreakpoint 1: where = debugging`debug1.main + 22\n at debug1.zig:11:30, address = 0x00000000010341a6\n(lldb) run\nProcess 8654 launched: 'add_program' (x86_64)\nProcess 8654 stopped\n* thread #1, name = 'add_program',\n stop reason = breakpoint 1.1 frame #0: 0x10341a6\n add_program`debug1.main at add_program.zig:11:30\n 8 \t}\n 9\n 10 \tpub fn main() !void {\n-> 11 \t var n = add_and_increment(2, 3);\n 12 \t n = add_and_increment(n, n);\n 13 \t try stdout.print(\"Result: {d}!\\n\", .{n});\n 14 \t}\n```\n\nI can start navigating through the code, and checking the objects\nthat are being generated. If you are not familiar with the commands\navailable in LLDB, I recommend you to read the official documentation\nof the project[^lldb].\nYou can also look for cheat sheets, which quickly describes all commands\navailable for you[^lldb-quick-list].\n\n[^lldb]: \n[^lldb-quick-list]: .\n\nCurrently, we are in the first line at the `main()` function. In this line, we create\nthe `n` object, by executing the `add_and_increment()` function.\nTo execute the current line of code, and go to the next line, we can\nrun the `n` LLDB command. Let's execute this command.\n\nAfter we executed this line, we can also look at the value stored inside this `n` object\nby using the `p` LLDB command. The syntax for this command is `p `.\n\nIf we take a look at the value stored in the `n` object (`p n`),\nnotice that it stores the hexadecimal value `0x06`, which\nis the number 6 in decimal. We can also see that this value has a type of `unsigned char`,\nwhich is an unsigned 8-bit integer.\nWe have talked already about this at @sec-zig-strings, that `u8` integers in Zig are equivalent\nto the C data type `unsigned char`.\n\n\n\n```bash\n(lldb) n\nProcess 4798 stopped\n* thread #1, name = 'debugging',\n stop reason = step over frame #0: 0x10341ae\n debugging`debug1.main at debug1.zig:12:26\n 9\n 10 \tpub fn main() !void {\n 11 \t var n = add_and_increment(2, 3);\n-> 12 \t n = add_and_increment(n, n);\n 13 \t try stdout.print(\"Result: {d}!\\n\", .{n});\n 14 \t}\n(lldb) p n\n(unsigned char) $1 = '\\x06'\n```\n\nNow, on the next line of code, we are executing the `add_and_increment()` function once again.\nWhy not step inside this function? Shall we? We can do that, by executing the `s` LLDB command.\nNotice in the example below that, after executing this command, we have entered into the context of the\n`add_and_increment()` function.\n\nAlso notice in the example below that, I have walked two more lines in the function's body, then,\nI execute the `frame variable` LLDB command, to see at once, the value stored in each of the variables\nthat were created inside the current scope.\n\nYou can see in the output below that, the object `sum` stores the value `\\f`,\nwhich represents the *form feed* character. This character in the ASCII table,\ncorresponds to the hexadecimal value `0x0C`, or, in decimal, the number 12.\nSo, this means that the result of the expression `a + b` executed at line\n5, resulted in the number 12.\n\n```bash\n(lldb) s\nProcess 4798 stopped\n* thread #1, name = 'debugging',\n stop reason = step in frame #0: 0x10342de\n debugging`debug1.add_and_increment(a='\\x02', b='\\x03')\n at debug1.zig:4:39\n-> 4 \tfn add_and_increment(a: u8, b: u8) u8 {\n 5 \t const sum = a + b;\n 6 \t const incremented = sum + 1;\n 7 \t return incremented;\n(lldb) n\n(lldb) n\n(lldb) frame variable\n(unsigned char) a = '\\x06'\n(unsigned char) b = '\\x06'\n(unsigned char) sum = '\\f'\n(unsigned char) incremented = '\\x06'\n```\n\n\n\n## How to investigate the data type of your objects\n\nSince Zig is a strongly-typed language, the data types associated with your objects\nare very important for your program. So, debugging the data types associated\nwith your objects might be important to understand bugs and errors in your program.\n\nWhen you walk through your program with a debugger, you can inspect the types of\nyour objects by simply printing them to the console, with the LLDB `p` command.\nBut you also have alternatives embedded in the language itself to access the data\ntypes of your objects.\n\nIn Zig, you can retrieve the data type of an object, by using the built-in function\n`@TypeOf()`. Just apply this function over the object, and you get access to\nthe data type of the object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst expect = std.testing.expect;\n\npub fn main() !void {\n const number: i32 = 5;\n try expect(@TypeOf(number) == i32);\n try stdout.print(\"{any}\\n\", .{@TypeOf(number)});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ni32\n```\n\n\n:::\n:::\n\n\n\n\nThis function is similar to the `type()` built-in function from Python,\nor, the `typeof` operator in Javascript.\n\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Debugging Zig applications\n\nBeing able to debug your applications is essential for any programmer who wants to\ndo serious programming in any language. That is why, in this chapter, we are going to talk about the\navailable strategies and tools to debug applications written in Zig.\n\n\n## Print debugging\n\nWe begin with the classic and battle-tested *print debugging* strategy.\nThe key advantage that debugging offers you is *visibility*.\nWith *print statements* you can easily see what results and objects\nare being produced by your application.\n\nThis is the essence of *print debugging* - using\nprint expressions to see the values that are being generated by your program,\nand, as a result, get a much better understanding of how your program\nis behaving.\n\nMany programmers often resort to the print functions in Zig, such as the `stdout.print()`,\nor, the `std.debug.print()`, to get a better understanding of their programs.\nThis is a known and old strategy that is very simple and effective, and it's better known within\nthe programming community as *print debugging*.\nIn Zig, you can print information to the `stdout` or `stderr` streams of your system.\n\nLet's begin with `stdout`. First, you\nneed to get access to the `stdout`, by calling the `getStdOut()` method, from\nthe Zig Standard Library. This method returns a *file descriptor* object,\nand, through this object you can read/write to the `stdout`.\nI recommend you to check out all methods available in this object, by [checking the page in\nthe Zig Standard Library Official Reference for the type `File`](https://ziglang.org/documentation/master/std/#std.fs.File)[^zig-fiile-reference].\n\n[^zig-fiile-reference]: .\n\nFor our purpose here, which is to write something to the `stdout`, especially to debug our\nprogram, I recommend you to use the `writer()` method, which gives you a *writer* object.\nThis *writer* object offers some helper methods to write stuff into the file descriptor object\nthat represents the `stdout` stream. In special, the `print()` method.\n\n\nThe `print()` method from this *writer* object is a \"print formatter\" type of a function.\nIn other words, this method works exactly like the `printf()` function from C,\nor, like `println!()` from Rust.\nIn the first argument of the function, you specify a template string, and,\nin the second argument, you provide a list of values (or objects) that you want to insert\ninto your template message.\n\nIdeally, the template string in the first argument should contain some format specifier.\nEach format specifier is matched to a value (or object) that you have listed in the second argument.\nSo, if you provided 5 different objects in the second argument, then, the template string\nshould contain 5 format specifiers, one for each object provided.\n\nEach format specifier is represented by a single letter, and\nyou provide this format specifier inside a pair of curly braces. So, if you want to format\nyour object using the string specifier (`s`), then, you can insert the text `{s}` in your template string.\nHere is a quick list of the most used format specifiers:\n\n- `d`: for printing integers and floating-point numbers.\n- `c`: for printing characters.\n- `s`: for printing strings.\n- `p`: for printing memory addresses.\n- `x`: for printing hexadecimal values.\n- `any`: use any compatible format specifier (i.e., it automatically selects a format specifier for you).\n\nThe code example below gives you an example of use of this `print()` method\nwith the `d` format specifier.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn add(x: u8, y: u8) u8 {\n return x + y;\n}\n\npub fn main() !void {\n const result = add(34, 16);\n try stdout.print(\"Result: {d}\", .{result});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 50\n```\n\n\n:::\n:::\n\n\n\n\nIt's important to emphasize that, the `stdout.print()` method, as you would expect,\nprints your template string into the `stdout` stream of your system.\nHowever, you can also print your template string into the `stderr` stream\nif your prefer. All you need to do, is to replace the `stdout.print()`\ncall with the function `std.debug.print()`. Like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add(x: u8, y: u8) u8 {\n return x + y;\n}\n\npub fn main() !void {\n const result = add(34, 16);\n std.debug.print(\"Result: {d}\\n\", .{result});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 50\n```\n\n\n:::\n:::\n\n\n\n\n\nYou could also achieve the exact same result by getting a file descriptor object to `stderr`,\nthen, creating a *writer* object to `stderr`, then, using the `print()` method of this\n*writer* object, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stderr = std.io.getStdErr().writer();\n// some more lines ...\ntry stderr.print(\"Result: {d}\", .{result});\n```\n:::\n\n\n\n\n\n\n## Debugging through debuggers\n\nAlthough *print debugging* is a valid and very useful strategy,\nmost programmers prefer to use a debugger to debug their programs.\nSince Zig is a low-level language, you can use either GDB (GNU Debugger),\nor LLDB (LLVM Project Debugger) as your debugger.\n\nBoth debuggers can work with Zig code, and it's a matter of taste here.\nYou choose the debugger of your preference, and you work with it.\nIn this book, I will use LLDB as my debugger in the examples.\n\n\n### Compile your source code in debug mode {#sec-compile-debug-mode}\n\nIn order to debug your program through a debugger, you must compile\nyour source code in `Debug` mode. Because when you compile your\nsource code in other modes (such as `Release`), the compiler usually\nstrips out some essential information that is used by the debugger\nto read and track your program, like PDB (*Program Database*) files.\n\nBy compiling your source code in `Debug` mode, you ensure that the debugger\nwill find the necessary information in your program to debug it.\nBy default, the compiler uses the `Debug` mode when compiling your code.\nHaving this in mind, when you compile your program with the `build-exe`\ncommand (which was described in @sec-compile-code), if you don't specify\nan explicit mode through the `-O` command-line [^oargument]\nargument, then, the compiler will compile your code in `Debug` mode.\n\n[^oargument]: See .\n\n\n### Let's debug a program\n\nAs an example, let's use LLDB to navigate and investigate the following\npiece of Zig code:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\nfn add_and_increment(a: u8, b: u8) u8 {\n const sum = a + b;\n const incremented = sum + 1;\n return incremented;\n}\n\npub fn main() !void {\n var n = add_and_increment(2, 3);\n n = add_and_increment(n, n);\n try stdout.print(\"Result: {d}!\\n\", .{n});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 13!\n```\n\n\n:::\n:::\n\n\n\n\nThere is nothing wrong with this program. But it's\na good start for us. First, we need to compile\nthis program with the `zig build-exe` command.\nFor this example, suppose that I have compiled the above\nZig code into a binary executable called `add_program`.\n\n```bash\nzig build-exe add_program.zig\n```\n\nNow, we can start LLDB with `add_program`, like this:\n\n```bash\nlldb add_program\n```\n\nFrom now on, LLDB is started, and you can know that I'm\nexecuting LLDB commands by looking at the prefix `(lldb)`.\nIf something is prefixed with `(lldb)`, then you know\nthat it's a LLDB command.\n\nThe first thing I will do, is to set a breakpoint at\nthe `main()` function, by executing `b main`.\nAfter that, I just start the execution of the program\nwith `run`.\nYou can see in the output below, that the execution\nstopped at the first line in the function `main()`, as we expected.\n\n```bash\n(lldb) b main\nBreakpoint 1: where = debugging`debug1.main + 22\n at debug1.zig:11:30, address = 0x00000000010341a6\n(lldb) run\nProcess 8654 launched: 'add_program' (x86_64)\nProcess 8654 stopped\n* thread #1, name = 'add_program',\n stop reason = breakpoint 1.1 frame #0: 0x10341a6\n add_program`debug1.main at add_program.zig:11:30\n 8 \t}\n 9\n 10 \tpub fn main() !void {\n-> 11 \t var n = add_and_increment(2, 3);\n 12 \t n = add_and_increment(n, n);\n 13 \t try stdout.print(\"Result: {d}!\\n\", .{n});\n 14 \t}\n```\n\nI can start navigating through the code, and checking the objects\nthat are being generated. If you are not familiar with the commands\navailable in LLDB, I recommend you to read the official documentation\nof the project[^lldb].\nYou can also look for cheat sheets, which quickly describes all commands\navailable for you[^lldb-quick-list].\n\n[^lldb]: \n[^lldb-quick-list]: .\n\nCurrently, we are in the first line at the `main()` function. In this line, we create\nthe `n` object, by executing the `add_and_increment()` function.\nTo execute the current line of code, and go to the next line, we can\nrun the `n` LLDB command. Let's execute this command.\n\nAfter we executed this line, we can also look at the value stored inside this `n` object\nby using the `p` LLDB command. The syntax for this command is `p `.\n\nIf we take a look at the value stored in the `n` object (`p n`),\nnotice that it stores the hexadecimal value `0x06`, which\nis the number 6 in decimal. We can also see that this value has a type of `unsigned char`,\nwhich is an unsigned 8-bit integer.\nWe have talked already about this in @sec-zig-strings, that `u8` integers in Zig are equivalent\nto the C data type `unsigned char`.\n\n\n\n```bash\n(lldb) n\nProcess 4798 stopped\n* thread #1, name = 'debugging',\n stop reason = step over frame #0: 0x10341ae\n debugging`debug1.main at debug1.zig:12:26\n 9\n 10 \tpub fn main() !void {\n 11 \t var n = add_and_increment(2, 3);\n-> 12 \t n = add_and_increment(n, n);\n 13 \t try stdout.print(\"Result: {d}!\\n\", .{n});\n 14 \t}\n(lldb) p n\n(unsigned char) $1 = '\\x06'\n```\n\nNow, on the next line of code, we are executing the `add_and_increment()` function once again.\nWhy not step inside this function? Shall we? We can do that, by executing the `s` LLDB command.\nNotice in the example below that, after executing this command, we have entered into the context of the\n`add_and_increment()` function.\n\nAlso notice in the example below that, I have walked two more lines in the function's body, then,\nI execute the `frame variable` LLDB command, to see at once, the value stored in each of the variables\nthat were created inside the current scope.\n\nYou can see in the output below that, the object `sum` stores the value `\\f`,\nwhich represents the *form feed* character. This character in the ASCII table,\ncorresponds to the hexadecimal value `0x0C`, or, in decimal, the number 12.\nSo, this means that the result of the expression `a + b` executed at line\n5, resulted in the number 12.\n\n```bash\n(lldb) s\nProcess 4798 stopped\n* thread #1, name = 'debugging',\n stop reason = step in frame #0: 0x10342de\n debugging`debug1.add_and_increment(a='\\x02', b='\\x03')\n at debug1.zig:4:39\n-> 4 \tfn add_and_increment(a: u8, b: u8) u8 {\n 5 \t const sum = a + b;\n 6 \t const incremented = sum + 1;\n 7 \t return incremented;\n(lldb) n\n(lldb) n\n(lldb) frame variable\n(unsigned char) a = '\\x06'\n(unsigned char) b = '\\x06'\n(unsigned char) sum = '\\f'\n(unsigned char) incremented = '\\x06'\n```\n\n\n\n## How to investigate the data type of your objects\n\nSince Zig is a strongly-typed language, the data types associated with your objects\nare very important for your program. So, debugging the data types associated\nwith your objects might be important to understand bugs and errors in your program.\n\nWhen you walk through your program with a debugger, you can inspect the types of\nyour objects by simply printing them to the console, with the LLDB `p` command.\nBut you also have alternatives embedded in the language itself to access the data\ntypes of your objects.\n\nIn Zig, you can retrieve the data type of an object, by using the built-in function\n`@TypeOf()`. Just apply this function over the object, and you get access to\nthe data type of the object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst expect = std.testing.expect;\n\npub fn main() !void {\n const number: i32 = 5;\n try expect(@TypeOf(number) == i32);\n try stdout.print(\"{any}\\n\", .{@TypeOf(number)});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ni32\n```\n\n\n:::\n:::\n\n\n\n\nThis function is similar to the `type()` built-in function from Python,\nor, the `typeof` operator in Javascript.\n", + "supporting": [ + "02-debugging_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/03-structs/execute-results/html.json b/_freeze/Chapters/03-structs/execute-results/html.json index 2629908d..8781660b 100644 --- a/_freeze/Chapters/03-structs/execute-results/html.json +++ b/_freeze/Chapters/03-structs/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "ddf3054f897e82f090f3aa7c5890ec78", + "hash": "ec9ff8aaff4376d4eab0dd3ee150d725", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `role`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object has type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e. four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n```\n:::\n\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It is important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n else => {\n try stdout.print(\n \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n );\n },\n}\n```\n:::\n\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n```\n:::\n\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function gets executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, is worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression get's executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that get's printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n // code to execute\n}\n```\n:::\n\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It is the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e. the logical test is equal to false), the function raises an assertion error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e. constant) object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n x = x + 2;\n return x;\n}\n\npub fn main() !void {\n const y = add2(4);\n std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n x = x + 2;\n ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e. `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n const d: u32 = 2;\n x.* = x.* + d;\n}\n\npub fn main() !void {\n var x: u32 = 4;\n add2(&x);\n std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n pub fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n pub fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nEvery method that you declare in your struct that is marked with the keyword `pub`,\nbecomes a public method of this particular struct.\n\nSo every method that you create inside your struct, is, at first, a private method\nof that struct. Meaning that, this method can only be called from within this\nstruct. But, if you mark this method as public, with the keyword `pub`, then,\nyou can call the method directly from an instance of the `User` struct.\n\nIn other words, the functions marked by the keyword `pub`\nare members of the public API of that struct.\nFor example, if I did not mark the `print_name()` method as public,\nthen, I could not execute the line `u.print_name()`. Because I would\nnot be authorized to call this method directly in my code.\n\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n```\n:::\n\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt is not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n```\n:::\n\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods are affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e. changes the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n```\n:::\n\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it is not about the input object, it is about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special part in this place. More specifically, it is\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and it is\ntrying to infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n```\n:::\n\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e. we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it is explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file9f8940318094.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe, and there are situations where these assumptions do not hold. For example,\nwhen casting an integer value into a float value, or vice-versa, it is not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file9f8954828844.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e. they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file9f8944ca02e1.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e. a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" get's executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object get's saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n .{ .max_threads = num_threads }\n);\n```\n:::\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `role`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object has type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e., four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n```\n:::\n\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It's important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n else => {\n try stdout.print(\n \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n );\n },\n}\n```\n:::\n\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n```\n:::\n\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function gets executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, it's worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression gets executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that gets printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n // code to execute\n}\n```\n:::\n\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It's the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e., the logical test is equal to false), the function raises an assertion error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e., constant) object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n x = x + 2;\n return x;\n}\n\npub fn main() !void {\n const y = add2(4);\n std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n x = x + 2;\n ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e., `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n const d: u32 = 2;\n x.* = x.* + d;\n}\n\npub fn main() !void {\n var x: u32 = 4;\n add2(&x);\n std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n pub fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n pub fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nEvery method that you declare in your struct that is marked with the keyword `pub`,\nbecomes a public method of this particular struct.\n\nSo every method that you create inside your struct, is, at first, a private method\nof that struct. Meaning that, this method can only be called from within this\nstruct. But, if you mark this method as public, with the keyword `pub`, then,\nyou can call the method directly from an instance of the `User` struct.\n\nIn other words, the functions marked by the keyword `pub`\nare members of the public API of that struct.\nFor example, if I did not mark the `print_name()` method as public,\nthen, I could not execute the line `u.print_name()`. Because I would\nnot be authorized to call this method directly in my code.\n\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n```\n:::\n\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt's not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n```\n:::\n\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods are affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e., changes the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n```\n:::\n\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it's not about the input object, it's about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special part in this place. More specifically, it's\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and trying\nto infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n```\n:::\n\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e., we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it's explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file79ce58134f59.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe. There are many situations where these assumptions do not hold. For example,\n\nwhen casting an integer value into a float value, or vice-versa, it's not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file79ce286cee5b.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e., they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file79ce1e7313c8.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e., a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" gets executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object gets saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n .{ .max_threads = num_threads }\n);\n```\n:::\n", + "supporting": [ + "03-structs_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/03-unittests/execute-results/html.json b/_freeze/Chapters/03-unittests/execute-results/html.json index 37cb076d..7e5990dc 100644 --- a/_freeze/Chapters/03-unittests/execute-results/html.json +++ b/_freeze/Chapters/03-unittests/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "28d3cb0fae2775c98b5945221b3f555c", + "hash": "555cc5c67a26414e89a3511dba578c1d", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Unit tests {#sec-unittests}\n\nIn this chapter, I want to dive in on how unit tests are done in\nZig. We are going to talk about what is the testing workflow in Zig, and\nalso, about the `test` command from the `zig` compiler.\n\n\n## Introducing the `test` block\n\nIn Zig, unit tests are written inside a `test` declaration, or, how I prefer to call it, inside a `test` block.\nEvery `test` block is written by using the keyword `test`.\nYou can optionally use a string literal to write a label, which is responsible for identifying\nthe specific group of unit tests that you are writing inside this specific `test` block.\n\nIn the example below, we are testing if the sum of two objects (`a` and `b`)\nis equal to 4. The `expect()` function from the Zig Standard Library\nis a function that receives a logical test as input. If this logical test\nresults in `true`, then, the test passes. But if it results\nin `false`, then, the test fails.\n\nYou can write any Zig code you want inside a `test` block.\nPart of this code might be some necessary commands to setup your testing\nenvironment, or just initializing some objects that you need to use\nin your unit tests.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest \"testing simple sum\" {\n const a: u8 = 2;\n const b: u8 = 2;\n try expect((a + b) == 4);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filea5b06c1ec326.test.testing simple sum...OKA\n All 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\nYou can have multiple `test` blocks written on the same Zig module.\nAlso, you can mix `test` blocks with your source code, with no problems\nor consequences. If you mix `test` blocks with your normal source code,\nwhen you execute the `build`, `build-exe`, `build-obj` or `build-lib` commands from the\n`zig` compiler that we exposed at @sec-compile-code, these `test` blocks are automatically\nignored by the compiler.\n\nIn other words, the `zig` compiler builds and execute your unit tests only\nwhen you ask it to. By default, the compiler always ignore `test`\nblocks written in your Zig modules. The compiler normally checks only if\nthere are any syntax errors in these `test` blocks.\n\nIf you take a look at the source code for most of the files present in the\nZig Standard Library[^zig-std-lib], you can see that the `test` blocks\nare written together with the normal source code of the library.\nYou can see this for example, at the [`array_list` module](https://github.com/ziglang/zig/blob/master/lib/std/array_list.zig)[^zig-array].\nSo, the standard that the Zig developers decided to adopt\nis to keep their unit tests together with the source code\nof the functionality that they are testing.\n\nEach programmer might have a different opinion on this.\nSome of them might prefer to keep unit tests separate from the actual\nsource code of their application. If that is your case, you can\nsimply create a separate `tests` folder in your project, and\nstart writing Zig modules that contains only unit tests (as you would normally do\non a Python project with `pytest`, for example), and everything will work fine.\nIt boils down to which is your preference here.\n\n[^zig-std-lib]: \n[^zig-array]: \n\n\n## How to run your tests\n\nIf the `zig` compiler ignores any `test` block by default, how can\nyou compile and run your unit tests? The answer is the `test` command from\nthe `zig` compiler. By running the `zig test` command, the compiler will\nfind every instance of a `test` block in your Zig modules, and, it will\ncompile and run the unit tests that you wrote.\n\n\n```bash\nzig test simple_sum.zig\n```\n\n```\n1/1 simple_sum.test.testing simple sum... OK\nAll 1 tests passed.\n```\n\n\n## Testing memory allocations\n\nOne of the advantages of Zig is that it offers great tools\nthat help us, programmers, to avoid (but also detect) memory problems, such as\nmemory leaks and double-frees. The `defer` keyword\nis especially helpful in this regard.\n\nWhen developing your source code, you, the programmer, is responsible for making\nsure that your code do not produce such problems. However,\nyou can also use a special type of an allocator object in Zig\nthat is capable of automatically detecting such problems for you.\nThis is the `std.testing.allocator` object.\nThis allocator object offers some basic memory safety detection\nfeatures, which are capable of detecting memory leaks.\n\nAs we described at @sec-heap, to allocate memory on the heap, you need\nto use an allocator object, and your functions that use these objects to allocate memory\non the heap, should receive an allocator object as one of its inputs.\nEvery memory on the heap that you allocate using these allocator objects,\nmust also be freed using this same allocator object.\n\nSo, if you want to test the memory allocations performed by your functions,\nand make sure that you don't have problems in these allocations, you can simply\nwrite unit tests for these functions, where you provide the\n`std.testing.allocator` object as input to these functions.\n\nLook at the example below, where I'm defining a function that clearly causes\na memory leak. Because we allocate memory, but, at the same time,\nwe do not free this allocated memory at any point. So, when the function\nreturns, we lose the reference to the `buffer` object, which contains\nthe allocated memory, and, as a result, we can no longer free this memory.\n\nNotice that, inside a `test` block I execute this function with\nthe `std.testing.allocator`. The allocator object was capable\nof looking deeper in our program, and detecting the memory leak. As a result,\nthis allocator object returns an error message of \"memory leaked\", and also,\na stack trace showing the exact point where the memory was leaked.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nfn some_memory_leak(allocator: Allocator) !void {\n const buffer = try allocator.alloc(u32, 10);\n _ = buffer;\n // Return without freeing the\n // allocated memory\n}\n\ntest \"memory leak\" {\n const allocator = std.testing.allocator;\n try some_memory_leak(allocator);\n}\n```\n:::\n\n\n\n\n```\nTest [1/1] leak_memory.test.memory leak...\n [gpa] (err): memory address 0x7c1fddf39000 leaked: \n./ZigExamples/debugging/leak_memory.zig:4:39: 0x10395f2\n const buffer = try allocator.alloc(u32, 10);\n ^\n./ZigExamples/debugging/leak_memory.zig:12:25: 0x10398ea\n try some_memory_leak(allocator);\n\n... more stack trace\n```\n\n\n## Testing errors\n\nOne common style of unit tests are those that look for\nspecific errors in your functions. In other words, you write\na unit test that tries to assert if a specific function call\nreturns any error, or a specific type of error.\n\nIn C++ you would normally write this style of unit tests using, for example,\nthe functions `REQUIRE_THROWS()` or `CHECK_THROWS()` from the [`Catch2` test framework](https://github.com/catchorg/Catch2/tree/devel)[^catch2].\nIn the case of a Python project, you would probably use the\n[`raises()` function from `pytest`](https://docs.pytest.org/en/7.1.x/reference/reference.html#pytest-raises)[^pytest].\nWhile in Rust, you would probably use `assert_eq!()` in conjunction with `Err()`.\n\n[^pytest]: \n[^catch2]: \n\n\nBut in Zig, we use the `expectError()` function, from the `std.testing` module.\nWith this function, you can test if a specific function call returns the exact\ntype of error that you expect it to return. To use this function, you first write\n`try expectError()`. Then, on the first argument, you provide the type of error that you\nare expecting from the function call. Then, on the second argument, you write\nthe function call that you expect to fail.\n\nThe code example below demonstrates such type of unit test in Zig.\nNotice that, inside the function `alloc_error()` we are allocating\n100 bytes of memory, or, an array of 100 elements, for the object `ibuffer`. However,\nin the `test` block, we are using the `FixedBufferAllocator()`\nallocator object, which is limited to 10 bytes of space, because\nthe object `buffer`, which we provided to the allocator object,\nhave only 10 bytes of space.\n\nThat is why, the `alloc_error()` function raises an `OutOfMemory` error\non this case.\nBecause this function is trying to allocate more space than the allocator\nobject allows.\nSo, in essence, we are testing for a specific type of error,\nwhich is `OutOfMemory`. If the `alloc_error()` function returns any other type of error,\nthen, the `expectError()` function would make the entire test fail.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst expectError = std.testing.expectError;\nfn alloc_error(allocator: Allocator) !void {\n var ibuffer = try allocator.alloc(u8, 100);\n defer allocator.free(ibuffer);\n ibuffer[0] = 2;\n}\n\ntest \"testing error\" {\n var buffer: [10]u8 = undefined;\n var fba = std.heap.FixedBufferAllocator.init(&buffer);\n const allocator = fba.allocator();\n try expectError(error.OutOfMemory, alloc_error(allocator));\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filea5b059c00874.test.testing error...OKAll 1 \n tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## Testing simple equalities\n\nIn Zig, there are some different ways you can test for an equality.\nYou already saw that we can use `expect()` with the logical operator `==`\nto essentially reproduce an equality test. But we also have\nsome other helper functions that you should know about, especially\n`expectEqual()`, `expectEqualSlices()` and `expectEqualStrings()`.\n\n\nThe `expectEqual()` function, as the name suggests, is a classic\ntest equality function. It receives two objects as input. The first\nobject is the value that you expect to be in the second object.\nWhile second object is the object you have, or, the object that your application\nproduced as result. So, with `expectEqual()` you are essentially\ntesting if the values stored inside these two objects\nare equal or not.\n\nYou can see in the example below that, the test performed by\n`expectEqual()` failed. Because the objects `v1` and `v2` contain\ndifferent values in them.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"values are equal?\" {\n const v1 = 15;\n const v2 = 18;\n try std.testing.expectEqual(v1, v2);\n}\n```\n:::\n\n\n\n\n```\n1/1 ve.test.values are equal?...\n expected 15, found 18\n FAIL (TestExpectedEqual)\nve.zig:5:5: test.values are equal? (test)\n try std.testing.expectEqual(v1, v2);\n ^\n0 passed; 0 skipped; 1 failed.\n```\n\n\nAlthough useful, the `expectEqual()` function does not work with arrays.\nFor testing if two arrays are equal, you should use the `expectEqualSlices()`\nfunction instead. This function have three arguments. First, you provide\nthe data type contained in both arrays that you are trying to compare.\nWhile the second and third arguments corresponds to the array objects that you want to compare.\n\nIn the example below, we are using this function to test if two array\nobjects (`array1` and `array2`) are equal or not. Since they\nare in fact equal, the unit test passed with no errors.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"arrays are equal?\" {\n const array1 = [3]u32{1, 2, 3};\n const array2 = [3]u32{1, 2, 3};\n try std.testing.expectEqualSlices(\n u32, &array1, &array2\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filea5b054e42b80.test.arrays are equal?...OKAl\n ll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\nAt last, you might also want to use the `expectEqualStrings()` function.\nAs the name suggests, you can use this function to test if two strings\nare equal or not. Just provide the two string objects that you want to compare,\nas inputs to the function.\n\nIf the function finds any existing differences between the two strings,\nthen, the function will raise an error, and also, print an error message\nthat shows the exact difference between the two string objects provided,\nas the example below demonstrates:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"strings are equal?\" {\n const str1 = \"hello, world!\";\n const str2 = \"Hello, world!\";\n try std.testing.expectEqualStrings(\n str1, str2\n );\n}\n```\n:::\n\n\n\n\n```\n1/1 t.test.strings are equal?... \n====== expected this output: =========\nhello, world!␃\n======== instead found this: =========\nHello, world!␃\n======================================\nFirst difference occurs on line 1:\nexpected:\nhello, world!\n^ ('\\x68')\nfound:\nHello, world!\n^ ('\\x48')\n```\n\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Unit tests {#sec-unittests}\n\nIn this chapter, I want to dive in on how unit tests are done in\nZig. We are going to talk about what is the testing workflow in Zig, and\nalso, about the `test` command from the `zig` compiler.\n\n\n## Introducing the `test` block\n\nIn Zig, unit tests are written inside a `test` declaration, or, how I prefer to call it, inside a `test` block.\nEvery `test` block is written by using the keyword `test`.\nYou can optionally use a string literal to write a label, which is responsible for identifying\nthe specific group of unit tests that you are writing inside this specific `test` block.\n\nIn the example below, we are testing if the sum of two objects (`a` and `b`)\nis equal to 4. The `expect()` function from the Zig Standard Library\nis a function that receives a logical test as input. If this logical test\nresults in `true`, then, the test passes. But if it results\nin `false`, then, the test fails.\n\nYou can write any Zig code you want inside a `test` block.\nPart of this code might be some necessary commands to setup your testing\nenvironment, or just initializing some objects that you need to use\nin your unit tests.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest \"testing simple sum\" {\n const a: u8 = 2;\n const b: u8 = 2;\n try expect((a + b) == 4);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file81c21dbf264e.test.testing simple sum...OKA\n All 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\nYou can have multiple `test` blocks written on the same Zig module.\nAlso, you can mix `test` blocks with your source code, with no problems\nor consequences. If you mix `test` blocks with your normal source code,\nwhen you execute the `build`, `build-exe`, `build-obj` or `build-lib` commands from the\n`zig` compiler that we exposed in @sec-compile-code, these `test` blocks are automatically\nignored by the compiler.\n\nIn other words, the `zig` compiler builds and execute your unit tests only\nwhen you ask it to. By default, the compiler always ignore `test`\nblocks written in your Zig modules. The compiler normally checks only if\nthere are any syntax errors in these `test` blocks.\n\nIf you take a look at the source code for most of the files present in the\nZig Standard Library[^zig-std-lib], you can see that the `test` blocks\nare written together with the normal source code of the library.\nYou can see this for example, at the [`array_list` module](https://github.com/ziglang/zig/blob/master/lib/std/array_list.zig)[^zig-array].\nSo, the standard that the Zig developers decided to adopt\nis to keep their unit tests together with the source code\nof the functionality that they are testing.\n\nEach programmer might have a different opinion on this.\nSome of them might prefer to keep unit tests separate from the actual\nsource code of their application. If that is your case, you can\nsimply create a separate `tests` folder in your project, and\nstart writing Zig modules that contains only unit tests (as you would normally do\non a Python project with `pytest`, for example), and everything will work fine.\nIt boils down to which is your preference here.\n\n[^zig-std-lib]: \n[^zig-array]: \n\n\n## How to run your tests\n\nIf the `zig` compiler ignores any `test` block by default, how can\nyou compile and run your unit tests? The answer is the `test` command from\nthe `zig` compiler. By running the `zig test` command, the compiler will\nfind every instance of a `test` block in your Zig modules, and, it will\ncompile and run the unit tests that you wrote.\n\n\n```bash\nzig test simple_sum.zig\n```\n\n```\n1/1 simple_sum.test.testing simple sum... OK\nAll 1 tests passed.\n```\n\n\n## Testing memory allocations\n\nOne of the advantages of Zig is that it offers great tools\nthat help us, programmers, to avoid (but also detect) memory problems, such as\nmemory leaks and double-frees. The `defer` keyword\nis especially helpful in this regard.\n\nWhen developing your source code, you, the programmer, are responsible for making\nsure that your code does not produce such problems. However,\nyou can also use a special type of an allocator object in Zig\nthat is capable of automatically detecting such problems for you.\nThis is the `std.testing.allocator` object.\nThis allocator object offers some basic memory safety detection\nfeatures, which are capable of detecting memory leaks.\n\nAs we described in @sec-heap, to allocate memory on the heap, you need\nto use an allocator object, and your functions that use these objects to allocate memory\non the heap, should receive an allocator object as one of its inputs.\nEvery memory on the heap that you allocate using these allocator objects,\nmust also be freed using this same allocator object.\n\nSo, if you want to test the memory allocations performed by your functions,\nand make sure that you don't have problems in these allocations, you can simply\nwrite unit tests for these functions, where you provide the\n`std.testing.allocator` object as input to these functions.\n\nLook at the example below, where I'm defining a function that clearly causes\na memory leak. Because we allocate memory, but, at the same time,\nwe do not free this allocated memory at any point. So, when the function\nreturns, we lose the reference to the `buffer` object, which contains\nthe allocated memory, and, as a result, we can no longer free this memory.\n\nNotice that, inside a `test` block I execute this function with\nthe `std.testing.allocator`. The allocator object was capable\nof looking deeper in our program, and detecting the memory leak. As a result,\nthis allocator object returns an error message of \"memory leaked\", and also,\na stack trace showing the exact point where the memory was leaked.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nfn some_memory_leak(allocator: Allocator) !void {\n const buffer = try allocator.alloc(u32, 10);\n _ = buffer;\n // Return without freeing the\n // allocated memory\n}\n\ntest \"memory leak\" {\n const allocator = std.testing.allocator;\n try some_memory_leak(allocator);\n}\n```\n:::\n\n\n\n\n```\nTest [1/1] leak_memory.test.memory leak...\n [gpa] (err): memory address 0x7c1fddf39000 leaked:\n./ZigExamples/debugging/leak_memory.zig:4:39: 0x10395f2\n const buffer = try allocator.alloc(u32, 10);\n ^\n./ZigExamples/debugging/leak_memory.zig:12:25: 0x10398ea\n try some_memory_leak(allocator);\n\n... more stack trace\n```\n\n\n## Testing errors\n\nOne common style of unit tests are those that look for\nspecific errors in your functions. In other words, you write\na unit test that tries to assert if a specific function call\nreturns any error, or a specific type of error.\n\nIn C++ you would normally write this style of unit tests using, for example,\nthe functions `REQUIRE_THROWS()` or `CHECK_THROWS()` from the [`Catch2` test framework](https://github.com/catchorg/Catch2/tree/devel)[^catch2].\nIn the case of a Python project, you would probably use the\n[`raises()` function from `pytest`](https://docs.pytest.org/en/7.1.x/reference/reference.html#pytest-raises)[^pytest].\nWhile in Rust, you would probably use `assert_eq!()` in conjunction with `Err()`.\n\n[^pytest]: \n[^catch2]: \n\n\nBut in Zig, we use the `expectError()` function, from the `std.testing` module.\nWith this function, you can test if a specific function call returns the exact\ntype of error that you expect it to return. To use this function, you first write\n`try expectError()`. Then, on the first argument, you provide the type of error that you\nare expecting from the function call. Then, on the second argument, you write\nthe function call that you expect to fail.\n\nThe code example below demonstrates such type of unit test in Zig.\nNotice that, inside the function `alloc_error()` we are allocating\n100 bytes of memory, or, an array of 100 elements, for the object `ibuffer`. However,\nin the `test` block, we are using the `FixedBufferAllocator()`\nallocator object, which is limited to 10 bytes of space, because\nthe object `buffer`, which we provided to the allocator object,\nhave only 10 bytes of space.\n\nThat is why, the `alloc_error()` function raises an `OutOfMemory` error\non this case.\nBecause this function is trying to allocate more space than the allocator\nobject allows.\nSo, in essence, we are testing for a specific type of error,\nwhich is `OutOfMemory`. If the `alloc_error()` function returns any other type of error,\nthen, the `expectError()` function would make the entire test fail.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst expectError = std.testing.expectError;\nfn alloc_error(allocator: Allocator) !void {\n var ibuffer = try allocator.alloc(u8, 100);\n defer allocator.free(ibuffer);\n ibuffer[0] = 2;\n}\n\ntest \"testing error\" {\n var buffer: [10]u8 = undefined;\n var fba = std.heap.FixedBufferAllocator.init(&buffer);\n const allocator = fba.allocator();\n try expectError(error.OutOfMemory, alloc_error(allocator));\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file81c24fea00d1.test.testing error...OKAll 1 \n tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## Testing simple equalities\n\nIn Zig, there are some different ways you can test for an equality.\nYou already saw that we can use `expect()` with the logical operator `==`\nto essentially reproduce an equality test. But we also have\nsome other helper functions that you should know about, especially\n`expectEqual()`, `expectEqualSlices()` and `expectEqualStrings()`.\n\n\nThe `expectEqual()` function, as the name suggests, is a classic\ntest equality function. It receives two objects as input. The first\nobject is the value that you expect to be in the second object.\nWhile second object is the object you have, or, the object that your application\nproduced as result. So, with `expectEqual()` you are essentially\ntesting if the values stored inside these two objects\nare equal or not.\n\nYou can see in the example below that, the test performed by\n`expectEqual()` failed. Because the objects `v1` and `v2` contain\ndifferent values in them.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"values are equal?\" {\n const v1 = 15;\n const v2 = 18;\n try std.testing.expectEqual(v1, v2);\n}\n```\n:::\n\n\n\n\n```\n1/1 ve.test.values are equal?...\n expected 15, found 18\n FAIL (TestExpectedEqual)\nve.zig:5:5: test.values are equal? (test)\n try std.testing.expectEqual(v1, v2);\n ^\n0 passed; 0 skipped; 1 failed.\n```\n\n\nAlthough useful, the `expectEqual()` function does not work with arrays.\nFor testing if two arrays are equal, you should use the `expectEqualSlices()`\nfunction instead. This function have three arguments. First, you provide\nthe data type contained in both arrays that you are trying to compare.\nWhile the second and third arguments corresponds to the array objects that you want to compare.\n\nIn the example below, we are using this function to test if two array\nobjects (`array1` and `array2`) are equal or not. Since they\nare in fact equal, the unit test passed with no errors.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"arrays are equal?\" {\n const array1 = [3]u32{1, 2, 3};\n const array2 = [3]u32{1, 2, 3};\n try std.testing.expectEqualSlices(\n u32, &array1, &array2\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file81c25513148.test.arrays are equal?...OKAll\n l 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\nAt last, you might also want to use the `expectEqualStrings()` function.\nAs the name suggests, you can use this function to test if two strings\nare equal or not. Just provide the two string objects that you want to compare,\nas inputs to the function.\n\nIf the function finds any existing differences between the two strings,\nthen, the function will raise an error, and also, print an error message\nthat shows the exact difference between the two string objects provided,\nas the example below demonstrates:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"strings are equal?\" {\n const str1 = \"hello, world!\";\n const str2 = \"Hello, world!\";\n try std.testing.expectEqualStrings(\n str1, str2\n );\n}\n```\n:::\n\n\n\n\n```\n1/1 t.test.strings are equal?...\n====== expected this output: =========\nhello, world!␃\n======== instead found this: =========\nHello, world!␃\n======================================\nFirst difference occurs on line 1:\nexpected:\nhello, world!\n^ ('\\x68')\nfound:\nHello, world!\n^ ('\\x48')\n```\n", + "supporting": [ + "03-unittests_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/04-http-server/execute-results/html.json b/_freeze/Chapters/04-http-server/execute-results/html.json index 8f509955..09b85ed5 100644 --- a/_freeze/Chapters/04-http-server/execute-results/html.json +++ b/_freeze/Chapters/04-http-server/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "3ea52d4cb7e3e92c83ca208ca4f62693", + "hash": "d35b08ad233c0b9a03e30bed4b1982f2", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 2 - Building a HTTP Server from scratch\n\nIn this chapter, I want to implement a new\nsmall project with you. This time, we are going\nto implement a basic HTTP Server from scratch.\n\nThe Zig Standard Library already have a HTTP Server\nimplemented, which is available at `std.http.Server`.\nBut again, our objective here in this chapter, is to implement\nit **from scratch**. So we can't use this server object available\nfrom the Zig Standard Library.\n\n## What is a HTTP Server?\n\nFirst of all, what is a HTTP Server?\nA HTTP server, as any other type of server, is essentially\na program that runs indefinitely, on an infinite loop, waiting for incoming connections\nfrom clients. Once the server receives an incoming connection, it will\naccept this connection, and it will send messages back-and-forth to the client\nthrough this connection.\n\nBut the messages that are transmitted inside this connection are in a\nspecific format. They are HTTP messages\n(i.e. messages that use the HTTP Protocol specification).\nThe HTTP Protocol is the backbone of the modern web.\nThe world wide web as we know it today, would not exist without the \nHTTP Protocol.\n\nSo, Web servers (which is just a fancy name to\nHTTP Servers) are servers that exchange HTTP messages with clients.\nAnd these HTTP servers and the HTTP Protocol specification\nare essential to the operation of the world wide web today.\n\nThat is the whole picture of the process.\nAgain, we have two subjects involved here, a server (which is\na program that is running indefinitely, waiting to receive incoming connections),\nand a client (which is someone that wants to connect to the server,\nand exchange HTTP messages with it).\n\nYou may find the material about the [HTTP Protocol available at the Mozilla MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)[^mdn-http]\n, a great resource for you to also look at. It gives you a great overview on how\nHTTP works, and what role the server plays in this matter.\n\n[^mdn-http]: .\n\n\n## How a HTTP Server works? {#sec-how-http-works}\n\nImagine a HTTP Server as if it were the receptionist of a large hotel. In a hotel,\nyou have a reception, and inside that reception there is a receptionist\nwaiting for customers to arrive. A HTTP Server is essentially a receptionist\nthat is indefinitely waiting for new customers (or, in the context of HTTP, new clients)\nto arrive in the hotel.\n\nWhen a customer arrives at the hotel, that customer starts a conversation with the\nreceptionist. He tells the receptionist how many days he wants to stay at the hotel.\nThen, the receptionist search for an available apartment. If there is an available apartment\nat the moment, the customer pays the hotel fees, then, he gets the keys to the apartment,\nand then, he goes to the apartment to rest.\n\nAfter this entire process of dealing with the customer (searching for available apartments,\nreceiving payment, handing over the keys), the receptionist goes back to what he was\ndoing earlier, which is to wait. Wait for new customers to arrive.\n\nThat is, in a nutshell, what a HTTP Server do. It waits for clients to connect to the\nserver. When a client attempts to connect to the server, the server accepts this connection,\nand it starts to exchange messages with the client through this connection.\nThe first message that happens inside this connection is always a message from the client\nto the server. This message is called the *HTTP Request*.\n\nThis HTTP Request is a HTTP message that contains what\nthe client wants from the server. It is literally a request. The client\nthat connected to the server is asking this server to do something for him.\n\nThere are different \"types of request\" that a client can send to a HTTP Server.\nBut the most basic type of request, is when a client ask to the\nHTTP Server to serve (i.e. to send) some specific web page (which is a HTML file) to him.\nWhen you type `google.com` in your web browser, you are essentially sending a HTTP Request to Google's\nHTTP servers. This request is asking these servers to send the Google webpage to you.\n\nNonetheless, when the server receives this first message, the *HTTP Request*, it\nanalyzes this request, to understand: who the client is? What he wants the server to do?\nThis client has provided all the necessary information to perform the action that he\nasked? Etc.\n\nOnce the server understands what the client wants, he simply perform the action\nthat was requested, and, to finish the whole process, the server sends back\na HTTP message to the client, informing if the action performed was successful or not,\nand, at last, the server ends (or closes) the connection with the client.\n\nThis last HTTP message sent from the server to the client, is called the *HTTP Response*.\nBecause the server is responding to the action that was requested by the client.\nThe main objective of this response message is let the client know if the\naction requested was successful or not, before the server closes the connection.\n\n\n## How a HTTP server is normally implemented? {#sec-http-how-impl}\n\nLet's use the C language as an example. There are many materials\nteaching how to write a simple HTTP server in C code, like @jeffrey_http,\nor @nipun_http, or @eric_http.\nHaving this in mind, I will not show C code examples here, because you\ncan find them on the internet.\nBut I will describe the theory behind the necessary steps to create\nsuch HTTP server in C.\n\n\nIn essence, we normally implement a HTTP server in C by using WebSocket technology,\nwhich involves the following steps:\n\n1. Create a socket object.\n1. Bind a name (or more specifically, an address) to this socket object.\n1. Make this socket object to start listening and waiting for incoming connections.\n1. When a connection arrive, we accept this connection, and we exchange the HTTP messages (HTTP Request and HTTP Response).\n1. Then, we simply close this connection.\n\n\nA socket object is essentially a channel of communication.\nYou are creating a channel where people can send messages through.\nWhen you create a socket object, this object is not binded to any particular\naddress. This means that with this object you have a representation of a channel of communication\nin your hands. But this channel is not currently available, or, it is not currently accessible,\nbecause it do not have a known address where you can find it.\n\nThat is what the \"bind\" operation do. It binds a name (or more specifically, an address) to\nthis socket object, or, this channel of communication, so that it becomes available,\nor, accessible through this address. While the \"listen\" operation makes the socket object to\nlisten for incoming connections in this address. In other words, the \"listen\" operation\nmakes the socket to wait for incoming connections.\ncurrently\nNow, when a client actually attempts to connect to the server through the socket address\nthat we have specified, in order to establish this connection with the client,\nthe socket object needs to accept this incoming connection. Thus, when we\naccept an incoming connection, the client and the server become\nconnected to each other, and they can start reading or writing messages into this\nestablished connection.\n\nAfter we receive the HTTP Request from the client, analyze it, and send the HTTP Response\nto the client, we can then close the connection, and end this communication.\n\n\n## Implementing the server - Part 1\n\n### Creating the socket object {#sec-create-socket}\n\nLet's begin with creating the socket object for our server.\nJust to make things shorter, I will create this socket object in\na separate Zig module. I will name it `config.zig`.\n\nIn Zig, we can create a web socket using\nthe `std.posix.socket()` function, from the Zig Standard Library.\nAs I mentioned earlier at @sec-http-how-impl, every socket object that we create\nrepresents a communication channel, and we need to bind this channel to a specific address.\nAn \"address\" is defined as an IP address, or, more specifically, an IPv4 address^[It can be also an IPv6 address. But normally, we use a IPv4 address for that.].\nEvery IPv4 address is composed by two components. The first component is the host,\nwhich is a sequence of 4 numbers separated by dot characters (`.`) that identifies the machine used.\nWhile the second component is a port number, which identifies the specific\ndoor, or, the specific port to use in the host machine.\n\nThe sequence of 4 numbers (i.e. the host) identifies the machine (i.e. the computer itself) where\nthis socket will live in. Every computer normally have multiple \"doors\" available inside of him, because \nthis allows the computer to receive and work with multiple connections at the same time.\nHe simply use a single door for each connection. So the port number, is\nessentially a number that identifies the specific door in the computer that will be responsible\nfor receiving the connection. That is, it identifies the \"door\" in the computer that the socket will use\nto receive incoming connections.\n\nTo make things simpler, I will use an IP address that identifies our current machine in this example.\nThis means that, our socket object will reside on the same computer that we are currently using\n(this is also known as the \"localhost\") to write this Zig source code.\n\nBy convention, the IP address that identifies the \"localhost\", which is the current machine we\nare using, is the IP `127.0.0.1`. So, that is the IP\naddress we are going to use in our server. I can declare it in Zig\nby using an array of 4 integers, like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst localhost = [4]u8{ 127, 0, 0, 1 };\n_ = localhost;\n```\n:::\n\n\n\n\nNow, we need to decide which port number to use. By convention, there are some\nport numbers that are reserved, meaning that, we cannot use them for our own\npurposes, like the port 22 (which is normally used for SSH connections).\nFor TCP connections, which is our case here,\na port number is a 16-bit unsigned integer (type `u16` in Zig),\nthus ranging from 0 to 65535 [@wikipedia_port].\nSo, we can choose\na number from 0 to 65535 for our port number. In the \nexample of this book, I will use the port number 3490\n(just a random number).\n\n\nNow that we have these two informations at hand, I can\nfinally create our socket object, using the `std.posix.socket()` function.\nFirst, we use the host and the port number to create an `Address` object,\nwith the `std.net.Address.initIp4()` function, like in the example below.\nAfter that, I use this address object inside the `socket()` function\nto create our socket object.\n\nThe `Socket` struct defined below summarizes all the logic behind\nthis process. In this struct, we have two data members, which are:\n1) the address object; 2) and a stream object, which is\nthe object we will use to read and write the messages into any connection we establish.\n\nNotice that, inside the constructor method of this struct,\nwhen we create the socket object, we are using the `IPROTO.TCP` property as an input to\ntell the function to create a socket for TCP connections.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\nconst net = @import(\"std\").net;\n\npub const Socket = struct {\n _address: std.net.Address,\n _stream: std.net.Stream,\n\n pub fn init() !Socket {\n const host = [4]u8{ 127, 0, 0, 1 };\n const port = 3490;\n const addr = net.Address.initIp4(host, port);\n const socket = try std.posix.socket(\n addr.any.family,\n std.posix.SOCK.STREAM,\n std.posix.IPPROTO.TCP\n );\n const stream = net.Stream{ .handle = socket };\n return Socket{ ._address = addr, ._stream = stream };\n }\n};\n```\n:::\n\n\n\n\n\n### Listening and receiving connections\n\nRemember that we stored the `Socket` struct\ndeclaration that we built at @sec-create-socket inside a Zig module named `config.zig`.\nThis is why I imported this module into our main module (`main.zig`) in the example below, as the `SocketConf` object,\nto access the `Socket` struct.\n\nOnce we created our socket object, we can focus now on making this socket object\nlisten and receive new incoming connections. We do that, by calling the `listen()`\nmethod from the `Address` object that is contained inside the socket object, and then,\nwe call the `accept()` method over the result.\n\nThe `listen()` method from the `Address` object produces a server object,\nwhich is an object that will stay open and running indefinitely, waiting\nto receive an incoming connection. Therefore, if you try to run the code\nexample below, by calling the `run` command from the `zig` compiler,\nyou will notice that the programs keeps running indefinitely,\nwithout a clear end.\n\nThis happens, because the program is waiting for something to happen.\nIt is waiting for someone to try to connect to the address (`http://127.0.0.1:3490`) where\nthe server is running and listening for incoming connections. This is what\nthe `listen()` method do, it makes the socket to be active waiting for someone\nto connect.\n\nOn the other side, the `accept()` method is the function that establishes the connection\nwhen someone tries to connect to the socket. This means that, the `accept()` method\nreturns a new connection object as a result. And you can use this connection object\nto read or write messages from or to the client.\nFor now, we are not doing anything with this connection object.\nBut we are going to use it on the next section.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n try stdout.print(\"Server Addr: {any}\\n\", .{socket._address});\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n _ = connection;\n}\n```\n:::\n\n\n\n\nThis code example allows one single connection. In other words, the\nserver will wait for one incoming connection, and as soon as the\nserver is done with this first connection that it establishes, the\nprogram ends, and the server stops.\n\nThis is not the norm on the real world. Most people that write\na HTTP server like this, usually put the `accept()` method\ninside a `while` (infinite) loop, where if a connection\nis created with `accept()`, a new thread of execution is created to deal with\nthis new connection and the client. That is, real-world examples of HTTP Servers\nnormally rely on parallel computing to work.\n\nWith this design, the server simply accepts the connection,\nand the whole process of dealing with the client, and receiving\nthe HTTP Request, and sending the HTTP Response, all of this\nis done in the background, on a separate execution thread.\n\nSo, as soon as the server accepts the connection, and creates\nthe separate thread, the server goes back to what he was doing earlier,\nwhich is to wait indefinitely for a new connection to accept.\nHaving this in mind, the code example exposed above, is a\nserver that serves only a single client. Because the program\nterminates as soon as the connection is accepted.\n\n\n\n### Reading the message from the client {#sec-read-http-message}\n\nNow that we have a connection established, i.e. the connection\nobject that we created through the `accept()` function, we can now\nuse this connection object to read any messages that the client\nsend to our server. But we can also use it to send messages back\nto the client.\n\nThe basic idea is, if we **write** any data into this connection object,\nthen, we are sending data to the client, and if we **read** the data present in\nthis connection object, then, we are reading any data that the\nclient sent to us, through this connection object. So, just\nhave this logic in mind. \"Read\" is for reading messages from the client,\nand \"write\" is to send a message to the client.\n\nRemember from @sec-how-http-works that, the first thing that we need to do is to read the HTTP Request\nsent by the client to our server. Because it is the first message that happens\ninside the established connection, and, as a consequence, it is the first\nthing that we need to deal with.\n\nThat is why, I'm going to create a new Zig module in this small project, named `request.zig`\nto keep all functions related to the HTTP Request\ntogether. Then, I will create a new function named `read_request()` that will\nuse our connection object to read the message sent by the client,\nwhich is the HTTP Request.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Connection = std.net.Server.Connection;\npub fn read_request(conn: Connection,\n buffer: []u8) !void {\n const reader = conn.stream.reader();\n _ = try reader.read(buffer);\n}\n```\n:::\n\n\n\n\n\nThis function accepts a slice object which behaves as a buffer.\nThe `read_request()` function reads the message sent into\nthe connection object, and saves this message into this buffer object that\nwe have provided as input.\n\nNotice that I'm using the connection object that we created to read\nthe message from the client. I first access the `reader` object that lives inside the\nconnection object. Then, I call the `read()` method of this `reader` object\nto effectively read and save the data sent by the client into the buffer object\nthat we created earlier. I'm discarding the return value\nof the `read()` method, by assigning it to the underscore character (`_`),\nbecause this return value is not useful for us right now.\n\n\n\n## Looking at the current state of the program\n\n\nI think now is a good time to see how our program is currently working. Shall we?\nSo, the first thing I will do is to update the `main.zig` module in our small Zig project,\nso that the `main()` function call this new `read_request()` function that we have just created.\nI will also add a print statement at the end of the `main()` function,\njust so that you can see what the HTTP Request that we have just loaded into the buffer object\nlooks like.\n\nAlso, I'm creating the buffer object in the `main()` function, which will be\nresponsible for storing the message sent by the client, and, I'm also\nusing a `for` loop to initialize all fields of this buffer object to the number zero.\nThis is important to make sure that we don't have uninitialized memory in\nthis object. Because uninitialized memory may cause undefined behaviour in our program.\n\nSince the `read_request()` function should receive as input the buffer object as a slice object (`[]u8`),\nI am using the syntax `array[0..array.len]` to get access to a slice of this `buffer` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst Request = @import(\"request.zig\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n try stdout.print(\"Server Addr: {any}\\n\", .{socket._address});\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n var buffer: [1000]u8 = undefined;\n for (0..buffer.len) |i| {\n buffer[i] = 0;\n }\n _ = try Request.read_request(\n connection, buffer[0..buffer.len]\n );\n try stdout.print(\"{s}\\n\", .{buffer});\n}\n```\n:::\n\n\n\n\nNow, I'm going to execute this program, with the `run` command from the\n`zig` compiler. But remember, as we sad earlier, as soon as I execute this program, it will\nhang indefinitely, because the program is waiting for a client trying to\nconnect to the server.\n\nMore specifically, the program will pause at the line\nwith the `accept()` call. As soon as a client try to connect to the\nserver, then, the execution will \"unpause\", and the `accept()` function\nwill finally be executed to create the\nconnection object that we need, and the remaining of the program\nwill run.\n\nYou can see that at @fig-print-zigrun1. The message `Server Addr: 127.0.0.1:3490`\nis printed to the console, and the program is now waiting for an incoming connection.\n\n![A screenshot of running the program](./../Figures/print-zigrun1.png){#fig-print-zigrun1}\n\n\nWe can finally try to connect to this server, and there are several ways we can do this.\nFor example, we could use the following Python script:\n\n```python\nimport requests\nrequests.get(\"http://127.0.0.1:3490\")\n```\n\nOr, we could also open any web browser of our preference, and type\nthe URL `localhost:3490`. OBS: `localhost` is the same thing as the\nIP `127.0.0.1`. When you press enter, and your web browser go\nto this address, first, the browser will probably print a message\nsaying that \"this page isn't working\", and, then, it will\nprobably change to a new message saying that \"the site can't be\nreached\".\n\nYou get these \"error messages\" in the web browser, because\nit got no response back from the server. In other words, when the web\nbrowser connected to our server, it did send the HTTP Request through the established connection.\nThen, the web browser was expecting to receive a HTTP Response back, but\nit got no response from the server (we didn't implemented the HTTP Response logic yet).\n\nBut that is okay. We have achieved the result that we wanted for now,\nwhich is to connect to the server, and see the HTTP Request\nthat was sent by the web browser (or by the Python script)\nto the server.\n\nIf you comeback to the console that you left open\nwhen you have executed the program, you will see that the\nprogram finished its execution, and, a new message is\nprinted in the console, which is the actual HTTP Request\nmessage that was sent by the web browser to the server.\nYou can see this message at @fig-print-zigrun2.\n\n![A screenshot of the HTTP Request sent by the web browser](./../Figures/print-zigrun2.png){#fig-print-zigrun2}\n\n\n\n\n## Learning about Enums in Zig {#sec-enum}\n\nEnums structures are available in Zig through the `enum` keyword.\nAn enum (short for \"enumeration\") is a special structure that represents a group of constant values.\nSo, if you have a variable which can assume a short and known\nset of values, you might want to associate this variable to an enum structure,\nto make sure that this variable only assumes a value from this set.\n\nA classic example for enums are primary colors. If for some reason, your program\nneeds to represent one of the primary colors, you can create an enum\nthat represents one of these colors.\nIn the example below, we are creating the enum `PrimaryColorRGB`, which\nrepresents a primary color from the RGB color system. By using this enum,\nI am guaranteed that the `acolor` object for example, will contain\none of these three values: `RED`, `GREEN` or `BLUE`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst PrimaryColorRGB = enum {\n RED, GREEN, BLUE\n};\nconst acolor = PrimaryColorRGB.RED;\n_ = acolor;\n```\n:::\n\n\n\n\nIf for some reason, my code tries to save in `acolor`,\na value that is not in this set, I will get an error message\nwarning me that a value such as \"MAGENTA\" do not exist\ninside the `PrimaryColorRGB` enum.\nThen I can easily fix my mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst acolor = PrimaryColorRGB.MAGENTA;\n```\n:::\n\n\n\n\n```\ne1.zig:5:36: error: enum 'PrimaryColorRGB' has\n no member named 'MAGENTA':\n const acolor = PrimaryColorRGB.MAGENTA;\n ^~~~~~~\n```\n\nBehind the hood, enums in Zig work the same way that enums\nwork in C. Each enum value is essentially represented as an integer.\nThe first value in the set is represented as zero,\nthen, the second value is one, ... etc.\n\nOne thing that we are going to learn on the next section is that\nenums can have methods in them. Wait... What? This is amazing!\nYes, enums in Zig are similar to structs, and they can have\nprivate and public methods inside them.\n\n\n\n\n\n\n\n## Implementing the server - Part 2\n\nNow, on this section, I want to focus on parsing\nthe HTTP Request that we received from the client.\nHowever, to effectively parse a HTTP Request message, we first need to understand its\nstructure.\nIn summary, a HTTP Request is a text message that is divided into 3 different\nsections (or parts):\n\n- The top-level header indicating the method of the HTTP Request, the URI, and the HTTP version used in the message.\n- A list of HTTP Headers.\n- The body of the HTTP Request.\n\n### The top-level header\n\nThe first line of text in a HTTP Request always come with the three most essential\ninformation about the request. These three key attributes of the HTTP Request\nare separated by a simple space in this first line of the request.\nThe first information is the HTTP method that is being\nused in the request, second, we have the URI to which this HTTP Request is being sent to,\nand third, we have the version of the HTTP protocol that is being used in this HTTP Request.\n\nIn the snippet below, you can find an example of this first line in a HTTP Request.\nFirst, we have the HTTP method of this request (`GET`). Many programmers\nrefer to the URI component (`/users/list`) as the \"API endpoint\" to which the HTTP Request\nis being sent to. In the context of this specific request, since it is a GET request,\nyou could also say that the URI component is the path to the resource we want to access,\nor, the path to the document (or the file) that we want to retrieve from the server.\n\n```\nGET /users/list HTTP/1.1\n```\n\nAlso, notice that this HTTP Request is using the version 1.1 of the HTTP protocol,\nwhich is the most popular version of the protocol used in the web.\n\n\n\n### The list of HTTP headers\n\nMost HTTP Requests also include a section of HTTP Headers,\nwhich is just a list of attributes or key-value pairs associated with this\nparticular request. This section always comes right after the \"top-level header\" of the request.\n\nFor our purpose in this chapter, which is to build a simple HTTP Server,\nwe are going to ignore this section of the HTTP Request, for simplicity.\nBut most HTTP servers that exist in the wild parses and use these\nHTTP headers to change the way that the server responds to the request\nsent by the client.\n\nFor example, many requests we encounter in the real-world comes with\na HTTP header called `Accept`. In this header, we find a list of [MIME types](https://en.wikipedia.org/wiki/Media_type)[^mime].\nThis list indicates the file formats that the client can read, or parse, or interpret.\nIn other words, you also interpret this header as the client saying the following phrase\nto the server: \"Hey! Look, I can read only HTML documents, so please, send me back\na document that is in a HTML format.\".\n\n[^mime]: .\n\nIf the HTTP server can read and use this `Accept` header, then, the server can identify\nwhich is the best file format for the document to be sent to the client. Maybe the HTTP server have\nthe same document in multiple formats, for example, in JSON, in XML, in HTML and in PDF,\nbut the client can only understand documents in the HTML format. That is the purpose\nof this `Accept` header.\n\n\n### The body\n\nThe body comes after the list of HTTP headers, and it is an optional section of the HTTP Request, meaning that, not\nall HTTP Request will come with a body in it. For example, every HTTP Request that uses the\nGET method usually do not come with a body.\n\nBecause a GET request is used to request data, instead of sending it to the server.\nSo, the body section is more related to the POST method, which is a method that involves\nsending data to the server, to be processed and stored.\n\nSince we are going to support only the GET method in this project, it means that\nwe also do not need to care about the body of the request.\n\n\n\n### Creating the HTTP Method enum\n\nEvery HTTP Request comes with a explicit method. The method used in a HTTP Request\nis identified by one these words:\n\n- GET;\n- POST;\n- OPTIONS;\n- PATCH;\n- DELETE;\n- and some other methods.\n\nEach HTTP method is used for a specific type of task. The POST method for example is normally\nused to post some data into the destination. In other words, it is used\nto send some data to the HTTP server, so that it can be processed and stored by the server.\n\nAs another example, the GET method is normally used to get content from the server.\nIn other words, we use this method whenever we want the server to send some\ncontent back to us. It can be any type of content. It can be a web page,\na document file, or some data in a JSON format.\n\nWhen a client sends a POST HTTP Request, the HTTP Response sent by the server normally have the sole purpose of\nletting the client know if the server processed and stored the data successfully.\nIn contrast, when the server receives a GET HTTP Request, then, the server sends the content\nthat the client asked for in the HTTP Response itself. This demonstrates that the method associated\nwith the HTTP Request changes a lot on the dynamics and the roles that each party\nplays in the whole process.\n\nSince the HTTP method of the HTTP Request is identified by this very small and specific\nset of words, it would be interesting to create an enum structure to represent a HTTP method.\nThis way, we can easily check if the HTTP Request we receive from the client is a\nHTTP method that we currently support in our small HTTP server project.\n\nThe `Method` structure below represents this enumeration.\nNotice that, for now, only the GET HTTP method is included in this\nenumeration. Because, for the purpose of this chapter, I want to\nimplement only the GET HTTP method. That is why I am not\nincluding the other HTTP methods in this enumeration.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Method = enum {\n GET\n};\n```\n:::\n\n\n\n\n\nNow, I think we should add two methods to this enum structure. One method is `is_supported()`,\nwhich will be a function that returns a boolean value, indicating if the input HTTP method is supported\nor not by our HTTP Server. The other is `init()`, which is a constructor function that takes a string as input,\nand tries to convert it into a `Method` value.\n\n\nBut in order to build these functions, I will use a functionality from the Zig Standard Library, called\n`StaticStringMap()`. This function allows us to create a simple map from strings to enum values.\nIn other words, we can use this map structure to map a string to the respective enum value.\nTo some extent, this specific structure from the standard library works almost like a \"hashtable\" structure,\nand it is optimized for small sets of words, or, small sets of keys, which is our case here.\nWe are going to talk more about hashtables in Zig at @sec-maps-hashtables.\n\nTo use this \"static string map\" structure, you have to import it from the `std.static_string_map` module\nof the Zig Standard Library. Just to make things shorter and easier to type, I am going to import this\nfunction through a different and shorter name (`Map`).\n\nWith `Map()` imported, we can just apply this function over the enum structure\nthat we are going to use in the resulting map. In our case here, it is the `Method` enum structure\nthat we declared at the last code example. Then, I call the `initComptime()` method with the\nmap, i.e. the list of key-value pairs that we are going to use.\n\nYou can see in the example below that I wrote this map using multiple anonymous struct literals.\nInside the first (or \"top-level\") struct literal, we have a list (or a sequence) of struct literals.\nEach struct literal in this list represents a separate key-value pair. The first element (or the key)\nin each key-value pair should always be a string value. While the second element should\nbe a value from the enum structure that you have used inside the `Map()` function.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Map = std.static_string_map.StaticStringMap;\nconst MethodMap = Map(Method).initComptime(.{\n .{ \"GET\", Method.GET },\n});\n```\n:::\n\n\n\n\nTherefore, the `MethodMap` object is basically a `std::map` object from C++, or,\na `dict` object from Python. You can retrieve (or get) the enum value that\ncorresponds to a particular key, by using the `get()` method from the map\nobject. This method returns an optional value, so, the `get()` method might\nresult in a null value.\n\nWe can use this in our advantage to detect if a particular HTTP method is\nsupported or not in our HTTP server. Because, if the `get()` method returns null,\nit means that it did not found the method that we provided inside the `MethodMap` object, and,\nas a consequence, this method is not supported by our HTTP server.\n\nThe `init()` method below, takes a string value as input, and then, it simply passes this string value\nto the `get()` method of our `MethodMap` object. As consequence, we should get the enum value that corresponds\nto this input string.\n\nNotice in the example below that, the `init()` method returns either an error\n(which might happen if the `?` method returns `unreacheable`, checkout @sec-null-handling for more details)\nor a `Method` object as result. Since `GET` is currently the only value in our `Method` enum\nstructure, it means that, the `init()` method will most likely return the value `Method.GET` as result.\n\nAlso notice that, in the `is_supported()` method, we are using the optional value returned\nby the `get()` method from our `MethodMap` object. The if statement unwraps the optional value\nreturned by this method, and returns `true` in case this optional value is a not-null value.\nOtherwise, it simply returns `false`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Method = enum {\n GET,\n pub fn init(text: []const u8) !Method {\n return MethodMap.get(text).?;\n }\n pub fn is_supported(m: []const u8) bool {\n const method = MethodMap.get(m);\n if (method) |_| {\n return true;\n }\n return false;\n }\n};\n```\n:::\n\n\n\n\n\n\n\n\n\n\n### Writing the parse request function\n\nNow that we created the enum that represents our HTTP method,\nwe should start to write the function responsible for\nactually parsing the HTTP Request.\n\nThe first thing we can do, is to write a struct to represent the HTTP Request.\nTake the `Request` struct below as an example. It contains the three\nessential information from the \"top-level\" header (i.e. the first line)\nin the HTTP Request.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Request = struct {\n method: Method,\n version: []const u8,\n uri: []const u8,\n pub fn init(method: Method,\n uri: []const u8,\n version: []const u8) Request {\n return Request{\n .method = method,\n .uri = uri,\n .version = version,\n };\n }\n};\n```\n:::\n\n\n\n\n\nThe `parse_request()` function should receive a string as input. This input string\ncontains the entire HTTP Request message, and the parsing function should\nread and understand the individual parts of this message.\n\nNow, remember that for the purpose of this chapter, we care only about the first\nline in this message, which contains the \"top-level header\", or, the three essential attributes about the HTTP Request,\nwhich are the HTTP method used, the URI and the HTTP version.\n\nNotice that I use the function `indexOfScalar()` in `parse_request()`. This function from the\nZig Standard Library returns the first index where the scalar value that we provide\nhappens in a string. In this case, I'm looking at the first occurrence of the new line character (`\\n`).\nBecause once again, we care only about the first line in the HTTP Request message.\nThis is the line where we have the three information that we want to parse\n(version of HTTP, the HTTP method and the URI).\n\nTherefore, we are using this `indexOfScalar()` function\nto limit our parsing process to the first line in the message.\nIs also worth mentioning that, the `indexOfScalar()` function returns an optional value.\nThat is why I use the `orelse` keyword to provide an alternative value, in case\nthe value returned by the function is a null value.\n\nSince each of these three attributes are separated by a simple space, we\ncould use the function `splitScalar()` from the Zig Standard Library to split\nthe input string into sections by looking for every position that appears\na simple space. In other words, this `splitScalar()` function is equivalent\nto the `split()` method in Python, or, the `std::getline()` function from C++,\nor the `strtok()` function in C.\n\nWhen you use this `splitScalar()` function, you get an iterator as the result.\nThis iterator have a `next()` method that you can use to advance the iterator\nto the next position, or, to the next section of the splitted string.\nNote that, when you use `next()`, the method not only advances the iterator,\nbut it also returns a slice to the current section of the splitted\nstring as result.\n\nNow, if you want to get a slice to the current section of the splitted\nstring, but not advance the iterator to the next position, you can use\nthe `peek()` method. Both `next()` and `peek()` methods return an optional value, that is\nwhy I use the `?` method to unwrap these optional values.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn parse_request(text: []u8) Request {\n const line_index = std.mem.indexOfScalar(\n u8, text, '\\n'\n ) orelse text.len;\n var iterator = std.mem.splitScalar(\n u8, text[0..line_index], ' '\n );\n const method = try Method.init(iterator.next().?);\n const uri = iterator.next().?;\n const version = iterator.next().?;\n const request = Request.init(method, uri, version);\n return request;\n}\n```\n:::\n\n\n\n\n\nAs I described at @sec-zig-strings, strings in Zig are simply arrays of bytes in the language.\nSo, you will find lots of excellent utility functions to work directly with strings\ninside this `mem` module from the Zig Standard Library.\nWe have described some of these useful utility functions already\nat @sec-strings-useful-funs.\n\n\n\n### Using the parse request function\n\nNow that we wrote the function responsible for parsing the HTTP Request,\nwe can add the function call to `parse_request()` in\nthe `main()` function of our program.\n\nAfter that, is a good idea to test once again the state of our program.\nI execute this program again with the `run` command from the `zig` compiler,\nthen, I use my web browser to connect once again to the server through the URL `localhost:3490`, and finally,\nthe end result of our `Request` object is printed to the console.\n\nA quick observation, since I have used the `any` format specifier in the\nprint statement, the data members `version` and `uri` of the `Request`\nstruct were printed as raw integer values. String data being printed\nas integer values is common in Zig, and remember, these integer values are just the decimal representation of\nthe bytes that form the string in question.\n\nIn the result below, the sequence of decimal values 72, 84, 84, 80, 47, 49, 46, 49, and 13,\nare the bytes that form the text \"HTTP/1.1\". And the integer 47, is the decimal value of\nthe character `/`, which represents our URI in this request.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst Request = @import(\"request.zig\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n\n var buffer: [1000]u8 = undefined;\n for (0..buffer.len) |i| {\n buffer[i] = 0;\n }\n try Request.read_request(\n connection, buffer[0..buffer.len]\n );\n const request = Request.parse_request(\n buffer[0..buffer.len]\n );\n try stdout.print(\"{any}\\n\", .{request});\n}\n```\n:::\n\n\n\n\n```\nrequest.Request{\n .method = request.Method.GET,\n .version = {72, 84, 84, 80, 47, 49, 46, 49, 13},\n .uri = {47}\n}\n```\n\n\n\n### Sending the HTTP Response to the client\n\nIn this last part, we are going to write the logic responsible for\nsending the HTTP Response from the server to the client. To make things\nsimple, the server in this project will send just a simple web page\ncontaining the text \"Hello world\".\n\nFirst, I create a new Zig module in the project, named `response.zig`.\nIn this module, I will declare just two functions. Each function\ncorresponds to a specific status code in the HTTP Response.\nThe `send_200()` function will send a HTTP Response with status code 200\n(which means \"Success\") to the client. While the `send_404()` function sends a response\nwith status code 404 (which means \"Not found\").\n\nThis is definitely not the most ergonomic and adequate way of handling the\nHTTP Response, but it works for our case here. We are just building toy projects\nin this book after all, therefore, the source code that we write do not need to be perfect.\nIt just needs to work!\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Connection = std.net.Server.Connection;\npub fn send_200(conn: Connection) !void {\n const message = (\n \"HTTP/1.1 200 OK\\nContent-Length: 48\"\n ++ \"\\nContent-Type: text/html\\n\"\n ++ \"Connection: Closed\\n\\n\"\n ++ \"

    Hello, World!

    \"\n );\n _ = try conn.stream.write(message);\n}\n\npub fn send_404(conn: Connection) !void {\n const message = (\n \"HTTP/1.1 404 Not Found\\nContent-Length: 50\"\n ++ \"\\nContent-Type: text/html\\n\"\n ++ \"Connection: Closed\\n\\n\"\n ++ \"

    File not found!

    \"\n );\n _ = try conn.stream.write(message);\n}\n```\n:::\n\n\n\n\nNotice that both functions receives the connection object as input, and\nuse the `write()` method to write the HTTP Response message directly\ninto this communication channel. As result, the party in the other\nside of the connection (i.e. the client), will receive such message.\n\nMost real-world HTTP Servers will have a single function (or a single struct) to effectively handle\nthe response. It gets the HTTP Request already parsed as input, and then, it tries to build\nthe HTTP Response bit by bit, before the function sends it over the connection.\n\nWe would also have a specialized struct to represent a HTTP Response, and\na lot of methods that would be used to build each part or component of the response object.\nTake the `Response` struct created by the Javascript runtime Bun as an example.\nYou can find this struct in the [`response.zig` module](https://github.com/oven-sh/bun/blob/main/src/bun.js/webcore/response.zig)[^bun-resp]\nin their GitHub project.\n\n[^bun-resp]: .\n\n\n## The end result\n\nWe can now, update once again our `main()` function to incorporate our new\nfunctions from the `response.zig` module. First, I need to import this module\ninto our `main.zig` module, then, I add the function calls to `send_200()`\nand `send_404()`.\n\nNotice that I'm using if statements to decide which \"response function\" to call,\nbased especially on the URI present in the HTTP Request. If the user asked for\na content (or a document) that is not present in our server, we should respond\nwith a 404 status code. But since we have just a simple HTTP server, with no\nreal documents to send, we can just check if the URI is the root path (`/`)\nor not to decide which function to call.\n\nAlso, notice that I'm using the function `std.mem.eql()` from the Zig Standard Library\nto check if the string from `uri` is equal or not the string `\"/\"`. We have\ndescribed this function already at @sec-strings-useful-funs, so, comeback to\nthat section if you are not familiar yet with this function.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst Request = @import(\"request.zig\");\nconst Response = @import(\"response.zig\");\nconst Method = Request.Method;\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n try stdout.print(\"Server Addr: {any}\\n\", .{socket._address});\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n\n var buffer: [1000]u8 = undefined;\n for (0..buffer.len) |i| {\n buffer[i] = 0;\n }\n try Request.read_request(connection, buffer[0..buffer.len]);\n const request = Request.parse_request(\n buffer[0..buffer.len]\n );\n if (request.method == Method.GET) {\n if (std.mem.eql(u8, request.uri, \"/\")) {\n try Response.send_200(connection);\n } else {\n try Response.send_404(connection);\n }\n }\n}\n```\n:::\n\n\n\n\n\nNow that we adjusted our `main()` function, I can now execute our program, and\nsee the effects of these last changes. First, I execute the program once again, with the\n`run` command of the `zig` compiler. The program will hang, waiting for a client to connect.\n\nThen, I open my web browser, and try to connect to the server again, using the URL `localhost:3490`.\nThis time, instead of getting some sort of an error message from the browser, you will get the message\n\"Hello World\" printed into your web browser. Because this time, the server sended the HTTP Response\nsuccessfully to the web browser, as demonstrated by @fig-print-zigrun3.\n\n\n![The Hello World message sent in the HTTP Response](./../Figures/print-zigrun3.png){#fig-print-zigrun3}\n\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 2 - Building a HTTP Server from scratch\n\nIn this chapter, I want to implement a new\nsmall project with you. This time, we are going\nto implement a basic HTTP Server from scratch.\n\nThe Zig Standard Library already have a HTTP Server\nimplemented, which is available at `std.http.Server`.\nBut again, our objective here in this chapter, is to implement\nit **from scratch**. So we can't use this server object available\nfrom the Zig Standard Library.\n\n## What is a HTTP Server?\n\nFirst of all, what is a HTTP Server?\nA HTTP server, as any other type of server, is essentially\na program that runs indefinitely, on an infinite loop, waiting for incoming connections\nfrom clients. Once the server receives an incoming connection, it will\naccept this connection, and it will send messages back-and-forth to the client\nthrough this connection.\n\nBut the messages that are transmitted inside this connection are in a\nspecific format. They are HTTP messages\n(i.e., messages that use the HTTP Protocol specification).\nThe HTTP Protocol is the backbone of the modern web.\nThe world wide web as we know it today, would not exist without the\nHTTP Protocol.\n\nSo, Web servers (which is just a fancy name to\nHTTP Servers) are servers that exchange HTTP messages with clients.\nAnd these HTTP servers and the HTTP Protocol specification\nare essential to the operation of the world wide web today.\n\nThat is the whole picture of the process.\nAgain, we have two subjects involved here, a server (which is\na program that is running indefinitely, waiting to receive incoming connections),\nand a client (which is someone that wants to connect to the server,\nand exchange HTTP messages with it).\n\nYou may find the material about the [HTTP Protocol available at the Mozilla MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)[^mdn-http]\n, a great resource for you to also look at. It gives you a great overview on how\nHTTP works, and what role the server plays in this matter.\n\n[^mdn-http]: .\n\n\n## How a HTTP Server works? {#sec-how-http-works}\n\nImagine a HTTP Server as if it were the receptionist of a large hotel. In a hotel,\nyou have a reception, and inside that reception there is a receptionist\nwaiting for customers to arrive. A HTTP Server is essentially a receptionist\nthat is indefinitely waiting for new customers (or, in the context of HTTP, new clients)\nto arrive in the hotel.\n\nWhen a customer arrives at the hotel, that customer starts a conversation with the\nreceptionist. He tells the receptionist how many days he wants to stay at the hotel.\nThen, the receptionist search for an available apartment. If there is an available apartment\nat the moment, the customer pays the hotel fees, then, he gets the keys to the apartment,\nand then, he goes to the apartment to rest.\n\nAfter this entire process of dealing with the customer (searching for available apartments,\nreceiving payment, handing over the keys), the receptionist goes back to what he was\ndoing earlier, which is to wait. Wait for new customers to arrive.\n\nThat is, in a nutshell, what a HTTP Server do. It waits for clients to connect to the\nserver. When a client attempts to connect to the server, the server accepts this connection,\nand it starts to exchange messages with the client through this connection.\nThe first message that happens inside this connection is always a message from the client\nto the server. This message is called the *HTTP Request*.\n\nThis HTTP Request is a HTTP message that contains what\nthe client wants from the server. It is literally a request. The client\nthat connected to the server is asking this server to do something for him.\n\nThere are different \"types of request\" that a client can send to a HTTP Server.\nBut the most basic type of request, is when a client ask to the\nHTTP Server to serve (i.e., to send) some specific web page (which is a HTML file) to him.\nWhen you type `google.com` in your web browser, you are essentially sending a HTTP Request to Google's\nHTTP servers. This request is asking these servers to send the Google webpage to you.\n\nNonetheless, when the server receives this first message, the *HTTP Request*, it\nanalyzes this request, to understand: who the client is? What he wants the server to do?\nThis client has provided all the necessary information to perform the action that he\nasked? Etc.\n\nOnce the server understands what the client wants, he simply perform the action\nthat was requested, and, to finish the whole process, the server sends back\na HTTP message to the client, informing if the action performed was successful or not,\nand, at last, the server ends (or closes) the connection with the client.\n\nThis last HTTP message sent from the server to the client, is called the *HTTP Response*.\nBecause the server is responding to the action that was requested by the client.\nThe main objective of this response message is let the client know if the\naction requested was successful or not, before the server closes the connection.\n\n\n## How a HTTP server is normally implemented? {#sec-http-how-impl}\n\nLet's use the C language as an example. There are many materials\nteaching how to write a simple HTTP server in C code, like @jeffrey_http,\nor @nipun_http, or @eric_http.\nHaving this in mind, I will not show C code examples here, because you\ncan find them on the internet.\nBut I will describe the theory behind the necessary steps to create\nsuch HTTP server in C.\n\n\nIn essence, we normally implement a HTTP server in C by using WebSocket technology,\nwhich involves the following steps:\n\n1. Create a socket object.\n1. Bind a name (or more specifically, an address) to this socket object.\n1. Make this socket object to start listening and waiting for incoming connections.\n1. When a connection arrive, we accept this connection, and we exchange the HTTP messages (HTTP Request and HTTP Response).\n1. Then, we simply close this connection.\n\n\nA socket object is essentially a channel of communication.\nYou are creating a channel where people can send messages through.\nWhen you create a socket object, this object is not binded to any particular\naddress. This means that with this object you have a representation of a channel of communication\nin your hands. But this channel is not currently available, or, it is not currently accessible,\nbecause it does not have a known address where you can find it.\n\nThat is what the \"bind\" operation do. It binds a name (or more specifically, an address) to\nthis socket object, or, this channel of communication, so that it becomes available,\nor, accessible through this address. While the \"listen\" operation makes the socket object to\nlisten for incoming connections in this address. In other words, the \"listen\" operation\nmakes the socket to wait for incoming connections.\ncurrently\nNow, when a client actually attempts to connect to the server through the socket address\nthat we have specified, in order to establish this connection with the client,\nthe socket object needs to accept this incoming connection. Thus, when we\naccept an incoming connection, the client and the server become\nconnected to each other, and they can start reading or writing messages into this\nestablished connection.\n\nAfter we receive the HTTP Request from the client, analyze it, and send the HTTP Response\nto the client, we can then close the connection, and end this communication.\n\n\n## Implementing the server - Part 1\n\n### Creating the socket object {#sec-create-socket}\n\nLet's begin with creating the socket object for our server.\nJust to make things shorter, I will create this socket object in\na separate Zig module. I will name it `config.zig`.\n\nIn Zig, we can create a web socket using\nthe `std.posix.socket()` function, from the Zig Standard Library.\nAs I mentioned earlier in @sec-http-how-impl, every socket object that we create\nrepresents a communication channel, and we need to bind this channel to a specific address.\nAn \"address\" is defined as an IP address, or, more specifically, an IPv4 address^[It can be also an IPv6 address. But normally, we use a IPv4 address for that.].\nEvery IPv4 address is composed by two components. The first component is the host,\nwhich is a sequence of 4 numbers separated by dot characters (`.`) that identifies the machine used.\nWhile the second component is a port number, which identifies the specific\ndoor, or, the specific port to use in the host machine.\n\nThe sequence of 4 numbers (i.e., the host) identifies the machine (i.e., the computer itself) where\nthis socket will live in. Every computer normally have multiple \"doors\" available inside of him, because\nthis allows the computer to receive and work with multiple connections at the same time.\nHe simply use a single door for each connection. So the port number, is\nessentially a number that identifies the specific door in the computer that will be responsible\nfor receiving the connection. That is, it identifies the \"door\" in the computer that the socket will use\nto receive incoming connections.\n\nTo make things simpler, I will use an IP address that identifies our current machine in this example.\nThis means that, our socket object will reside on the same computer that we are currently using\n(this is also known as the \"localhost\") to write this Zig source code.\n\nBy convention, the IP address that identifies the \"localhost\", which is the current machine we\nare using, is the IP `127.0.0.1`. So, that is the IP\naddress we are going to use in our server. I can declare it in Zig\nby using an array of 4 integers, like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst localhost = [4]u8{ 127, 0, 0, 1 };\n_ = localhost;\n```\n:::\n\n\n\n\nNow, we need to decide which port number to use. By convention, there are some\nport numbers that are reserved, meaning that, we cannot use them for our own\npurposes, like the port 22 (which is normally used for SSH connections).\nFor TCP connections, which is our case here,\na port number is a 16-bit unsigned integer (type `u16` in Zig),\nthus ranging from 0 to 65535 [@wikipedia_port].\nSo, we can choose\na number from 0 to 65535 for our port number. In the\nexample of this book, I will use the port number 3490\n(just a random number).\n\n\nNow that we have these two informations at hand, I can\nfinally create our socket object, using the `std.posix.socket()` function.\nFirst, we use the host and the port number to create an `Address` object,\nwith the `std.net.Address.initIp4()` function, like in the example below.\nAfter that, I use this address object inside the `socket()` function\nto create our socket object.\n\nThe `Socket` struct defined below summarizes all the logic behind\nthis process. In this struct, we have two data members, which are:\n1) the address object; 2) and a stream object, which is\nthe object we will use to read and write the messages into any connection we establish.\n\nNotice that, inside the constructor method of this struct,\nwhen we create the socket object, we are using the `IPROTO.TCP` property as an input to\ntell the function to create a socket for TCP connections.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\nconst net = @import(\"std\").net;\n\npub const Socket = struct {\n _address: std.net.Address,\n _stream: std.net.Stream,\n\n pub fn init() !Socket {\n const host = [4]u8{ 127, 0, 0, 1 };\n const port = 3490;\n const addr = net.Address.initIp4(host, port);\n const socket = try std.posix.socket(\n addr.any.family,\n std.posix.SOCK.STREAM,\n std.posix.IPPROTO.TCP\n );\n const stream = net.Stream{ .handle = socket };\n return Socket{ ._address = addr, ._stream = stream };\n }\n};\n```\n:::\n\n\n\n\n\n### Listening and receiving connections\n\nRemember that we stored the `Socket` struct\ndeclaration that we built in @sec-create-socket inside a Zig module named `config.zig`.\nThis is why I imported this module into our main module (`main.zig`) in the example below, as the `SocketConf` object,\nto access the `Socket` struct.\n\nOnce we created our socket object, we can focus now on making this socket object\nlisten and receive new incoming connections. We do that, by calling the `listen()`\nmethod from the `Address` object that is contained inside the socket object, and then,\nwe call the `accept()` method over the result.\n\nThe `listen()` method from the `Address` object produces a server object,\nwhich is an object that will stay open and running indefinitely, waiting\nto receive an incoming connection. Therefore, if you try to run the code\nexample below, by calling the `run` command from the `zig` compiler,\nyou will notice that the programs keeps running indefinitely,\nwithout a clear end.\n\nThis happens, because the program is waiting for something to happen.\nIt's waiting for someone to try to connect to the address (`http://127.0.0.1:3490`) where\nthe server is running and listening for incoming connections. This is what\nthe `listen()` method do, it makes the socket to be active waiting for someone\nto connect.\n\nOn the other side, the `accept()` method is the function that establishes the connection\nwhen someone tries to connect to the socket. This means that, the `accept()` method\nreturns a new connection object as a result. And you can use this connection object\nto read or write messages from or to the client.\nFor now, we are not doing anything with this connection object.\nBut we are going to use it in the next section.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n try stdout.print(\"Server Addr: {any}\\n\", .{socket._address});\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n _ = connection;\n}\n```\n:::\n\n\n\n\nThis code example allows one single connection. In other words, the\nserver will wait for one incoming connection, and as soon as the\nserver is done with this first connection that it establishes, the\nprogram ends, and the server stops.\n\nThis is not the norm in the real world. Most people that write\na HTTP server like this, usually put the `accept()` method\ninside a `while` (infinite) loop, where if a connection\nis created with `accept()`, a new thread of execution is created to deal with\nthis new connection and the client. That is, real-world examples of HTTP Servers\nnormally rely on parallel computing to work.\n\nWith this design, the server simply accepts the connection,\nand the whole process of dealing with the client, and receiving\nthe HTTP Request, and sending the HTTP Response, all of this\nis done in the background, on a separate execution thread.\n\nSo, as soon as the server accepts the connection, and creates\nthe separate thread, the server goes back to what he was doing earlier,\nwhich is to wait indefinitely for a new connection to accept.\nHaving this in mind, the code example exposed above, is a\nserver that serves only a single client. Because the program\nterminates as soon as the connection is accepted.\n\n\n\n### Reading the message from the client {#sec-read-http-message}\n\nNow that we have a connection established, i.e., the connection\nobject that we created through the `accept()` function, we can now\nuse this connection object to read any messages that the client\nsend to our server. But we can also use it to send messages back\nto the client.\n\nThe basic idea is, if we **write** any data into this connection object,\nthen, we are sending data to the client, and if we **read** the data present in\nthis connection object, then, we are reading any data that the\nclient sent to us, through this connection object. So, just\nhave this logic in mind. \"Read\" is for reading messages from the client,\nand \"write\" is to send a message to the client.\n\nRemember from @sec-how-http-works that, the first thing that we need to do is to read the HTTP Request\nsent by the client to our server. Because it is the first message that happens\ninside the established connection, and, as a consequence, it is the first\nthing that we need to deal with.\n\nThat is why, I'm going to create a new Zig module in this small project, named `request.zig`\nto keep all functions related to the HTTP Request\ntogether. Then, I will create a new function named `read_request()` that will\nuse our connection object to read the message sent by the client,\nwhich is the HTTP Request.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Connection = std.net.Server.Connection;\npub fn read_request(conn: Connection,\n buffer: []u8) !void {\n const reader = conn.stream.reader();\n _ = try reader.read(buffer);\n}\n```\n:::\n\n\n\n\n\nThis function accepts a slice object which behaves as a buffer.\nThe `read_request()` function reads the message sent into\nthe connection object, and saves this message into this buffer object that\nwe have provided as input.\n\nNotice that I'm using the connection object that we created to read\nthe message from the client. I first access the `reader` object that lives inside the\nconnection object. Then, I call the `read()` method of this `reader` object\nto effectively read and save the data sent by the client into the buffer object\nthat we created earlier. I'm discarding the return value\nof the `read()` method, by assigning it to the underscore character (`_`),\nbecause this return value is not useful for us right now.\n\n\n\n## Looking at the current state of the program\n\n\nI think now is a good time to see how our program is currently working. Shall we?\nSo, the first thing I will do is to update the `main.zig` module in our small Zig project,\nso that the `main()` function call this new `read_request()` function that we have just created.\nI will also add a print statement at the end of the `main()` function,\njust so that you can see what the HTTP Request that we have just loaded into the buffer object\nlooks like.\n\nAlso, I'm creating the buffer object in the `main()` function, which will be\nresponsible for storing the message sent by the client, and, I'm also\nusing a `for` loop to initialize all fields of this buffer object to the number zero.\nThis is important to make sure that we don't have uninitialized memory in\nthis object. Because uninitialized memory may cause undefined behaviour in our program.\n\nSince the `read_request()` function should receive as input the buffer object as a slice object (`[]u8`),\nI am using the syntax `array[0..array.len]` to get access to a slice of this `buffer` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst Request = @import(\"request.zig\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n try stdout.print(\"Server Addr: {any}\\n\", .{socket._address});\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n var buffer: [1000]u8 = undefined;\n for (0..buffer.len) |i| {\n buffer[i] = 0;\n }\n _ = try Request.read_request(\n connection, buffer[0..buffer.len]\n );\n try stdout.print(\"{s}\\n\", .{buffer});\n}\n```\n:::\n\n\n\n\nNow, I'm going to execute this program, with the `run` command from the\n`zig` compiler. But remember, as we sad earlier, as soon as I execute this program, it will\nhang indefinitely, because the program is waiting for a client trying to\nconnect to the server.\n\nMore specifically, the program will pause at the line\nwith the `accept()` call. As soon as a client try to connect to the\nserver, then, the execution will \"unpause\", and the `accept()` function\nwill finally be executed to create the\nconnection object that we need, and the remaining of the program\nwill run.\n\nYou can see that in @fig-print-zigrun1. The message `Server Addr: 127.0.0.1:3490`\nis printed to the console, and the program is now waiting for an incoming connection.\n\n![A screenshot of running the program](./../Figures/print-zigrun1.png){#fig-print-zigrun1}\n\n\nWe can finally try to connect to this server, and there are several ways we can do this.\nFor example, we could use the following Python script:\n\n```python\nimport requests\nrequests.get(\"http://127.0.0.1:3490\")\n```\n\nOr, we could also open any web browser of our preference, and type\nthe URL `localhost:3490`. OBS: `localhost` is the same thing as the\nIP `127.0.0.1`. When you press enter, and your web browser go\nto this address, first, the browser will probably print a message\nsaying that \"this page isn't working\", and, then, it will\nprobably change to a new message saying that \"the site can't be\nreached\".\n\nYou get these \"error messages\" in the web browser, because\nit got no response back from the server. In other words, when the web\nbrowser connected to our server, it did send the HTTP Request through the established connection.\nThen, the web browser was expecting to receive a HTTP Response back, but\nit got no response from the server (we didn't implemented the HTTP Response logic yet).\n\nBut that is okay. We have achieved the result that we wanted for now,\nwhich is to connect to the server, and see the HTTP Request\nthat was sent by the web browser (or by the Python script)\nto the server.\n\nIf you comeback to the console that you left open\nwhen you have executed the program, you will see that the\nprogram finished its execution, and, a new message is\nprinted in the console, which is the actual HTTP Request\nmessage that was sent by the web browser to the server.\nYou can see this message in @fig-print-zigrun2.\n\n![A screenshot of the HTTP Request sent by the web browser](./../Figures/print-zigrun2.png){#fig-print-zigrun2}\n\n\n\n\n## Learning about Enums in Zig {#sec-enum}\n\nEnums structures are available in Zig through the `enum` keyword.\nAn enum (short for \"enumeration\") is a special structure that represents a group of constant values.\nSo, if you have a variable which can assume a short and known\nset of values, you might want to associate this variable to an enum structure,\nto make sure that this variable only assumes a value from this set.\n\nA classic example for enums are primary colors. If for some reason, your program\nneeds to represent one of the primary colors, you can create an enum\nthat represents one of these colors.\nIn the example below, we are creating the enum `PrimaryColorRGB`, which\nrepresents a primary color from the RGB color system. By using this enum,\nI am guaranteed that the `acolor` object for example, will contain\none of these three values: `RED`, `GREEN` or `BLUE`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst PrimaryColorRGB = enum {\n RED, GREEN, BLUE\n};\nconst acolor = PrimaryColorRGB.RED;\n_ = acolor;\n```\n:::\n\n\n\n\nIf for some reason, my code tries to save in `acolor`,\na value that is not in this set, I will get an error message\nwarning me that a value such as \"MAGENTA\" do not exist\ninside the `PrimaryColorRGB` enum.\nThen I can easily fix my mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst acolor = PrimaryColorRGB.MAGENTA;\n```\n:::\n\n\n\n\n```\ne1.zig:5:36: error: enum 'PrimaryColorRGB' has\n no member named 'MAGENTA':\n const acolor = PrimaryColorRGB.MAGENTA;\n ^~~~~~~\n```\n\nBehind the hood, enums in Zig work the same way that enums\nwork in C. Each enum value is essentially represented as an integer.\nThe first value in the set is represented as zero,\nthen, the second value is one, ... etc.\n\nOne thing that we are going to learn in the next section is that\nenums can have methods in them. Wait... What? This is amazing!\nYes, enums in Zig are similar to structs, and they can have\nprivate and public methods inside them.\n\n\n\n\n\n\n\n## Implementing the server - Part 2\n\nNow, on this section, I want to focus on parsing\nthe HTTP Request that we received from the client.\nHowever, to effectively parse a HTTP Request message, we first need to understand its\nstructure.\nIn summary, a HTTP Request is a text message that is divided into 3 different\nsections (or parts):\n\n- The top-level header indicating the method of the HTTP Request, the URI, and the HTTP version used in the message.\n- A list of HTTP Headers.\n- The body of the HTTP Request.\n\n### The top-level header\n\nThe first line of text in a HTTP Request always come with the three most essential\ninformation about the request. These three key attributes of the HTTP Request\nare separated by a simple space in this first line of the request.\nThe first information is the HTTP method that is being\nused in the request, second, we have the URI to which this HTTP Request is being sent to,\nand third, we have the version of the HTTP protocol that is being used in this HTTP Request.\n\nIn the snippet below, you can find an example of this first line in a HTTP Request.\nFirst, we have the HTTP method of this request (`GET`). Many programmers\nrefer to the URI component (`/users/list`) as the \"API endpoint\" to which the HTTP Request\nis being sent to. In the context of this specific request, since it's a GET request,\nyou could also say that the URI component is the path to the resource we want to access,\nor, the path to the document (or the file) that we want to retrieve from the server.\n\n```\nGET /users/list HTTP/1.1\n```\n\nAlso, notice that this HTTP Request is using the version 1.1 of the HTTP protocol,\nwhich is the most popular version of the protocol used in the web.\n\n\n\n### The list of HTTP headers\n\nMost HTTP Requests also include a section of HTTP Headers,\nwhich is just a list of attributes or key-value pairs associated with this\nparticular request. This section always comes right after the \"top-level header\" of the request.\n\nFor our purpose in this chapter, which is to build a simple HTTP Server,\nwe are going to ignore this section of the HTTP Request, for simplicity.\nBut most HTTP servers that exist in the wild parses and use these\nHTTP headers to change the way that the server responds to the request\nsent by the client.\n\nFor example, many requests we encounter in the real-world comes with\na HTTP header called `Accept`. In this header, we find a list of [MIME types](https://en.wikipedia.org/wiki/Media_type)[^mime].\nThis list indicates the file formats that the client can read, or parse, or interpret.\nIn other words, you also interpret this header as the client saying the following phrase\nto the server: \"Hey! Look, I can read only HTML documents, so please, send me back\na document that is in a HTML format.\".\n\n[^mime]: .\n\nIf the HTTP server can read and use this `Accept` header, then, the server can identify\nwhich is the best file format for the document to be sent to the client. Maybe the HTTP server have\nthe same document in multiple formats, for example, in JSON, in XML, in HTML and in PDF,\nbut the client can only understand documents in the HTML format. That is the purpose\nof this `Accept` header.\n\n\n### The body\n\nThe body comes after the list of HTTP headers, and it's an optional section of the HTTP Request, meaning that, not\nall HTTP Requests will come with a body in them. For example, every HTTP Request that uses the\nGET method usually does not come with a body.\n\nBecause a GET request is used to request data, instead of sending it to the server.\nSo, the body section is more related to the POST method, which is a method that involves\nsending data to the server, to be processed and stored.\n\nSince we are going to support only the GET method in this project, it means that\nwe also do not need to care about the body of the request.\n\n\n\n### Creating the HTTP Method enum\n\nEvery HTTP Request comes with a explicit method. The method used in a HTTP Request\nis identified by one these words:\n\n- GET;\n- POST;\n- OPTIONS;\n- PATCH;\n- DELETE;\n- and some other methods.\n\nEach HTTP method is used for a specific type of task. The POST method for example is normally\nused to post some data into the destination. In other words, it's used\nto send some data to the HTTP server, so that it can be processed and stored by the server.\n\nAs another example, the GET method is normally used to get content from the server.\nIn other words, we use this method whenever we want the server to send some\ncontent back to us. It can be any type of content. It can be a web page,\na document file, or some data in a JSON format.\n\nWhen a client sends a POST HTTP Request, the HTTP Response sent by the server normally have the sole purpose of\nletting the client know if the server processed and stored the data successfully.\nIn contrast, when the server receives a GET HTTP Request, then, the server sends the content\nthat the client asked for in the HTTP Response itself. This demonstrates that the method associated\nwith the HTTP Request changes a lot on the dynamics and the roles that each party\nplays in the whole process.\n\nSince the HTTP method of the HTTP Request is identified by this very small and specific\nset of words, it would be interesting to create an enum structure to represent a HTTP method.\nThis way, we can easily check if the HTTP Request we receive from the client is a\nHTTP method that we currently support in our small HTTP server project.\n\nThe `Method` structure below represents this enumeration.\nNotice that, for now, only the GET HTTP method is included in this\nenumeration. Because, for the purpose of this chapter, I want to\nimplement only the GET HTTP method. That is why I am not\nincluding the other HTTP methods in this enumeration.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Method = enum {\n GET\n};\n```\n:::\n\n\n\n\n\nNow, I think we should add two methods to this enum structure. One method is `is_supported()`,\nwhich will be a function that returns a boolean value, indicating if the input HTTP method is supported\nor not by our HTTP Server. The other is `init()`, which is a constructor function that takes a string as input,\nand tries to convert it into a `Method` value.\n\n\nBut in order to build these functions, I will use a functionality from the Zig Standard Library, called\n`StaticStringMap()`. This function allows us to create a simple map from strings to enum values.\nIn other words, we can use this map structure to map a string to the respective enum value.\nTo some extent, this specific structure from the standard library works almost like a \"hashtable\" structure,\nand it's optimized for small sets of words, or, small sets of keys, which is our case here.\nWe are going to talk more about hashtables in Zig in @sec-maps-hashtables.\n\nTo use this \"static string map\" structure, you have to import it from the `std.static_string_map` module\nof the Zig Standard Library. Just to make things shorter and easier to type, I am going to import this\nfunction through a different and shorter name (`Map`).\n\nWith `Map()` imported, we can just apply this function over the enum structure\nthat we are going to use in the resulting map. In our case here, it's the `Method` enum structure\nthat we declared at the last code example. Then, I call the `initComptime()` method with the\nmap, i.e., the list of key-value pairs that we are going to use.\n\nYou can see in the example below that I wrote this map using multiple anonymous struct literals.\nInside the first (or \"top-level\") struct literal, we have a list (or a sequence) of struct literals.\nEach struct literal in this list represents a separate key-value pair. The first element (or the key)\nin each key-value pair should always be a string value. While the second element should\nbe a value from the enum structure that you have used inside the `Map()` function.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Map = std.static_string_map.StaticStringMap;\nconst MethodMap = Map(Method).initComptime(.{\n .{ \"GET\", Method.GET },\n});\n```\n:::\n\n\n\n\nTherefore, the `MethodMap` object is basically a `std::map` object from C++, or,\na `dict` object from Python. You can retrieve (or get) the enum value that\ncorresponds to a particular key, by using the `get()` method from the map\nobject. This method returns an optional value, so, the `get()` method might\nresult in a null value.\n\nWe can use this in our advantage to detect if a particular HTTP method is\nsupported or not in our HTTP server. Because, if the `get()` method returns null,\nit means that it did not found the method that we provided inside the `MethodMap` object, and,\nas a consequence, this method is not supported by our HTTP server.\n\nThe `init()` method below, takes a string value as input, and then, it simply passes this string value\nto the `get()` method of our `MethodMap` object. As consequence, we should get the enum value that corresponds\nto this input string.\n\nNotice in the example below that, the `init()` method returns either an error\n(which might happen if the `?` method returns `unreacheable`, checkout @sec-null-handling for more details)\nor a `Method` object as result. Since `GET` is currently the only value in our `Method` enum\nstructure, it means that, the `init()` method will most likely return the value `Method.GET` as result.\n\nAlso notice that, in the `is_supported()` method, we are using the optional value returned\nby the `get()` method from our `MethodMap` object. The if statement unwraps the optional value\nreturned by this method, and returns `true` in case this optional value is a not-null value.\nOtherwise, it simply returns `false`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Method = enum {\n GET,\n pub fn init(text: []const u8) !Method {\n return MethodMap.get(text).?;\n }\n pub fn is_supported(m: []const u8) bool {\n const method = MethodMap.get(m);\n if (method) |_| {\n return true;\n }\n return false;\n }\n};\n```\n:::\n\n\n\n\n\n\n\n\n\n\n### Writing the parse request function\n\nNow that we created the enum that represents our HTTP method,\nwe should start to write the function responsible for\nactually parsing the HTTP Request.\n\nThe first thing we can do, is to write a struct to represent the HTTP Request.\nTake the `Request` struct below as an example. It contains the three\nessential information from the \"top-level\" header (i.e., the first line)\nin the HTTP Request.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Request = struct {\n method: Method,\n version: []const u8,\n uri: []const u8,\n pub fn init(method: Method,\n uri: []const u8,\n version: []const u8) Request {\n return Request{\n .method = method,\n .uri = uri,\n .version = version,\n };\n }\n};\n```\n:::\n\n\n\n\n\nThe `parse_request()` function should receive a string as input. This input string\ncontains the entire HTTP Request message, and the parsing function should\nread and understand the individual parts of this message.\n\nNow, remember that for the purpose of this chapter, we care only about the first\nline in this message, which contains the \"top-level header\", or, the three essential attributes about the HTTP Request,\nwhich are the HTTP method used, the URI and the HTTP version.\n\nNotice that I use the function `indexOfScalar()` in `parse_request()`. This function from the\nZig Standard Library returns the first index where the scalar value that we provide\nhappens in a string. In this case, I'm looking at the first occurrence of the new line character (`\\n`).\nBecause once again, we care only about the first line in the HTTP Request message.\nThis is the line where we have the three information that we want to parse\n(version of HTTP, the HTTP method and the URI).\n\nTherefore, we are using this `indexOfScalar()` function\nto limit our parsing process to the first line in the message.\nIt's also worth mentioning that, the `indexOfScalar()` function returns an optional value.\nThat is why I use the `orelse` keyword to provide an alternative value, in case\nthe value returned by the function is a null value.\n\nSince each of these three attributes are separated by a simple space, we\ncould use the function `splitScalar()` from the Zig Standard Library to split\nthe input string into sections by looking for every position that appears\na simple space. In other words, this `splitScalar()` function is equivalent\nto the `split()` method in Python, or, the `std::getline()` function from C++,\nor the `strtok()` function in C.\n\nWhen you use this `splitScalar()` function, you get an iterator as the result.\nThis iterator have a `next()` method that you can use to advance the iterator\nto the next position, or, to the next section of the splitted string.\nNote that, when you use `next()`, the method not only advances the iterator,\nbut it also returns a slice to the current section of the splitted\nstring as result.\n\nNow, if you want to get a slice to the current section of the splitted\nstring, but not advance the iterator to the next position, you can use\nthe `peek()` method. Both `next()` and `peek()` methods return an optional value, that is\nwhy I use the `?` method to unwrap these optional values.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn parse_request(text: []u8) Request {\n const line_index = std.mem.indexOfScalar(\n u8, text, '\\n'\n ) orelse text.len;\n var iterator = std.mem.splitScalar(\n u8, text[0..line_index], ' '\n );\n const method = try Method.init(iterator.next().?);\n const uri = iterator.next().?;\n const version = iterator.next().?;\n const request = Request.init(method, uri, version);\n return request;\n}\n```\n:::\n\n\n\n\n\nAs I described in @sec-zig-strings, strings in Zig are simply arrays of bytes in the language.\nSo, you will find lots of excellent utility functions to work directly with strings\ninside this `mem` module from the Zig Standard Library.\nWe have described some of these useful utility functions already\nin @sec-strings-useful-funs.\n\n\n\n### Using the parse request function\n\nNow that we wrote the function responsible for parsing the HTTP Request,\nwe can add the function call to `parse_request()` in\nthe `main()` function of our program.\n\nAfter that, is a good idea to test once again the state of our program.\nI execute this program again with the `run` command from the `zig` compiler,\nthen, I use my web browser to connect once again to the server through the URL `localhost:3490`, and finally,\nthe end result of our `Request` object is printed to the console.\n\nA quick observation, since I have used the `any` format specifier in the\nprint statement, the data members `version` and `uri` of the `Request`\nstruct were printed as raw integer values. String data being printed\nas integer values is common in Zig, and remember, these integer values are just the decimal representation of\nthe bytes that form the string in question.\n\nIn the result below, the sequence of decimal values 72, 84, 84, 80, 47, 49, 46, 49, and 13,\nare the bytes that form the text \"HTTP/1.1\". And the integer 47, is the decimal value of\nthe character `/`, which represents our URI in this request.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst Request = @import(\"request.zig\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n\n var buffer: [1000]u8 = undefined;\n for (0..buffer.len) |i| {\n buffer[i] = 0;\n }\n try Request.read_request(\n connection, buffer[0..buffer.len]\n );\n const request = Request.parse_request(\n buffer[0..buffer.len]\n );\n try stdout.print(\"{any}\\n\", .{request});\n}\n```\n:::\n\n\n\n\n```\nrequest.Request{\n .method = request.Method.GET,\n .version = {72, 84, 84, 80, 47, 49, 46, 49, 13},\n .uri = {47}\n}\n```\n\n\n\n### Sending the HTTP Response to the client\n\nIn this last part, we are going to write the logic responsible for\nsending the HTTP Response from the server to the client. To make things\nsimple, the server in this project will send just a simple web page\ncontaining the text \"Hello world\".\n\nFirst, I create a new Zig module in the project, named `response.zig`.\nIn this module, I will declare just two functions. Each function\ncorresponds to a specific status code in the HTTP Response.\nThe `send_200()` function will send a HTTP Response with status code 200\n(which means \"Success\") to the client. While the `send_404()` function sends a response\nwith status code 404 (which means \"Not found\").\n\nThis is definitely not the most ergonomic and adequate way of handling the\nHTTP Response, but it works for our case here. We are just building toy projects\nin this book after all, therefore, the source code that we write do not need to be perfect.\nIt just needs to work!\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Connection = std.net.Server.Connection;\npub fn send_200(conn: Connection) !void {\n const message = (\n \"HTTP/1.1 200 OK\\nContent-Length: 48\"\n ++ \"\\nContent-Type: text/html\\n\"\n ++ \"Connection: Closed\\n\\n\"\n ++ \"

    Hello, World!

    \"\n );\n _ = try conn.stream.write(message);\n}\n\npub fn send_404(conn: Connection) !void {\n const message = (\n \"HTTP/1.1 404 Not Found\\nContent-Length: 50\"\n ++ \"\\nContent-Type: text/html\\n\"\n ++ \"Connection: Closed\\n\\n\"\n ++ \"

    File not found!

    \"\n );\n _ = try conn.stream.write(message);\n}\n```\n:::\n\n\n\n\nNotice that both functions receives the connection object as input, and\nuse the `write()` method to write the HTTP Response message directly\ninto this communication channel. As result, the party in the other\nside of the connection (i.e., the client), will receive such message.\n\nMost real-world HTTP Servers will have a single function (or a single struct) to effectively handle\nthe response. It gets the HTTP Request already parsed as input, and then, it tries to build\nthe HTTP Response bit by bit, before the function sends it over the connection.\n\nWe would also have a specialized struct to represent a HTTP Response, and\na lot of methods that would be used to build each part or component of the response object.\nTake the `Response` struct created by the Javascript runtime Bun as an example.\nYou can find this struct in the [`response.zig` module](https://github.com/oven-sh/bun/blob/main/src/bun.js/webcore/response.zig)[^bun-resp]\nin their GitHub project.\n\n[^bun-resp]: .\n\n\n## The end result\n\nWe can now, update once again our `main()` function to incorporate our new\nfunctions from the `response.zig` module. First, I need to import this module\ninto our `main.zig` module, then, I add the function calls to `send_200()`\nand `send_404()`.\n\nNotice that I'm using if statements to decide which \"response function\" to call,\nbased especially on the URI present in the HTTP Request. If the user asked for\na content (or a document) that is not present in our server, we should respond\nwith a 404 status code. But since we have just a simple HTTP server, with no\nreal documents to send, we can just check if the URI is the root path (`/`)\nor not to decide which function to call.\n\nAlso, notice that I'm using the function `std.mem.eql()` from the Zig Standard Library\nto check if the string from `uri` is equal or not the string `\"/\"`. We have\ndescribed this function already in @sec-strings-useful-funs, so, comeback to\nthat section if you are not familiar yet with this function.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst Request = @import(\"request.zig\");\nconst Response = @import(\"response.zig\");\nconst Method = Request.Method;\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n try stdout.print(\"Server Addr: {any}\\n\", .{socket._address});\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n\n var buffer: [1000]u8 = undefined;\n for (0..buffer.len) |i| {\n buffer[i] = 0;\n }\n try Request.read_request(connection, buffer[0..buffer.len]);\n const request = Request.parse_request(\n buffer[0..buffer.len]\n );\n if (request.method == Method.GET) {\n if (std.mem.eql(u8, request.uri, \"/\")) {\n try Response.send_200(connection);\n } else {\n try Response.send_404(connection);\n }\n }\n}\n```\n:::\n\n\n\n\n\nNow that we adjusted our `main()` function, I can now execute our program, and\nsee the effects of these last changes. First, I execute the program once again, with the\n`run` command of the `zig` compiler. The program will hang, waiting for a client to connect.\n\nThen, I open my web browser, and try to connect to the server again, using the URL `localhost:3490`.\nThis time, instead of getting some sort of an error message from the browser, you will get the message\n\"Hello World\" printed into your web browser. Because this time, the server sended the HTTP Response\nsuccessfully to the web browser, as demonstrated by @fig-print-zigrun3.\n\n\n![The Hello World message sent in the HTTP Response](./../Figures/print-zigrun3.png){#fig-print-zigrun3}\n", + "supporting": [ + "04-http-server_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/05-pointers/execute-results/html.json b/_freeze/Chapters/05-pointers/execute-results/html.json index 12c21289..322b1cc9 100644 --- a/_freeze/Chapters/05-pointers/execute-results/html.json +++ b/_freeze/Chapters/05-pointers/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "8fdb1694a88afd9b81c337b29ec84c86", + "hash": "8201d761dfd46af14c754587b77047a2", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Pointers and Optionals {#sec-pointer}\n\nOn our next project we are going to build a HTTP server from scratch.\nBut in order to do that, we need to learn more about pointers and how they work in Zig.\nPointers in Zig are similar to pointers in C. But they come with some extra advantages in Zig.\n\nA pointer is an object that contains a memory address. This memory address is the address where\na particular value is stored in memory. It can be any value. Most of the times,\nit is a value that comes from another object (or variable) present in our code.\n\nIn the example below, I'm creating two objects (`number` and `pointer`).\nThe `pointer` object contains the memory address where the value of the `number` object\n(the number 5) is stored. So, that is a pointer in a nutshell. It is a memory\naddress that points to a particular existing value in the memory. You could\nalso say, that, the `pointer` object points to the memory address where the `number` object is\nstored.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\n_ = pointer;\n```\n:::\n\n\n\n\nWe create a pointer object in Zig by using the `&` operator. When you put this operator\nbefore the name of an existing object, you get the memory address of this object as result.\nWhen you store this memory address inside a new object, this new object becomes a pointer object.\nBecause it stores a memory address.\n\nPeople mostly use pointers as an alternative way to access a particular value.\nFor example, I can use the `pointer` object to access the value stored by\nthe `number` object. This operation of accessing the value that the\npointer \"points to\" is normally called of *dereferencing the pointer*.\nWe can dereference a pointer in Zig by using the `*` method of the pointer object. Like in the example\nbelow, where we take the number 5 pointed by the `pointer` object,\nand double it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\nconst doubled = 2 * pointer.*;\nstd.debug.print(\"{d}\\n\", .{doubled});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n10\n```\n\n\n:::\n:::\n\n\n\n\n\nThis syntax to dereference the pointer is nice. Because we can easily chain it with\nmethods of the value pointed by the pointer. We can use the `User` struct that we have\ncreated at @sec-structs-and-oop as an example. If you comeback to that section,\nyou will see that this struct have a method named `print_name()`.\n\nSo, for example, if we have an user object, and a pointer that points to this user object,\nwe can use the pointer to access this user object, and, at the same time, call the method `print_name()`\non it, by chaining the dereference method (`*`) with the `print_name()` method. Like in the\nexample below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst u = User.init(1, \"pedro\", \"email@gmail.com\");\nconst pointer = &u;\ntry pointer.*.print_name();\n```\n:::\n\n\n\n\n```\npedro\n```\n\nWe can also use pointers to effectively alter the value of an object.\nFor example, I could use the `pointer` object to set\nthe value of the object `number` to 6, like in the example below.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\n\n\n\nTherefore, as I mentioned earlier, people use pointers as an alternative way to access a particular value.\nAnd they use it especially when they do not want to \"move\" these values around. There are situations where,\nyou want to access a particular value in a different scope (i.e. a different location) of your code,\nbut you do not want to \"move\" this value to this new scope (or location) that you are in.\n\nThis matters especially if this value is big in size. Because if it is, then,\nmoving this value becomes an expensive operation to do.\nThe computer will have to spend a considerable amount of time\ncopying this value to this new location.\n\nTherefore, many programmers prefer to avoid this heavy operation of copying the value\nto the new location, by accessing this value through pointers.\nWe are going to talk more about this \"moving operation\" over the next sections.\nFor now, just keep in mind that avoiding this \"move operation\" is\none of main reasons why pointers are used in programming languages.\n\n\n\n\n\n## Constant objects vs variable objects {#sec-pointer-var}\n\nYou can have a pointer that points to a constant object, or, a pointer that points to a variable object.\nBut regardless of who this pointer is, a pointer **must always respect the characteristics of the object that it points to**.\nAs a consequence, if the pointer points to a constant object, then, you cannot use this pointer\nto change the value that it points to. Because it points to a value that is constant. As we discussed at @sec-assignments, you cannot\nchange a value that is constant.\n\nFor example, if I have a `number` object, which is constant, I cannot execute\nthe expression below where I'm trying to change the value of `number` to 6 through\nthe `pointer` object. As demonstrated below, when you try to do something\nlike that, you get a compile time error:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number = 5;\nconst pointer = &number;\npointer.* = 6;\n```\n:::\n\n\n\n\n```\np.zig:6:12: error: cannot assign to constant\n pointer.* = 6;\n```\n\nIf I change the `number` object to be a variable object, by introducing the `var` keyword,\nthen, I can successfully change the value of this object through a pointer, as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\n\n\nYou can see this relationship between \"constant versus variable\" on the data type of\nyour pointer object. In other words, the data type of a pointer object already gives you\nsome clues about whether the value that it points to is constant or not.\n\nWhen a pointer object points to a constant value, then, this pointer have a data type `*const T`,\nwhich means \"a pointer to a constant value of type `T`\".\nIn contrast, if the pointer points to a variable value, then, the type of the pointer is usually `*T`, which is\nsimply \"a pointer to a value of type `T`\".\nHence, whenever you see a pointer object whose data type is in the format `*const T`, then,\nyou know that you cannot use this pointer to change the value that it points to.\nBecause this pointer points to a constant value of type `T`.\n\n\nWe have talked about the value pointed by the pointer being constant or not,\nand the consequences that arises from it. But, what about the pointer object itself? I mean, what happens\nif the pointer object itself is constant or not? Think about it.\nWe can have a constant pointer that points to a constant value.\nBut we can also have a variable pointer that points to a constant value. And vice-versa.\n\nUntil this point, the `pointer` object was always constant,\nbut what this means for us? What is the consequence of the\n`pointer` object being constant? The consequence is that\nwe cannot change the pointer object, because it is constant. We can use the\npointer object in multiple ways, but we cannot change the\nmemory address that is inside this pointer object.\n\nHowever, if we mark the `pointer` object as a variable object,\nthen, we can change the memory address pointed by this `pointer` object.\nThe example below demonstrates that. Notice that the object pointed\nby the `pointer` object changes from `c1` to `c2`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c1: u8 = 5;\nconst c2: u8 = 6;\nvar pointer = &c1;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\npointer = &c2;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\n```\n:::\n\n\n\n\n```\n5\n6\n```\n\nThus, by setting the `pointer` object to a `var` or `const` object,\nyou specify if the memory address contained in this pointer object can change or not\nin your program. On the other side, you can change the value pointed by the pointer,\nif, and only if this value is stored in a variable object. If this value\nis in a constant object, then, you cannot change this value through a pointer.\n\n\n## Types of pointer\n\nIn Zig, there are two types of pointers [@zigdocs], which are:\n\n- single-item pointer (`*`);\n- many-item pointer (`[*]`);\n\n\nSingle-item pointer objects are objects whose data types are in the format `*T`.\nSo, for example, if an object have a data type `*u32`, it means that, this\nobject contains a single-item pointer that points to an unsigned 32-bit integer value.\nAs another example, if an object have type `*User`, then, it contains\na single-item pointer to an `User` value.\n\nIn contrast, many-item pointers are objects whose data types are in the format `[*]T`.\nNotice that the star symbol (`*`) is now inside a pair of brackets (`[]`). If the star\nsymbol is inside a pair of brackets, you know that this object is a many-item pointer.\n\nWhen you apply the `&` operator over an object, you will always get a single-item pointer.\nMany-item pointers are more of a \"internal type\" of the language, more closely\nrelated to slices. So, when you deliberately create a pointer with the `&` operator,\nyou always get a single-item pointer as result.\n\n\n\n## Pointer arithmetic\n\nPointer arithmetic is available in Zig, and they work the same way they work in C.\nWhen you have a pointer that points to an array, the pointer usually points to\nthe first element in the array, and you can use pointer arithmetic to\nadvance this pointer and access the other elements in the array.\n\n\nNotice in the example below, that initially, the `ptr` object was pointing\nto the first element in the array `ar`. But then, I started to walk through the array, by advancing\nthe pointer with simple pointer arithmetic.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{ 1, 2, 3, 4 };\nvar ptr: [*]const i32 = &ar;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\n```\n:::\n\n\n\n\n```\n1\n2\n3\n```\n\nAlthough you can create a pointer to an array like that, and\nstart to walk through this array by using pointer arithmetic,\nin Zig, we prefer to use slices, which were presented at @sec-arrays.\n\nBehind the hood, slices already are pointers,\nand they also come with the `len` property, which indicates\nhow many elements are in the slice. This is good because the `zig` compiler\ncan use it to check for potential buffer overflows, and other problems like that.\n\nAlso, you don't need to use pointer arithmetic to walk through the elements\nof a slice. You can simply use the `slice[index]` syntax to directly access\nany element you want in the slice.\nAs I mentioned at @sec-arrays, you can get a slice from an array by using\na range selector inside brackets. In the example below, I'm creating\na slice (`sl`) that covers the entire `ar` array. I can access any\nelement of `ar` from this slice, and, the slice itself already is a pointer\nbehind the hood.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{1,2,3,4};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\n\n## Optionals and Optional Pointers\n\nLet's talk about optionals and how they relate to pointers in Zig.\nBy default, objects in Zig are **non-nullable**. This means that, in Zig,\nyou can safely assume that any object in your source code is not null.\n\nThis is a powerful feature of Zig when you compare it to the developer experience in C.\nBecause in C, any object can be null at any point, and, as consequence, a pointer in C\nmight point to a null value. This is a common source of undefined behaviour in C.\nWhen programmers work with pointers in C, they have to constantly check if\ntheir pointers are pointing to null values or not.\n\nIf for some reason, your Zig code produces a null value somewhere, and, this null\nvalue ends up in an object that is non-nullable, a runtime error is always\nraised by your Zig program. Take the program below as an example.\nThe `zig` compiler can see the `null` value at compile time, and, as result,\nit raises a compile time error. But, if a `null` value is raised during\nruntime, a runtime error is also raised by the Zig program, with a\n\"attempt to use null value\" message.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nnumber = null;\n```\n:::\n\n\n\n```\np5.zig:5:14: error: expected type 'u8',\n found '@TypeOf(null)'\n number = null;\n ^~~~\n```\n\n\nYou don't get this type of safety in C.\nIn C, you don't get warnings or errors about null values being produced in your program.\nIf for some reason, your code produces a null value in C, most of the times, you end up getting a segmentation fault error\nas result, which can mean many things.\nThat is why programmers have to constantly check for null values in C.\n\nPointers in Zig are also, by default, **non-nullable**. This is another amazing\nfeature in Zig. So, you can safely assume that any pointer that you create in\nyour Zig code is pointing to a non-null value.\nTherefore, you don't have this heavy work of checking if the pointers you create\nin Zig are pointing to a null value.\n\n\n### What are optionals?\n\nOk, we know now that all objects are non-nullable by default in Zig.\nBut what if we actually need to use an object that might receive a null value?\nHere is where optionals come in.\n\nAn optional object in Zig is an object that can be null.\nTo mark an object as optional, we use the `?` operator. When you put\nthis `?` operator right before the data type of an object, you transform\nthis data type into an optional data type, and the object becomes an optional object.\n\nTake the snippet below as an example. We are creating a new variable object\ncalled `num`. This object have the data type `?i32`, which means that,\nthis object contains either a signed 32-bit integer (`i32`), or, a null value.\nBoth alternatives are valid values to the `num` object.\nThat is why, I can actually change the value of this object to null, and,\nno errors are raised by the `zig` compiler, as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\nnum = null;\n```\n:::\n\n\n\n\n### Optional pointers\n\nYou can also mark a pointer object as an optional pointer, meaning that,\nthis object contains either a null value, or, a pointer that points to a value.\nWhen you mark a pointer as optional, the data type of this pointer object\nbecomes `?*const T` or `?*T`, depending if the value pointed by the pointer\nis a constant value or not. The `?` identifies the object as optional, while\nthe `*` identifies it as a pointer object.\n\nIn the example below, we are creating a variable object named `num`, and an\noptional pointer object named `ptr`. Notice that the data type of the object\n`ptr` indicates that it is either a null value, or a pointer to an `i32` value.\nAlso, notice that the pointer object (`ptr`) can be marked as optional, even if\nthe object `num` is not optional.\n\nWhat this code tells us is that, the `num` variable will never contain a null value.\nThis variable will always contain a valid `i32` value. But in contrast, the `ptr` object might contain either a null\nvalue, or, a pointer to an `i32` value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: i32 = 5;\nvar ptr: ?*i32 = #\nptr = null;\nnum = 6;\n```\n:::\n\n\n\n\nBut what happens if we turn the table, and mark the `num` object as optional,\ninstead of the pointer object. If we do that, then, the pointer object is\nnot optional anymore. It would be a similar (although different) result. Because then, we would have\na pointer to an optional value. In other words, a pointer to a value that is either a\nnull value, or, a not-null value.\n\nIn the example below, we are recreating this idea. Now, the `ptr` object\nhave a data type of `*?i32`, instead of `?*i32`. Notice that the `*` symbol comes before of `?`\nthis time. So now, we have a pointer that points to a value that is either null\n, or, a signed 32-bit integer.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\n// ptr have type `*?i32`, instead of `?*i32`.\nconst ptr = #\n_ = ptr;\n```\n:::\n\n\n\n\n\n### Null handling in optionals {#sec-null-handling}\n\nWhen you have an optional object in your Zig code, you have to explicitly handle\nthe possibility of this object being null. It is like error-handling with `try` and `catch`.\nIn Zig you also have to handle null values like if they were a type of error.\n\nWe can do that, by using either:\n\n- an if statement, like you would do in C.\n- the `orelse` keyword.\n- unwrap the optional value with the `?` method.\n\nWhen you use an if statement, you use a pair of pipes\nto unwrap the optional value, and use this \"unwrapped object\"\ninside the if block.\nUsing the example below as a reference, if the object `num` is null,\nthen, the code inside the if statement is not executed. Otherwise,\nthe if statement will unwrap the object `num` into the `not_null_num`\nobject. This `not_null_num` object is guaranteed to be not null inside\nthe scope of the if statement.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst num: ?i32 = 5;\nif (num) |not_null_num| {\n try stdout.print(\"{d}\\n\", .{not_null_num});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n5\n```\n\n\n:::\n:::\n\n\n\n\nNow, the `orelse` keyword behaves like a binary operator. You connect two expressions with this keyword.\nOn the left side of `orelse`, you provide the expression that might result\nin a null value, and on the right side of `orelse`, you provide another expression\nthat will not result in a null value.\n\nThe idea behind the `orelse` keyword is: if the expression on the left side\nresult in a not-null value, then, this not-null value is used. However,\nif this expression on the left side result in a null value, then, the value\nof the expression on the right side is used instead.\n\nLooking at the example below, since the `x` object is currently null, the\n`orelse` decided to use the alternative value, which is the number 15.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x: ?i32 = null;\nconst dbl = (x orelse 15) * 2;\ntry stdout.print(\"{d}\\n\", .{dbl});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n30\n```\n\n\n:::\n:::\n\n\n\n\nYou can use the if statement or the `orelse` keyword, when you want to\nsolve (or deal with) this null value. However, if there is no clear solution\nto this null value, and the most logic and sane path is to simply panic\nand raise a loud error in your program when this null value is encountered,\nyou can use the `?` method of your optional object.\n\nIn essence, when you use this `?` method, the optional object is unwrapped.\nIf a not-null value is found in the optional object, then, this not-null value is used.\nOtherwise, the `unreachable` keyword is used. You can read more about this\n[`unreacheable` keyword at the official documentation](https://ziglang.org/documentation/master/#unreachable)[^un-docs].\nBut in essence, when you build your Zig source code using the build modes `ReleaseSafe` or `Debug`, this\n`unreacheable` keyword causes the program to panic and raise an error during runtime,\nlike in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn return_null(n: i32) ?i32 {\n if (n == 5) return null;\n return n;\n}\n\npub fn main() !void {\n const x: i32 = 5;\n const y: ?i32 = return_null(x);\n try stdout.print(\"{d}\\n\", .{y.?});\n}\n```\n:::\n\n\n\n\n```\nthread 12767 panic: attempt to use null value\np7.zig:12:34: 0x103419d in main (p7):\n try stdout.print(\"{d}\\n\", .{y.?});\n ^\n```\n\n\n[^un-docs]: .\n\n\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Pointers and Optionals {#sec-pointer}\n\nOn our next project we are going to build a HTTP server from scratch.\nBut in order to do that, we need to learn more about pointers and how they work in Zig.\nPointers in Zig are similar to pointers in C. But they come with some extra advantages in Zig.\n\nA pointer is an object that contains a memory address. This memory address is the address where\na particular value is stored in memory. It can be any value. Most of the times,\nit's a value that comes from another object (or variable) present in our code.\n\nIn the example below, I'm creating two objects (`number` and `pointer`).\nThe `pointer` object contains the memory address where the value of the `number` object\n(the number 5) is stored. So, that is a pointer in a nutshell. It's a memory\naddress that points to a particular existing value in the memory. You could\nalso say, that, the `pointer` object points to the memory address where the `number` object is\nstored.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\n_ = pointer;\n```\n:::\n\n\n\n\nWe create a pointer object in Zig by using the `&` operator. When you put this operator\nbefore the name of an existing object, you get the memory address of this object as result.\nWhen you store this memory address inside a new object, this new object becomes a pointer object.\nBecause it stores a memory address.\n\nPeople mostly use pointers as an alternative way to access a particular value.\nFor example, I can use the `pointer` object to access the value stored by\nthe `number` object. This operation of accessing the value that the\npointer \"points to\" is normally called of *dereferencing the pointer*.\nWe can dereference a pointer in Zig by using the `*` method of the pointer object. Like in the example\nbelow, where we take the number 5 pointed by the `pointer` object,\nand double it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\nconst doubled = 2 * pointer.*;\nstd.debug.print(\"{d}\\n\", .{doubled});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n10\n```\n\n\n:::\n:::\n\n\n\n\n\nThis syntax to dereference the pointer is nice. Because we can easily chain it with\nmethods of the value pointed by the pointer. We can use the `User` struct that we have\ncreated in @sec-structs-and-oop as an example. If you comeback to that section,\nyou will see that this struct have a method named `print_name()`.\n\nSo, for example, if we have an user object, and a pointer that points to this user object,\nwe can use the pointer to access this user object, and, at the same time, call the method `print_name()`\non it, by chaining the dereference method (`*`) with the `print_name()` method. Like in the\nexample below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst u = User.init(1, \"pedro\", \"email@gmail.com\");\nconst pointer = &u;\ntry pointer.*.print_name();\n```\n:::\n\n\n\n\n```\npedro\n```\n\nWe can also use pointers to effectively alter the value of an object.\nFor example, I could use the `pointer` object to set\nthe value of the object `number` to 6, like in the example below.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\n\n\n\nTherefore, as I mentioned earlier, people use pointers as an alternative way to access a particular value.\nAnd they use it especially when they do not want to \"move\" these values around. There are situations where,\nyou want to access a particular value in a different scope (i.e., a different location) of your code,\nbut you do not want to \"move\" this value to this new scope (or location) that you are in.\n\nThis matters especially if this value is big in size. Because if it is, then,\nmoving this value becomes an expensive operation to do.\nThe computer will have to spend a considerable amount of time\ncopying this value to this new location.\n\nTherefore, many programmers prefer to avoid this heavy operation of copying the value\nto the new location, by accessing this value through pointers.\nWe are going to talk more about this \"moving operation\" over the next sections.\nFor now, just keep in mind that avoiding this \"move operation\" is\none of main reasons why pointers are used in programming languages.\n\n\n\n\n\n## Constant objects vs variable objects {#sec-pointer-var}\n\nYou can have a pointer that points to a constant object, or, a pointer that points to a variable object.\nBut regardless of who this pointer is, a pointer **must always respect the characteristics of the object that it points to**.\nAs a consequence, if the pointer points to a constant object, then, you cannot use this pointer\nto change the value that it points to. Because it points to a value that is constant. As we discussed in @sec-assignments, you cannot\nchange a value that is constant.\n\nFor example, if I have a `number` object, which is constant, I cannot execute\nthe expression below where I'm trying to change the value of `number` to 6 through\nthe `pointer` object. As demonstrated below, when you try to do something\nlike that, you get a compile time error:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number = 5;\nconst pointer = &number;\npointer.* = 6;\n```\n:::\n\n\n\n\n```\np.zig:6:12: error: cannot assign to constant\n pointer.* = 6;\n```\n\nIf I change the `number` object to be a variable object, by introducing the `var` keyword,\nthen, I can successfully change the value of this object through a pointer, as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\n\n\nYou can see this relationship between \"constant versus variable\" on the data type of\nyour pointer object. In other words, the data type of a pointer object already gives you\nsome clues about whether the value that it points to is constant or not.\n\nWhen a pointer object points to a constant value, then, this pointer have a data type `*const T`,\nwhich means \"a pointer to a constant value of type `T`\".\nIn contrast, if the pointer points to a variable value, then, the type of the pointer is usually `*T`, which is\nsimply \"a pointer to a value of type `T`\".\nHence, whenever you see a pointer object whose data type is in the format `*const T`, then,\nyou know that you cannot use this pointer to change the value that it points to.\nBecause this pointer points to a constant value of type `T`.\n\n\nWe have talked about the value pointed by the pointer being constant or not,\nand the consequences that arises from it. But, what about the pointer object itself? I mean, what happens\nif the pointer object itself is constant or not? Think about it.\nWe can have a constant pointer that points to a constant value.\nBut we can also have a variable pointer that points to a constant value. And vice-versa.\n\nUntil this point, the `pointer` object was always constant,\nbut what does this mean for us? What is the consequence of the\n`pointer` object being constant? The consequence is that\nwe cannot change the pointer object, because it is constant. We can use the\npointer object in multiple ways, but we cannot change the\nmemory address that is inside this pointer object.\n\nHowever, if we mark the `pointer` object as a variable object,\nthen, we can change the memory address pointed by this `pointer` object.\nThe example below demonstrates that. Notice that the object pointed\nby the `pointer` object changes from `c1` to `c2`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c1: u8 = 5;\nconst c2: u8 = 6;\nvar pointer = &c1;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\npointer = &c2;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\n```\n:::\n\n\n\n\n```\n5\n6\n```\n\nThus, by setting the `pointer` object to a `var` or `const` object,\nyou specify if the memory address contained in this pointer object can change or not\nin your program. On the other side, you can change the value pointed by the pointer,\nif, and only if this value is stored in a variable object. If this value\nis in a constant object, then, you cannot change this value through a pointer.\n\n\n## Types of pointer\n\nIn Zig, there are two types of pointers [@zigdocs], which are:\n\n- single-item pointer (`*`);\n- many-item pointer (`[*]`);\n\n\nSingle-item pointer objects are objects whose data types are in the format `*T`.\nSo, for example, if an object have a data type `*u32`, it means that, this\nobject contains a single-item pointer that points to an unsigned 32-bit integer value.\nAs another example, if an object have type `*User`, then, it contains\na single-item pointer to an `User` value.\n\nIn contrast, many-item pointers are objects whose data types are in the format `[*]T`.\nNotice that the star symbol (`*`) is now inside a pair of brackets (`[]`). If the star\nsymbol is inside a pair of brackets, you know that this object is a many-item pointer.\n\nWhen you apply the `&` operator over an object, you will always get a single-item pointer.\nMany-item pointers are more of a \"internal type\" of the language, more closely\nrelated to slices. So, when you deliberately create a pointer with the `&` operator,\nyou always get a single-item pointer as result.\n\n\n\n## Pointer arithmetic\n\nPointer arithmetic is available in Zig, and they work the same way they work in C.\nWhen you have a pointer that points to an array, the pointer usually points to\nthe first element in the array, and you can use pointer arithmetic to\nadvance this pointer and access the other elements in the array.\n\n\nNotice in the example below, that initially, the `ptr` object was pointing\nto the first element in the array `ar`. But then, I started to walk through the array, by advancing\nthe pointer with simple pointer arithmetic.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{ 1, 2, 3, 4 };\nvar ptr: [*]const i32 = &ar;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\n```\n:::\n\n\n\n\n```\n1\n2\n3\n```\n\nAlthough you can create a pointer to an array like that, and\nstart to walk through this array by using pointer arithmetic,\nin Zig, we prefer to use slices, which were presented in @sec-arrays.\n\nBehind the hood, slices already are pointers,\nand they also come with the `len` property, which indicates\nhow many elements are in the slice. This is good because the `zig` compiler\ncan use it to check for potential buffer overflows, and other problems like that.\n\nAlso, you don't need to use pointer arithmetic to walk through the elements\nof a slice. You can simply use the `slice[index]` syntax to directly access\nany element you want in the slice.\nAs I mentioned in @sec-arrays, you can get a slice from an array by using\na range selector inside brackets. In the example below, I'm creating\na slice (`sl`) that covers the entire `ar` array. I can access any\nelement of `ar` from this slice, and, the slice itself already is a pointer\nbehind the hood.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{1,2,3,4};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\n\n## Optionals and Optional Pointers\n\nLet's talk about optionals and how they relate to pointers in Zig.\nBy default, objects in Zig are **non-nullable**. This means that, in Zig,\nyou can safely assume that any object in your source code is not null.\n\nThis is a powerful feature of Zig when you compare it to the developer experience in C.\nBecause in C, any object can be null at any point, and, as consequence, a pointer in C\nmight point to a null value. This is a common source of undefined behaviour in C.\nWhen programmers work with pointers in C, they have to constantly check if\ntheir pointers are pointing to null values or not.\n\nIf for some reason, your Zig code produces a null value somewhere, and, this null\nvalue ends up in an object that is non-nullable, a runtime error is always\nraised by your Zig program. Take the program below as an example.\nThe `zig` compiler can see the `null` value at compile time, and, as result,\nit raises a compile time error. But, if a `null` value is raised during\nruntime, a runtime error is also raised by the Zig program, with a\n\"attempt to use null value\" message.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nnumber = null;\n```\n:::\n\n\n\n```\np5.zig:5:14: error: expected type 'u8',\n found '@TypeOf(null)'\n number = null;\n ^~~~\n```\n\n\nYou don't get this type of safety in C.\nIn C, you don't get warnings or errors about null values being produced in your program.\nIf for some reason, your code produces a null value in C, most of the times, you end up getting a segmentation fault error\nas result, which can mean many things.\nThat is why programmers have to constantly check for null values in C.\n\nPointers in Zig are also, by default, **non-nullable**. This is another amazing\nfeature in Zig. So, you can safely assume that any pointer that you create in\nyour Zig code is pointing to a non-null value.\nTherefore, you don't have this heavy work of checking if the pointers you create\nin Zig are pointing to a null value.\n\n\n### What are optionals?\n\nOk, we know now that all objects are non-nullable by default in Zig.\nBut what if we actually need to use an object that might receive a null value?\nHere is where optionals come in.\n\nAn optional object in Zig is an object that can be null.\nTo mark an object as optional, we use the `?` operator. When you put\nthis `?` operator right before the data type of an object, you transform\nthis data type into an optional data type, and the object becomes an optional object.\n\nTake the snippet below as an example. We are creating a new variable object\ncalled `num`. This object have the data type `?i32`, which means that,\nthis object contains either a signed 32-bit integer (`i32`), or, a null value.\nBoth alternatives are valid values to the `num` object.\nThat is why, I can actually change the value of this object to null, and,\nno errors are raised by the `zig` compiler, as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\nnum = null;\n```\n:::\n\n\n\n\n### Optional pointers\n\nYou can also mark a pointer object as an optional pointer, meaning that,\nthis object contains either a null value, or, a pointer that points to a value.\nWhen you mark a pointer as optional, the data type of this pointer object\nbecomes `?*const T` or `?*T`, depending if the value pointed by the pointer\nis a constant value or not. The `?` identifies the object as optional, while\nthe `*` identifies it as a pointer object.\n\nIn the example below, we are creating a variable object named `num`, and an\noptional pointer object named `ptr`. Notice that the data type of the object\n`ptr` indicates that it's either a null value, or a pointer to an `i32` value.\nAlso, notice that the pointer object (`ptr`) can be marked as optional, even if\nthe object `num` is not optional.\n\nWhat this code tells us is that, the `num` variable will never contain a null value.\nThis variable will always contain a valid `i32` value. But in contrast, the `ptr` object might contain either a null\nvalue, or, a pointer to an `i32` value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: i32 = 5;\nvar ptr: ?*i32 = #\nptr = null;\nnum = 6;\n```\n:::\n\n\n\n\nBut what happens if we turn the table, and mark the `num` object as optional,\ninstead of the pointer object. If we do that, then, the pointer object is\nnot optional anymore. It would be a similar (although different) result. Because then, we would have\na pointer to an optional value. In other words, a pointer to a value that is either a\nnull value, or, a not-null value.\n\nIn the example below, we are recreating this idea. Now, the `ptr` object\nhave a data type of `*?i32`, instead of `?*i32`. Notice that the `*` symbol comes before of `?`\nthis time. So now, we have a pointer that points to a value that is either null\n, or, a signed 32-bit integer.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\n// ptr have type `*?i32`, instead of `?*i32`.\nconst ptr = #\n_ = ptr;\n```\n:::\n\n\n\n\n\n### Null handling in optionals {#sec-null-handling}\n\nWhen you have an optional object in your Zig code, you have to explicitly handle\nthe possibility of this object being null. It's like error-handling with `try` and `catch`.\nIn Zig you also have to handle null values like if they were a type of error.\n\nWe can do that, by using either:\n\n- an if statement, like you would do in C.\n- the `orelse` keyword.\n- unwrap the optional value with the `?` method.\n\nWhen you use an if statement, you use a pair of pipes\nto unwrap the optional value, and use this \"unwrapped object\"\ninside the if block.\nUsing the example below as a reference, if the object `num` is null,\nthen, the code inside the if statement is not executed. Otherwise,\nthe if statement will unwrap the object `num` into the `not_null_num`\nobject. This `not_null_num` object is guaranteed to be not null inside\nthe scope of the if statement.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst num: ?i32 = 5;\nif (num) |not_null_num| {\n try stdout.print(\"{d}\\n\", .{not_null_num});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n5\n```\n\n\n:::\n:::\n\n\n\n\nNow, the `orelse` keyword behaves like a binary operator. You connect two expressions with this keyword.\nOn the left side of `orelse`, you provide the expression that might result\nin a null value, and on the right side of `orelse`, you provide another expression\nthat will not result in a null value.\n\nThe idea behind the `orelse` keyword is: if the expression on the left side\nresult in a not-null value, then, this not-null value is used. However,\nif this expression on the left side result in a null value, then, the value\nof the expression on the right side is used instead.\n\nLooking at the example below, since the `x` object is currently null, the\n`orelse` decided to use the alternative value, which is the number 15.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x: ?i32 = null;\nconst dbl = (x orelse 15) * 2;\ntry stdout.print(\"{d}\\n\", .{dbl});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n30\n```\n\n\n:::\n:::\n\n\n\n\nYou can use the if statement or the `orelse` keyword, when you want to\nsolve (or deal with) this null value. However, if there is no clear solution\nto this null value, and the most logic and sane path is to simply panic\nand raise a loud error in your program when this null value is encountered,\nyou can use the `?` method of your optional object.\n\nIn essence, when you use this `?` method, the optional object is unwrapped.\nIf a not-null value is found in the optional object, then, this not-null value is used.\nOtherwise, the `unreachable` keyword is used. You can read more about this\n[`unreacheable` keyword at the official documentation](https://ziglang.org/documentation/master/#unreachable)[^un-docs].\nBut in essence, when you build your Zig source code using the build modes `ReleaseSafe` or `Debug`, this\n`unreacheable` keyword causes the program to panic and raise an error during runtime,\nlike in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn return_null(n: i32) ?i32 {\n if (n == 5) return null;\n return n;\n}\n\npub fn main() !void {\n const x: i32 = 5;\n const y: ?i32 = return_null(x);\n try stdout.print(\"{d}\\n\", .{y.?});\n}\n```\n:::\n\n\n\n\n```\nthread 12767 panic: attempt to use null value\np7.zig:12:34: 0x103419d in main (p7):\n try stdout.print(\"{d}\\n\", .{y.?});\n ^\n```\n\n\n[^un-docs]: .\n", + "supporting": [ + "05-pointers_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/07-build-system/execute-results/html.json b/_freeze/Chapters/07-build-system/execute-results/html.json index daf845bf..8d0f268d 100644 --- a/_freeze/Chapters/07-build-system/execute-results/html.json +++ b/_freeze/Chapters/07-build-system/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "0bac007aec8b6fa9d1efa7b682df4b7b", + "hash": "0286d5b6db10173d3df147400fd019aa", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Build System {#sec-build-system}\n\n\nIn this chapter, we are going to talk about the build system, and how an entire project\nis built in Zig.\nOne key advantage of Zig is that it includes a build system embedded in the language itself.\nThis is great, because then you do not have to depend on an external system, separated\nfrom the compiler, to build your code.\n\n\nYou can find a good description of Zig's build system\non the [article entitled \"Build System\"](https://ziglang.org/learn/build-system/#user-provided-options)[^zig-art1]\nfrom the official Zig's website.\nWe also have the excellent [series of posts written by Felix](https://zig.news/xq/zig-build-explained-part-1-59lf)[^felix].\nHence, this chapter represents an extra resource for you to consult and rely on.\n\n[^felix]: \n[^zig-art1]: \n\nBuilding code is one of the things that Zig is best at. One thing that is particularly\ndifficult in C/C++ and even in Rust, is to cross-compile source code to multiple targets\n(e.g. multiple computer architectures and operating systems),\nand the `zig` compiler is known for being one of the best existing pieces of software\nfor this particular task.\n\n\n\n\n## How source code is built?\n\nWe already have talked about the challenges of building source code in low-level languages\nat @sec-project-files. As we described at that section, programmers invented Build Systems\nto surpass these challenges on the process of building source code in low-level languages.\n\nLow-level languages uses a compiler to compile (or to build) your source code into binary instructions.\nIn C and C++, we normally use compilers like `gcc`, `g++` or `clang` to compile\nour C and C++ source code into these instructions.\nEvery language have its own compiler, and this is no different in Zig.\n\nIn Zig, we have the `zig` compiler to compile our Zig source code into\nbinary instructions that can be executed by our computer.\nIn Zig, the compilation (or the build) process involves\nthe following components:\n\n- The Zig modules that contains your source code;\n- Library files (either a dynamic library or a static library);\n- Compiler flags that tailors the build process to your needs.\n\nThese are the things that you need to connect together in order to build your\nsource code in Zig. In C and C++, you would have an extra component, which are the header files of\nthe libraries that you are using. But header files do not exist in Zig, so, you only need\nto care about them if you are linking your Zig source code with a C library.\nIf that is not your case, you can forget about it.\n\nYour build process is usually organized in a build script. In Zig, we normally\nwrite this build script into a Zig module in the root directory of our project,\nnamed as `build.zig`. You write this build script, then, when you run it, your project\nget's built into binary files that you can use and distribute to your users.\n\nThis build script is normally organized around *target objects*. A target is simply\nsomething to be built, or, in other words, it's something that you want the `zig` compiler\nto build for you. This concept of \"targets\" is present in most Build Systems,\nespecially in CMake[^cmake].\n\n[^cmake]: \n\nThere are four types of target objects that you can build in Zig, which are:\n\n- An executable (e.g. a `.exe` file on Windows).\n- A shared library (e.g. a `.so` file in Linux or a `.dll` file on Windows).\n- A static library (e.g. a `.a` file in Linux or a `.lib` file on Windows).\n- An executable file that executes only unit tests (or, a \"unit tests executable\").\n\nWe are going to talk more about these target objects at @sec-targets.\n\n\n\n## The `build()` function {#sec-build-fun}\n\nA build script in Zig always contains a public (and top-level) `build()` function declared.\nIt is like the `main()` function on the main Zig module of your project, that we discussed at @sec-main-file.\nBut instead of creating the entrypoint to your code, this `build()` function is the entrypoint to the build process.\n\nThis `build()` function should accept a pointer to a `Build` object as input, and it should use this \"build object\" to perform\nthe necessary steps to build your project. The return type of this function is always `void`,\nand this `Build` struct comes directly from the Zig Standard Library (`std.Build`). So, you can \naccess this struct by just importing the Zig Standard Library into your `build.zig` module.\n\nJust as a very simple example, here you can see the source code necessary to build\nan executable file from the `hello.zig` Zig module.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n });\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n\nYou can define and use other functions and objects in this build script. You can also import\nother Zig modules as you would normally do in any other module of your project.\nThe only real requirement for this build script, is to have a public and top-level\n`build()` function defined, that accepts a pointer to a `Build` struct as input.\n\n\n## Target objects {#sec-targets}\n\nAs we described over the previous sections, a build script is composed around target objects.\nEach target object is normally a binary file (or an output) that you want to get from the build process. You can list\nmultiple target objects in your build script, so that the build process generates multiple\nbinary files for you at once.\n\nFor example, maybe you are a developer working in a cross-platform application,\nand, because this application is cross-platform, you probably need to release\nbinary files of your software for each OS supported by your application to your end users.\nThus, you can define a different target object in your build script\nfor each OS (Windows, Linux, etc.) where you want to publish your software.\nThis will make the `zig` compiler to build your project to multiple target OS's at once.\nThe Zig Build System official documentation have a [great code example that demonstrates this strategy](https://ziglang.org/learn/build-system/#handy-examples)[^zig-ex].\n\n[^zig-ex]: \n\n\nA target object is created by the following methods of the `Build` struct that we introduced\nat @sec-build-fun:\n\n- `addExecutable()` creates an executable file;\n- `addSharedLibrary()` creates a shared library file;\n- `addStaticLibrary()` creates a static library file;\n- `addTest()` creates an executable file that executes unit tests.\n\n\nThese functions are methods from the `Build` struct that you receive\nas input of the `build()` function. All of them, create as output\na `Compile` object, which represents a target object to be compiled\nby the `zig` compiler. All of these functions accept a similar struct literal as input.\nThis struct literal defines three essential specs about this target object that you are building:\n`name`, `target` and `root_source_file`.\n\nWe have already seen these three options being used on the previous example,\nwhere we used the `addExecutable()` method to create an executable target object.\nThis example is reproduced below. Notice the use of the `path()` method\nfrom the `Build` struct, to define a path in the `root_source_file` option.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n});\n```\n:::\n\n\n\n\nThe `name` option specify the name that you want to give to the binary file defined\nby this target object. So, in this example, we are building an executable file named `hello`.\nIs common to set this `name` option to the name of your project.\n\n\nFurthermore, the `target` option specify the target computer architecture (or the target operating system) of this\nbinary file. For example, if you want this target object to run on a Windows machine\nthat uses a `x86_64` architecture, you can set this `target` option to `x86_64-windows-gnu` for example.\nThis will make the `zig` compiler to compile the project to run on a `x86_64` Windows machine.\nYou can see the full list of architectures and OS's that the `zig` compiler supports by running\nthe `zig targets` command in the terminal.\n\nNow, if you are building the project to run on the current machine\nthat you are using to run this build script, you can set this `target`\noption to the `host` method of the `Build` object, like we did in the example above.\nThis `host` method identifies the current machine where you are\ncurrently running the `zig` compiler.\n\n\nAt last, the `root_source_file` option specifies the root Zig module of your project.\nThat is the Zig module that contains the entrypoint to your application (i.e. the `main()` function), or, the main API of your library.\nThis also means that, all the Zig modules that compose your project are automatically discovered\nfrom the import statements you have inside this \"root source file\".\nThe `zig` compiler can detect when a Zig module depends on the other through the import statements,\nand, as a result, it can discover the entire map of Zig modules used in your project.\n\nThis is handy, and it is different from what happens in other build systems.\nIn CMake for example, you have to explicitly list the paths to all source files that you want to\ninclude in your build process. This is probably a symptom of the \"lack of conditional\ncompilation\" in the C and C++ compilers. Since they lack this feature, you have\nto explicitly choose which source files should be sent to the C/C++ compiler, because not\nevery C/C++ code is portable or supported in every operating system, and, therefore,\nwould cause a compilation error in the C/C++ compiler.\n\n\nNow, one important detail about the build process is that, you have to **explicitly\ninstall the target objects that you create in your build script**, by using the\n`installArtifact()` method of the `Build` struct.\n\nEverytime you invoke the build process of your project, by calling the `build` command\nof the `zig` compiler, a new directory named `zig-out` is created in the root\ndirectory of your project. This new directory contains the outputs of the build process,\nthat is, the binary files built from your source code.\n\nWhat the `installArtifact()` method do is to install (or copy) the built target objects\nthat you defined to this `zig-out` directory.\nThis means that, if you do not\ninstall the target objects you define in your build script, these target objects are\nessentially discarded at the end of the build process.\n\nFor example, you might be building a project that uses a third party library that is built\ntogether with the project. So, when you build your project, you would need first, to\nbuild the third party library, and then, you link it with the source code of your project.\nSo, in this case, we have two binary files that are generated in the build process (the executable file of your project, and the third party library).\nBut only one is of interest, which is the executable file of our project.\nWe can discard the binary file of the third party library, by simply not installing it\ninto this `zig-out` directory.\n\nThis `installArtifact()` method is pretty straightforward. Just remember to apply it to every\ntarget object that you want to save into the `zig-out` directory, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n});\n\nb.installArtifact(exe);\n```\n:::\n\n\n\n\n\n## Setting the build mode\n\nWe have talked about the three essential options that are set when you create a new target object.\nBut there is also a fourth option that you can use to set the build mode of this target object,\nwhich is the `optimize` option.\nThis option is called this way, because the build modes in Zig are treated more of\nan \"optimization vs safety\" problem. So optimization plays an important role here.\nDon't worry, I'm going back to this question very soon.\n\nIn Zig, we have four build modes (which are listed below). Each one of these build modes offer\ndifferent advantages and characteristics. As we described at @sec-compile-debug-mode, the `zig` compiler\nuses the `Debug` build mode by default, when you don't explicitly choose a build mode.\n\n- `Debug`, mode that produces and includes debugging information in the output of the build process (i.e. the binary file defined by the target object);\n- `ReleaseSmall`, mode that tries to produce a binary file that is small in size;\n- `ReleaseFast`, mode that tries to optimize your code, in order to produce a binary file that is as fast as possible;\n- `ReleaseSafe`, mode that tries to make your code as safe as possible, by including safeguards when possible.\n\nSo, when you build your project, you can set the build mode of your target object to `ReleaseFast` for example, which will tell\nthe `zig` compiler to apply important optimizations in your code. This creates a binary file\nthat simply runs faster on most contexts, because it contains a more optimized version of your code.\nHowever, as a result, we often lose some safety features in our code.\nBecause some safety checks are removed from the final binary file,\nwhich makes your code run faster, but in a less safe manner.\n\nThis choice depends on your current priorities. If you are building a cryptography or banking system, you might\nprefer to prioritize safety in your code, so, you would choose the `ReleaseSafe` build mode, which is a little\nslower to run, but much more secure, because it includes all possible runtime safety checks in the binary file\nbuilt in the build process. In the other hand, if you are writing a game for example, you might prefer to prioritize performance\nover safety, by using the `ReleaseFast` build mode, so that your users can experience faster frame rates in your game.\n\nIn the example below, we are creating the same target object that we have used on previous examples.\nBut this time, we are specifying the build mode of this target object to the `ReleaseSafe` mode.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n .optimize = .ReleaseSafe\n});\nb.installArtifact(exe);\n```\n:::\n\n\n\n\n\n## Setting the version of your build\n\nEverytime you build a target object in your build script, you can assign a version\nnumber to this specific build, following a semantic versioning framework.\nYou can find more about semantic versioning by visiting the [Semantic Versioning website](https://semver.org/)[^semver].\nAnyway, in Zig, you can specify the version of your build, by providing a `SemanticVersion` struct to\nthe `version` option, like in the example below:\n\n\n[^semver]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n .version = .{\n .major = 2, .minor = 9, .patch = 7\n }\n});\nb.installArtifact(exe);\n```\n:::\n\n\n\n\n\n## Detecting the OS in your build script {#sec-detect-os}\n\nIs very common in Build Systems to use different options, or, to include different modules, or,\nto link against different libraries depending on the Operational System (OS)\nthat you are targeting in the build process.\n\nIn Zig, you can detect the target OS of the build process, by looking\nat the `os.tag` inside the `builtin` module from the Zig library.\nIn the example below, we are using an if statement to run some\narbitrary code when the target of the build process is a\nWindows system.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nif (builtin.target.os.tag == .windows) {\n // Code that runs only when the target of\n // the compilation process is Windows.\n}\n```\n:::\n\n\n\n\n\n## Adding a run step to your build process\n\nOne thing that is neat in Rust is that you can compile and run your\nsource code with one single command (`cargo run`) from the Rust compiler.\nWe saw at @sec-compile-run-code how can we perform a similar job in Zig, by\nbuilding and running our Zig source code through the `run` command from the `zig` compiler.\n\nBut how can we, at the same time, build and run the binary file specified by a target object in our\nbuild script?\nThe answer is by including a \"run artifact\" in our build script.\nA run artifact is created through the `addRunArtifact()` method from the `Build` struct.\nWe simply provide as input to this function the target object that describes the binary file that we\nwant to execute. As a result, this function creates a run artifact that is capable of executing\nthis binary file.\n\nIn the example below, we are defining an executable binary file named `hello`,\nand we use this `addRunArtifact()` method to create a run artifact that will execute\nthis `hello` executable file.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"src/hello.zig\"),\n .target = b.host\n});\nb.installArtifact(exe);\nconst run_arti = b.addRunArtifact(exe);\n```\n:::\n\n\n\n\nNow that we have created this run artifact, we need to include it in\nthe build process. We do that by declaring a new step in our build\nscript to call this artifact, through the `step()` method of the `Build`\nstruct.\n\nWe can give any name we want to this step, but, for our\ncontext here, I'm going to name this step as \"run\".\nAlso, I give it a brief description to this step (\"Run the project\").\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst run_step = b.step(\n \"run\", \"Run the project\"\n);\n```\n:::\n\n\n\n\n\nNow that we have declared this \"run step\" we need to tell Zig that\nthis \"run step\" depends on the run artifact.\nIn other words, a run artifact always depends on a \"step\" to effectively be executed.\nBy creating this dependency\nwe finally stablish the necessary commands to build and run the executable file\nfrom the build script.\n\nWe can establish a dependency between the run step and the run artifact\nby using the `dependsOn()` method from the run step. So, we first\ncreate the run step, and then, we link it with the run artifact, by\nusing this `dependsOn()` method from the run step.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nrun_step.dependOn(&run_arti.step);\n```\n:::\n\n\n\n\nThe entire source code of this specific build script that\nwe wrote, piece by piece, in this section, is\navailable in the `build_and_run.zig` module. You can\nsee this module by\n[visiting the official repository of this book](https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_and_run.zig)\n[^module-src].\n\n\n[^module-src]: \n\nWhen you declare a new step in your build script, this step\nbecomes available through the `build` command in the `zig` compiler.\nYou can actually see this step by running `zig build --help` in the terminal, like\nin the example below, where we can see that this new \"run\"\nstep that we declared in the build script appeared in the output.\n\n```bash\nzig build --help\n```\n\n```\nSteps:\n ...\n run Run the project\n ...\n```\n\nNow, everything that we need to is to\ncall this \"run\" step that we created in our build script. We\ncall it by using the name that we gave to this step\nafter the `build` command from the `zig` compiler.\nThis will cause the compiler to build our executable file\nand execute it at the same time.\n\n```bash\nzig build run\n```\n\n## Build unit tests in your project\n\nWe have talked at length about writing unit tests in Zig at @sec-unittests,\nand we also have talked about how to execute these unit tests through\nthe `test` command of the `zig` compiler. However,\nas we did with the `run` command on the previous section, we also might want to\ninclude some commands in our build script to also build and execute the unit tests in our project.\n\nSo, once again, we are going to discuss how a specific built-in command from the `zig` compiler,\n(in this case, the `test` command) can be used in a build script in Zig.\nHere is where a \"test target object\" comes into play.\nAs was described at @sec-targets, we can create a test target object by using the `addTest()` method of\nthe `Build` struct. The first thing that we need to do is to\ndeclare a test target object in our build script.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst test_exe = b.addTest(.{\n .name = \"unit_tests\",\n .root_source_file = b.path(\"src/main.zig\"),\n .target = b.host,\n});\nb.installArtifact(test_exe);\n```\n:::\n\n\n\n\n\nA test target object essentially selects all `test` blocks in all Zig modules\nacross your project, and builds only the source code present inside\nthese `test` blocks in your project. As a result, this target object\ncreates an executable file that contains only the source code present\nin all of these `test` blocks (i.e. the unit tests) in your project.\n\nPerfect! Now that we have declared this test target object, an executable file\nnamed `unit_tests` is built by the `zig` compiler when we trigger the build\nscript with the `build` command. After the build\nprocess is finished, we can simply execute this `unit_tests` executable\nin the terminal.\n\nHowever, if you remember the previous section, we already learned\nhow can we create a run step in our build script, to execute an executable file\nbuilt by the build script.\n\nSo, we could simply add a run step in our build script to run these unit tests\nfrom a single command in the `zig` compiler, to make our lifes easier.\nIn the example below, we demonstrate the commands to\nregister a new build step called \"tests\" in our build script\nto run these unit tests.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst run_arti = b.addRunArtifact(test_exe);\nconst run_step = b.step(\"tests\", \"Run unit tests\");\nrun_step.dependOn(&run_arti.step);\n```\n:::\n\n\n\n\nNow that we registered this new build step, we can trigger it by calling the command below\nin the terminal. You can also checkout the complete source\ncode for this specific build script at the `build_tests.zig` module at the\n[official repository of this book](https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_tests.zig)\n[^module-src2].\n\n\n[^module-src2]: \n\n\n```bash\nzig build tests\n```\n\n\n## Tailoring your build process with user-provided options\n\nSometimes, you want to make a build script that is customizable by the user\nof your project. You can do that by creating user-provided options in\nyour build script. We create an user-provided option by using the\n`option()` method from the `Build` struct.\n\nWith this method, we create a \"build option\" which can be passed\nto the `build.zig` script at the command line. The user have the power of setting\nthis option at the `build` command from the\n`zig` compiler. In other words, each build option that we create\nbecomes a new command line argument that is accessible through the `build` command\nof the compiler.\n\nThese \"user-provided options\" are set by using the prefix `-D` in the command line.\nFor example, if we declare an option named `use_zlib`, that receives a boolean value which\nindicates if we should link our source code to `zlib` or not, we can set the value\nof this option in the command line with `-Duse_zlib`. The code example below\ndemonstrates this idea:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const use_zlib = b.option(\n bool,\n \"use_zlib\",\n \"Should link to zlib?\"\n ) orelse false;\n const exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"example.zig\"),\n .target = b.host,\n });\n if (use_zlib) {\n exe.linkSystemLibrary(\"zlib\");\n }\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n\n```bash\nzig build -Duse_zlib=false\n```\n\n\n## Linking to external libraries\n\n\nOne essential part of every build process is the linking stage.\nThis stage is responsible for combining the multiple object files\nthat represent your code, into a single executable file. It also links\nthis executable file to external libraries, if you use any in your code.\n\nIn Zig, we have two notions of a \"library\", which are: 1) a system's library;\n2) a local library. A system's library is just a library that already is installed\nin your system. While a local library is a library that belongs to the current\nproject. Is a library that is present in your project directory, and\nthat you are building together with your project source code.\n\nThe basic difference between the two, is that a system's library is already\nbuilt and installed in your system, supposedly, and all you need to do\nis to link your source code to this library to start using it.\nWe do that by using the `linkSystemLibrary()` method from a\n`Compile` object. This method accepts the name of the library\nin a string as input. Remember from @sec-targets that a `Compile` object\nis a target object that you declare in your build script.\n\nWhen you link a particular target object with a system's library,\nthe `zig` compiler will use `pkg-config` to find where\nare the binary files and also the header files of this library\nin your system.\nWhen it finds these files, the linker present in the `zig` compiler\nwill link your object files with the files of this library to\nproduce a single binary file for you.\n\nIn the example below, we are creating an executable file named `image_filter`,\nand, we are linking this executable file to the C Standard Library with the\nmethod `linkLibC()`, but we also are linking this executable file to the\nC library `libpng` that is currently installed in my system.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const exe = b.addExecutable(.{\n .name = \"image_filter\",\n .root_source_file = b.path(\"src/main.zig\"),\n .target = target,\n .optimize = optimize,\n });\n exe.linkLibC();\n exe.linkSystemLibrary(\"png\");\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n\nIf you are linking with a C library in your project, is generally a good idea\nto also link your code with the C Standard Library. Because is very likely\nthat this C library uses some functionality of the C Standard Library at some point.\nThe same goes to C++ libraries. So, if you are linking with\nC++ libraries, is a good idea to link your project with the C++\nStandard Library by using the `linkLibCpp()` method.\n\nOn the order side, when you want to link with a local library,\nyou should use the `linkLibrary()` method of a `Compile` object.\nThis method expects to receive another `Compile` object as input.\nThat is, another target object defined in your build script,\nusing either the `addStaticLibrary()` or `addSharedLibrary()` methods\nwhich defines a library to be built.\n\nAs we discussed earlier, a local library is a library\nthat is local to your project, and that is being built together\nwith your project. So, you need to create a target object in your build script\nto build this local library. Then, you link the target objects of interest in your project,\nwith this target object that identifies this local library.\n\nTake a look at this example extracted from the build script of the [`libxev` library](https://github.com/mitchellh/libxev/tree/main)[^libxev2].\nYou can see in this snippet that\nwe are declaring a shared library file, from the `c_api.zig`\nmodule. Then, later in the build script, we declare an\nexecutable file named `\"dynamic-binding-test\"`, which\nlinks to this shared library that we defined earlier\nin the script.\n\n[^libxev2]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst optimize = b.standardOptimizeOption(.{});\nconst target = b.standardTargetOptions(.{});\n\nconst dynamic_lib = b.addSharedLibrary(.{\n .name = dynamic_lib_name,\n .root_source_file = b.path(\"src/c_api.zig\"),\n .target = target,\n .optimize = optimize,\n});\nb.installArtifact(dynamic_lib);\n// ... more lines in the script\nconst dynamic_binding_test = b.addExecutable(.{\n .name = \"dynamic-binding-test\",\n .target = target,\n .optimize = optimize,\n});\ndynamic_binding_test.linkLibrary(dynamic_lib);\n```\n:::\n\n\n\n\n\n\n## Building C code {#sec-building-c-code}\n\nThe `zig` compiler comes with a C compiler embedded in it. In other words,\nyou can use the `zig` compiler to build C projects. This C compiler is available\nthrough the `cc` command of the `zig` compiler.\n\nAs an example, let's use the famous [FreeType library](https://freetype.org/)[^freetype].\nFreeType is one of the most widely used pieces of software in the world.\nIt is a C library designed to produce high-quality fonts. But it is also\nheavily used in the industry to natively render text and fonts\nin the screen of your computer.\n\nIn this section, we are going to write a build script, piece by piece, that is capable\nof building the FreeType project from source.\nYou can find the source code of this build script on the\n[`freetype-zig` repository](https://github.com/pedropark99/freetype-zig/tree/main)[^freetype-zig]\navailable at GitHub.\n\n[^freetype]: \n[^freetype-zig]: \n\nAfter you download the source code of FreeType from the official website[^freetype],\nyou can start writing the `build.zig` module. We begin by defining the target object\nthat defines the binary file that we want to compile.\n\nAs an example, I will build the project as a static library file using the `addStaticLibrary()` method\nto create the target object.\nAlso, since FreeType is a C library, I will also link the library\nagainst `libc` through the `linkLibC()` method, to guarantee that any use\nof the C Standard Library is covered in the compilation process.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst target = b.standardTargetOptions(.{});\nconst opti = b.standardOptimizeOption(.{});\nconst lib = b.addStaticLibrary(.{\n .name = \"freetype\",\n .optimize = opti,\n .target = target,\n});\nlib.linkLibC();\n```\n:::\n\n\n\n\n### Creating C compiler flags\n\nCompiler flags are also known as \"compiler options\" by many programmers,\nor also, as \"command options\" in the GCC official documentation.\nIt's fair to also call them as the \"command-line arguments\" of the C compiler.\nIn general, we use compiler flags to turn on (or turn off) some features from the compiler,\nor to tweak the compilation process to fit the needs of our project.\n\nIn build scripts written in Zig, we normally list the C compiler flags to be used in the compilation process\nin a simple array, like in the example below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c_flags = [_][]const u8{\n \"-Wall\",\n \"-Wextra\",\n \"-Werror\",\n};\n```\n:::\n\n\n\n\nIn theory, there is nothing stopping you from using this array to add \"include paths\" (with the `-I` flag)\nor \"library paths\" (with the `-L` flag) to the compilation process. But there are formal ways in Zig to\nadd these types of paths in the compilation process. Both are discussed at @sec-include-paths\nand @sec-library-paths.\n\nAnyway, in Zig, we add C flags to the build process together with the C files that we want to compile, by using the\n`addCSourceFile()` and `addCSourceFiles()` methods. In the example above, we have just declared\nthe C flags that we want to use. But we haven't added them to the build process yet.\nTo do that, we also need to list the C files to be compiled.\n\n### Listing your C files\n\nThe C files that contains \"cross-platform\" source code are listed in the `c_source_files`\nobject below. These are the C files that are included by default in every platform\nsupported by the FreeType library. Now, since the amount of C files in the FreeType library is big,\nI have omitted the rest of the files in the code example below, for brevity purposes.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c_source_files = [_][]const u8{\n \"src/autofit/autofit.c\",\n \"src/base/ftbase.c\",\n // ... and many other C files.\n};\n```\n:::\n\n\n\n\nNow, in addition to \"cross-platform\" source code, we also have some C files in the FreeType project\nthat are platform-specific, meaning that, they contain source code that can only be compiled in specific platforms,\nand, as a result, they are only included in the build process on these specific target platforms.\nThe objects that list these C files are exposed in the code example below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst windows_c_source_files = [_][]const u8{\n \"builds/windows/ftdebug.c\",\n \"builds/windows/ftsystem.c\"\n};\nconst linux_c_source_files = [_][]const u8{\n \"src/base/ftsystem.c\",\n \"src/base/ftdebug.c\"\n};\n```\n:::\n\n\n\n\nNow that we declared both the files that we want to include and the C compiler flags to be used,\nwe can add them to the target object that describes the FreeType library, by using the\n`addCSourceFile()` and `addCSourceFiles()` methods.\n\nBoth of these functions are methods from a `Compile` object (i.e. a target object).\nThe `addCSourceFile()` method is capable of adding a single C file to the target object,\nwhile the `addCSourceFiles()` method is used to add multiple C files in a single command.\nYou might prefer to use `addCSourceFile()` when you need to use different compiler flags\non specific C files in your project. But, if you can use the same compiler flags\nacross all C files, then, you will probably find `addCSourceFiles()` a better choice.\n\nNotice that we are using the `addCSourceFiles()` method in the example below,\nto add both the C files and the C compiler flags. Also notice that we\nare using the `os.tag` that we learned about at @sec-detect-os, to add the platform-specific\nC files.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nlib.addCSourceFiles(\n &c_source_files, &c_flags\n);\n\nswitch (builtin.target.os.tag) {\n .windows => {\n lib.addCSourceFiles(\n &windows_c_source_files,\n &c_flags\n );\n },\n .linux => {\n lib.addCSourceFiles(\n &linux_c_source_files,\n &c_flags\n );\n },\n else => {},\n}\n```\n:::\n\n\n\n\n\n### Defining C Macros\n\nC Macros are an essential part of the C programming language,\nand they are commonly defined through the `-D` flag from a C compiler.\nIn Zig, you can define a C Macro to be used in your build process\nby using the `defineCMacro()` method from the target object that\ndefines the binary file that you are building.\n\nIn the example below, we are using the `lib` object that we have defined\non the previous sections to define some C Macros used by the FreeType project\nin the compilation process. These C Macros specify if FreeType\nshould (or should not) include functionalities from different\nexternal libraries.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nlib.defineCMacro(\"FT_DISABLE_ZLIB\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_PNG\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_HARFBUZZ\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_BZIP2\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_BROTLI\", \"TRUE\");\nlib.defineCMacro(\"FT2_BUILD_LIBRARY\", \"TRUE\");\n```\n:::\n\n\n\n\n\n### Adding library paths {#sec-library-paths}\n\nLibrary paths are paths in your computer where the C compiler will look (or search) for\nlibrary files to link against your source code. In other words, when you use a library in your\nC source code, and you ask the C compiler to link your source code against this library,\nthe C compiler will search for the binary files of this library across the paths listed\nin this \"library paths\" set.\n\nThese paths are platform specific, and, by default, the C compiler starts by looking at a\npre-defined set of places in your computer. But you can add more paths (or more places)\nto this list. For example, you may have a library installed in a non-conventional place of your\ncomputer, and you can make the C compiler \"see\" this \"non-conventional place\" by adding this path\nto this list of pre-defined paths.\n\nIn Zig, you can add more paths to this set by using the `addLibraryPath()` method from your target object.\nFirst, you defined a `LazyPath` object, containing the path you want to add, then,\nyou provide this object as input to the `addLibraryPath()` method, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst lib_path: std.Build.LazyPath = .{\n .cwd_relative = \"/usr/local/lib/\"\n};\nlib.addLibraryPath(lib_path);\n```\n:::\n\n\n\n\n\n\n\n### Adding include paths {#sec-include-paths}\n\nThe preprocessor search path is a popular concept from the\nC community, but it is also known by many C programmers as \"include paths\", because\nthe paths in this \"search path\" relate to the `#include` statements found in the C files.\n\nInclude paths are similar to library paths. They are a set of pre-defined places in your computer where\nthe C compiler will look for files during the compilation process. But instead of looking for\nlibrary files, the include paths are places where the compiler looks for header files included\nin your C source code.\nThis is why many C programmers prefer to call these paths as the \"preprocessor search path\".\nBecause header files are processed during the preprocessor stage of the compilation\nprocess.\n\nSo, every header file that you include in your C source code, through a `#include` statements needs to\nbe found somewhere, and the C compiler will search for this header file across the paths listed in this \"include paths\" set.\nInclude paths are added to the compilation process through the `-I` flag.\n\nIn Zig, you can add new paths to this pre-defined set of paths, by using the `addIncludePath()` method\nfrom your target object. This method also accepts a `LazyPath` object as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst inc_path: std.Build.LazyPath = .{\n .path = \"./include\"\n};\nlib.addIncludePath(inc_path);\n```\n:::\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Build System {#sec-build-system}\n\n\nIn this chapter, we are going to talk about the build system, and how an entire project\nis built in Zig.\nOne key advantage of Zig is that it includes a build system embedded in the language itself.\nThis is great, because then you do not have to depend on an external system, separated\nfrom the compiler, to build your code.\n\n\nYou can find a good description of Zig's build system\nin the [article entitled \"Build System\"](https://ziglang.org/learn/build-system/#user-provided-options)[^zig-art1]\nfrom the official Zig's website.\nWe also have the excellent [series of posts written by Felix](https://zig.news/xq/zig-build-explained-part-1-59lf)[^felix].\nHence, this chapter represents an extra resource for you to consult and rely on.\n\n[^felix]: \n[^zig-art1]: \n\nBuilding code is one of the things that Zig is best at. One thing that is particularly\ndifficult in C/C++ and even in Rust, is to cross-compile source code to multiple targets\n(e.g. multiple computer architectures and operating systems),\nand the `zig` compiler is known for being one of the best existing pieces of software\nfor this particular task.\n\n\n\n\n## How source code is built?\n\nWe already have talked about the challenges of building source code in low-level languages\nin @sec-project-files. As we described at that section, programmers invented Build Systems\nto surpass these challenges on the process of building source code in low-level languages.\n\nLow-level languages uses a compiler to compile (or to build) your source code into binary instructions.\nIn C and C++, we normally use compilers like `gcc`, `g++` or `clang` to compile\nour C and C++ source code into these instructions.\nEvery language have its own compiler, and this is no different in Zig.\n\nIn Zig, we have the `zig` compiler to compile our Zig source code into\nbinary instructions that can be executed by our computer.\nIn Zig, the compilation (or the build) process involves\nthe following components:\n\n- The Zig modules that contains your source code;\n- Library files (either a dynamic library or a static library);\n- Compiler flags that tailors the build process to your needs.\n\nThese are the things that you need to connect together in order to build your\nsource code in Zig. In C and C++, you would have an extra component, which are the header files of\nthe libraries that you are using. But header files do not exist in Zig, so, you only need\nto care about them if you are linking your Zig source code with a C library.\nIf that is not your case, you can forget about it.\n\nYour build process is usually organized in a build script. In Zig, we normally\nwrite this build script into a Zig module in the root directory of our project,\nnamed as `build.zig`. You write this build script, then, when you run it, your project\ngets built into binary files that you can use and distribute to your users.\n\nThis build script is normally organized around *target objects*. A target is simply\nsomething to be built, or, in other words, it's something that you want the `zig` compiler\nto build for you. This concept of \"targets\" is present in most Build Systems,\nespecially in CMake[^cmake].\n\n[^cmake]: \n\nThere are four types of target objects that you can build in Zig, which are:\n\n- An executable (e.g. a `.exe` file on Windows).\n- A shared library (e.g. a `.so` file in Linux or a `.dll` file on Windows).\n- A static library (e.g. a `.a` file in Linux or a `.lib` file on Windows).\n- An executable file that executes only unit tests (or, a \"unit tests executable\").\n\nWe are going to talk more about these target objects in @sec-targets.\n\n\n\n## The `build()` function {#sec-build-fun}\n\nA build script in Zig always contains a public (and top-level) `build()` function declared.\nIt's like the `main()` function in the main Zig module of your project, that we discussed in @sec-main-file.\nBut instead of creating the entrypoint to your code, this `build()` function is the entrypoint to the build process.\n\nThis `build()` function should accept a pointer to a `Build` object as input, and it should use this \"build object\" to perform\nthe necessary steps to build your project. The return type of this function is always `void`,\nand this `Build` struct comes directly from the Zig Standard Library (`std.Build`). So, you can\naccess this struct by just importing the Zig Standard Library into your `build.zig` module.\n\nJust as a very simple example, here you can see the source code necessary to build\nan executable file from the `hello.zig` Zig module.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n });\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n\nYou can define and use other functions and objects in this build script. You can also import\nother Zig modules as you would normally do in any other module of your project.\nThe only real requirement for this build script, is to have a public and top-level\n`build()` function defined, that accepts a pointer to a `Build` struct as input.\n\n\n## Target objects {#sec-targets}\n\nAs we described over the previous sections, a build script is composed around target objects.\nEach target object is normally a binary file (or an output) that you want to get from the build process. You can list\nmultiple target objects in your build script, so that the build process generates multiple\nbinary files for you at once.\n\nFor example, maybe you are a developer working in a cross-platform application,\nand, because this application is cross-platform, you probably need to release\nbinary files of your software for each OS supported by your application to your end users.\nThus, you can define a different target object in your build script\nfor each OS (Windows, Linux, etc.) where you want to publish your software.\nThis will make the `zig` compiler to build your project to multiple target OS's at once.\nThe Zig Build System official documentation have a [great code example that demonstrates this strategy](https://ziglang.org/learn/build-system/#handy-examples)[^zig-ex].\n\n[^zig-ex]: \n\n\nA target object is created by the following methods of the `Build` struct that we introduced\nin @sec-build-fun:\n\n- `addExecutable()` creates an executable file;\n- `addSharedLibrary()` creates a shared library file;\n- `addStaticLibrary()` creates a static library file;\n- `addTest()` creates an executable file that executes unit tests.\n\n\nThese functions are methods from the `Build` struct that you receive\nas input of the `build()` function. All of them, create as output\na `Compile` object, which represents a target object to be compiled\nby the `zig` compiler. All of these functions accept a similar struct literal as input.\nThis struct literal defines three essential specs about this target object that you are building:\n`name`, `target` and `root_source_file`.\n\nWe have already seen these three options being used on the previous example,\nwhere we used the `addExecutable()` method to create an executable target object.\nThis example is reproduced below. Notice the use of the `path()` method\nfrom the `Build` struct, to define a path in the `root_source_file` option.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n});\n```\n:::\n\n\n\n\nThe `name` option specify the name that you want to give to the binary file defined\nby this target object. So, in this example, we are building an executable file named `hello`.\nIt's common to set this `name` option to the name of your project.\n\n\nFurthermore, the `target` option specify the target computer architecture (or the target operating system) of this\nbinary file. For example, if you want this target object to run on a Windows machine\nthat uses a `x86_64` architecture, you can set this `target` option to `x86_64-windows-gnu` for example.\nThis will make the `zig` compiler to compile the project to run on a `x86_64` Windows machine.\nYou can see the full list of architectures and OS's that the `zig` compiler supports by running\nthe `zig targets` command in the terminal.\n\nNow, if you are building the project to run on the current machine\nthat you are using to run this build script, you can set this `target`\noption to the `host` method of the `Build` object, like we did in the example above.\nThis `host` method identifies the current machine where you are\ncurrently running the `zig` compiler.\n\n\nAt last, the `root_source_file` option specifies the root Zig module of your project.\nThat is the Zig module that contains the entrypoint to your application (i.e., the `main()` function), or, the main API of your library.\nThis also means that, all the Zig modules that compose your project are automatically discovered\nfrom the import statements you have inside this \"root source file\".\nThe `zig` compiler can detect when a Zig module depends on the other through the import statements,\nand, as a result, it can discover the entire map of Zig modules used in your project.\n\nThis is handy, and it's different from what happens in other build systems.\nIn CMake for example, you have to explicitly list the paths to all source files that you want to\ninclude in your build process. This is probably a symptom of the \"lack of conditional\ncompilation\" in the C and C++ compilers. Since they lack this feature, you have\nto explicitly choose which source files should be sent to the C/C++ compiler, because not\nevery C/C++ code is portable or supported in every operating system, and, therefore,\nwould cause a compilation error in the C/C++ compiler.\n\n\nNow, one important detail about the build process is that, you have to **explicitly\ninstall the target objects that you create in your build script**, by using the\n`installArtifact()` method of the `Build` struct.\n\nEverytime you invoke the build process of your project, by calling the `build` command\nof the `zig` compiler, a new directory named `zig-out` is created in the root\ndirectory of your project. This new directory contains the outputs of the build process,\nthat is, the binary files built from your source code.\n\nWhat the `installArtifact()` method do is to install (or copy) the built target objects\nthat you defined to this `zig-out` directory.\nThis means that, if you do not\ninstall the target objects you define in your build script, these target objects are\nessentially discarded at the end of the build process.\n\nFor example, you might be building a project that uses a third party library that is built\ntogether with the project. So, when you build your project, you would need first, to\nbuild the third party library, and then, you link it with the source code of your project.\nSo, in this case, we have two binary files that are generated in the build process (the executable file of your project, and the third party library).\nBut only one is of interest, which is the executable file of our project.\nWe can discard the binary file of the third party library, by simply not installing it\ninto this `zig-out` directory.\n\nThis `installArtifact()` method is pretty straightforward. Just remember to apply it to every\ntarget object that you want to save into the `zig-out` directory, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n});\n\nb.installArtifact(exe);\n```\n:::\n\n\n\n\n\n## Setting the build mode\n\nWe have talked about the three essential options that are set when you create a new target object.\nBut there is also a fourth option that you can use to set the build mode of this target object,\nwhich is the `optimize` option.\nThis option is called this way, because the build modes in Zig are treated more of\nan \"optimization vs safety\" problem. So optimization plays an important role here.\nDon't worry, I'm going back to this question very soon.\n\nIn Zig, we have four build modes (which are listed below). Each one of these build modes offer\ndifferent advantages and characteristics. As we described in @sec-compile-debug-mode, the `zig` compiler\nuses the `Debug` build mode by default, when you don't explicitly choose a build mode.\n\n- `Debug`, mode that produces and includes debugging information in the output of the build process (i.e., the binary file defined by the target object);\n- `ReleaseSmall`, mode that tries to produce a binary file that is small in size;\n- `ReleaseFast`, mode that tries to optimize your code, in order to produce a binary file that is as fast as possible;\n- `ReleaseSafe`, mode that tries to make your code as safe as possible, by including safeguards when possible.\n\nSo, when you build your project, you can set the build mode of your target object to `ReleaseFast` for example, which will tell\nthe `zig` compiler to apply important optimizations in your code. This creates a binary file\nthat simply runs faster on most contexts, because it contains a more optimized version of your code.\nHowever, as a result, we often lose some safety features in our code.\nBecause some safety checks are removed from the final binary file,\nwhich makes your code run faster, but in a less safe manner.\n\nThis choice depends on your current priorities. If you are building a cryptography or banking system, you might\nprefer to prioritize safety in your code, so, you would choose the `ReleaseSafe` build mode, which is a little\nslower to run, but much more secure, because it includes all possible runtime safety checks in the binary file\nbuilt in the build process. In the other hand, if you are writing a game for example, you might prefer to prioritize performance\nover safety, by using the `ReleaseFast` build mode, so that your users can experience faster frame rates in your game.\n\nIn the example below, we are creating the same target object that we have used on previous examples.\nBut this time, we are specifying the build mode of this target object to the `ReleaseSafe` mode.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n .optimize = .ReleaseSafe\n});\nb.installArtifact(exe);\n```\n:::\n\n\n\n\n\n## Setting the version of your build\n\nEverytime you build a target object in your build script, you can assign a version\nnumber to this specific build, following a semantic versioning framework.\nYou can find more about semantic versioning by visiting the [Semantic Versioning website](https://semver.org/)[^semver].\nAnyway, in Zig, you can specify the version of your build, by providing a `SemanticVersion` struct to\nthe `version` option, like in the example below:\n\n\n[^semver]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n .version = .{\n .major = 2, .minor = 9, .patch = 7\n }\n});\nb.installArtifact(exe);\n```\n:::\n\n\n\n\n\n## Detecting the OS in your build script {#sec-detect-os}\n\nIt's very common in Build Systems to use different options, or, to include different modules, or,\nto link against different libraries depending on the Operational System (OS)\nthat you are targeting in the build process.\n\nIn Zig, you can detect the target OS of the build process, by looking\nat the `os.tag` inside the `builtin` module from the Zig library.\nIn the example below, we are using an if statement to run some\narbitrary code when the target of the build process is a\nWindows system.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nif (builtin.target.os.tag == .windows) {\n // Code that runs only when the target of\n // the compilation process is Windows.\n}\n```\n:::\n\n\n\n\n\n## Adding a run step to your build process\n\nOne thing that is neat in Rust is that you can compile and run your\nsource code with one single command (`cargo run`) from the Rust compiler.\nWe saw in @sec-compile-run-code how can we perform a similar job in Zig, by\nbuilding and running our Zig source code through the `run` command from the `zig` compiler.\n\nBut how can we, at the same time, build and run the binary file specified by a target object in our\nbuild script?\nThe answer is by including a \"run artifact\" in our build script.\nA run artifact is created through the `addRunArtifact()` method from the `Build` struct.\nWe simply provide as input to this function the target object that describes the binary file that we\nwant to execute. As a result, this function creates a run artifact that is capable of executing\nthis binary file.\n\nIn the example below, we are defining an executable binary file named `hello`,\nand we use this `addRunArtifact()` method to create a run artifact that will execute\nthis `hello` executable file.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"src/hello.zig\"),\n .target = b.host\n});\nb.installArtifact(exe);\nconst run_arti = b.addRunArtifact(exe);\n```\n:::\n\n\n\n\nNow that we have created this run artifact, we need to include it in\nthe build process. We do that by declaring a new step in our build\nscript to call this artifact, through the `step()` method of the `Build`\nstruct.\n\nWe can give any name we want to this step, but, for our\ncontext here, I'm going to name this step as \"run\".\nAlso, I give it a brief description to this step (\"Run the project\").\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst run_step = b.step(\n \"run\", \"Run the project\"\n);\n```\n:::\n\n\n\n\n\nNow that we have declared this \"run step\" we need to tell Zig that\nthis \"run step\" depends on the run artifact.\nIn other words, a run artifact always depends on a \"step\" to effectively be executed.\nBy creating this dependency\nwe finally stablish the necessary commands to build and run the executable file\nfrom the build script.\n\nWe can establish a dependency between the run step and the run artifact\nby using the `dependsOn()` method from the run step. So, we first\ncreate the run step, and then, we link it with the run artifact, by\nusing this `dependsOn()` method from the run step.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nrun_step.dependOn(&run_arti.step);\n```\n:::\n\n\n\n\nThe entire source code of this specific build script that\nwe wrote, piece by piece, in this section, is\navailable in the `build_and_run.zig` module. You can\nsee this module by\n[visiting the official repository of this book](https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_and_run.zig)\n[^module-src].\n\n\n[^module-src]: \n\nWhen you declare a new step in your build script, this step\nbecomes available through the `build` command in the `zig` compiler.\nYou can actually see this step by running `zig build --help` in the terminal, like\nin the example below, where we can see that this new \"run\"\nstep that we declared in the build script appeared in the output.\n\n```bash\nzig build --help\n```\n\n```\nSteps:\n ...\n run Run the project\n ...\n```\n\nNow, everything that we need to is to\ncall this \"run\" step that we created in our build script. We\ncall it by using the name that we gave to this step\nafter the `build` command from the `zig` compiler.\nThis will cause the compiler to build our executable file\nand execute it at the same time.\n\n```bash\nzig build run\n```\n\n## Build unit tests in your project\n\nWe have talked at length about writing unit tests in Zig in @sec-unittests,\nand we also have talked about how to execute these unit tests through\nthe `test` command of the `zig` compiler. However,\nas we did with the `run` command on the previous section, we also might want to\ninclude some commands in our build script to also build and execute the unit tests in our project.\n\nSo, once again, we are going to discuss how a specific built-in command from the `zig` compiler,\n(in this case, the `test` command) can be used in a build script in Zig.\nHere is where a \"test target object\" comes into play.\nAs was described in @sec-targets, we can create a test target object by using the `addTest()` method of\nthe `Build` struct. The first thing that we need to do is to\ndeclare a test target object in our build script.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst test_exe = b.addTest(.{\n .name = \"unit_tests\",\n .root_source_file = b.path(\"src/main.zig\"),\n .target = b.host,\n});\nb.installArtifact(test_exe);\n```\n:::\n\n\n\n\n\nA test target object essentially selects all `test` blocks in all Zig modules\nacross your project, and builds only the source code present inside\nthese `test` blocks in your project. As a result, this target object\ncreates an executable file that contains only the source code present\nin all of these `test` blocks (i.e., the unit tests) in your project.\n\nPerfect! Now that we have declared this test target object, an executable file\nnamed `unit_tests` is built by the `zig` compiler when we trigger the build\nscript with the `build` command. After the build\nprocess is finished, we can simply execute this `unit_tests` executable\nin the terminal.\n\nHowever, if you remember the previous section, we already learned\nhow can we create a run step in our build script, to execute an executable file\nbuilt by the build script.\n\nSo, we could simply add a run step in our build script to run these unit tests\nfrom a single command in the `zig` compiler, to make our lifes easier.\nIn the example below, we demonstrate the commands to\nregister a new build step called \"tests\" in our build script\nto run these unit tests.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst run_arti = b.addRunArtifact(test_exe);\nconst run_step = b.step(\"tests\", \"Run unit tests\");\nrun_step.dependOn(&run_arti.step);\n```\n:::\n\n\n\n\nNow that we registered this new build step, we can trigger it by calling the command below\nin the terminal. You can also checkout the complete source\ncode for this specific build script at the `build_tests.zig` module at the\n[official repository of this book](https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_tests.zig)\n[^module-src2].\n\n\n[^module-src2]: \n\n\n```bash\nzig build tests\n```\n\n\n## Tailoring your build process with user-provided options\n\nSometimes, you want to make a build script that is customizable by the user\nof your project. You can do that by creating user-provided options in\nyour build script. We create an user-provided option by using the\n`option()` method from the `Build` struct.\n\nWith this method, we create a \"build option\" which can be passed\nto the `build.zig` script at the command line. The user have the power of setting\nthis option at the `build` command from the\n`zig` compiler. In other words, each build option that we create\nbecomes a new command line argument that is accessible through the `build` command\nof the compiler.\n\nThese \"user-provided options\" are set by using the prefix `-D` in the command line.\nFor example, if we declare an option named `use_zlib`, that receives a boolean value which\nindicates if we should link our source code to `zlib` or not, we can set the value\nof this option in the command line with `-Duse_zlib`. The code example below\ndemonstrates this idea:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const use_zlib = b.option(\n bool,\n \"use_zlib\",\n \"Should link to zlib?\"\n ) orelse false;\n const exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"example.zig\"),\n .target = b.host,\n });\n if (use_zlib) {\n exe.linkSystemLibrary(\"zlib\");\n }\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n\n```bash\nzig build -Duse_zlib=false\n```\n\n\n## Linking to external libraries\n\n\nOne essential part of every build process is the linking stage.\nThis stage is responsible for combining the multiple object files\nthat represent your code, into a single executable file. It also links\nthis executable file to external libraries, if you use any in your code.\n\nIn Zig, we have two notions of a \"library\", which are: 1) a system's library;\n2) a local library. A system's library is just a library that is already installed\nin your system. While a local library is a library that belongs to the current\nproject; a library that is present in your project directory, and\nthat you are building together with your project source code.\n\nThe basic difference between the two, is that a system's library is already\nbuilt and installed in your system, supposedly, and all you need to do\nis to link your source code to this library to start using it.\nWe do that by using the `linkSystemLibrary()` method from a\n`Compile` object. This method accepts the name of the library\nin a string as input. Remember from @sec-targets that a `Compile` object\nis a target object that you declare in your build script.\n\nWhen you link a particular target object with a system's library,\nthe `zig` compiler will use `pkg-config` to find where\nare the binary files and also the header files of this library\nin your system.\nWhen it finds these files, the linker present in the `zig` compiler\nwill link your object files with the files of this library to\nproduce a single binary file for you.\n\nIn the example below, we are creating an executable file named `image_filter`,\nand, we are linking this executable file to the C Standard Library with the\nmethod `linkLibC()`, but we also are linking this executable file to the\nC library `libpng` that is currently installed in my system.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const exe = b.addExecutable(.{\n .name = \"image_filter\",\n .root_source_file = b.path(\"src/main.zig\"),\n .target = target,\n .optimize = optimize,\n });\n exe.linkLibC();\n exe.linkSystemLibrary(\"png\");\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n\nIf you are linking with a C library in your project, is generally a good idea\nto also link your code with the C Standard Library. Because is very likely\nthat this C library uses some functionality of the C Standard Library at some point.\nThe same goes to C++ libraries. So, if you are linking with\nC++ libraries, is a good idea to link your project with the C++\nStandard Library by using the `linkLibCpp()` method.\n\nOn the order side, when you want to link with a local library,\nyou should use the `linkLibrary()` method of a `Compile` object.\nThis method expects to receive another `Compile` object as input.\nThat is, another target object defined in your build script,\nusing either the `addStaticLibrary()` or `addSharedLibrary()` methods\nwhich defines a library to be built.\n\nAs we discussed earlier, a local library is a library\nthat is local to your project, and that is being built together\nwith your project. So, you need to create a target object in your build script\nto build this local library. Then, you link the target objects of interest in your project,\nwith this target object that identifies this local library.\n\nTake a look at this example extracted from the build script of the [`libxev` library](https://github.com/mitchellh/libxev/tree/main)[^libxev2].\nYou can see in this snippet that\nwe are declaring a shared library file, from the `c_api.zig`\nmodule. Then, later in the build script, we declare an\nexecutable file named `\"dynamic-binding-test\"`, which\nlinks to this shared library that we defined earlier\nin the script.\n\n[^libxev2]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst optimize = b.standardOptimizeOption(.{});\nconst target = b.standardTargetOptions(.{});\n\nconst dynamic_lib = b.addSharedLibrary(.{\n .name = dynamic_lib_name,\n .root_source_file = b.path(\"src/c_api.zig\"),\n .target = target,\n .optimize = optimize,\n});\nb.installArtifact(dynamic_lib);\n// ... more lines in the script\nconst dynamic_binding_test = b.addExecutable(.{\n .name = \"dynamic-binding-test\",\n .target = target,\n .optimize = optimize,\n});\ndynamic_binding_test.linkLibrary(dynamic_lib);\n```\n:::\n\n\n\n\n\n\n## Building C code {#sec-building-c-code}\n\nThe `zig` compiler comes with a C compiler embedded in it. In other words,\nyou can use the `zig` compiler to build C projects. This C compiler is available\nthrough the `cc` command of the `zig` compiler.\n\nAs an example, let's use the famous [FreeType library](https://freetype.org/)[^freetype].\nFreeType is one of the most widely used pieces of software in the world.\nIt's a C library designed to produce high-quality fonts. But it's also\nheavily used in the industry to natively render text and fonts\nin the screen of your computer.\n\nIn this section, we are going to write a build script, piece by piece, that is capable\nof building the FreeType project from source.\nYou can find the source code of this build script on the\n[`freetype-zig` repository](https://github.com/pedropark99/freetype-zig/tree/main)[^freetype-zig]\navailable at GitHub.\n\n[^freetype]: \n[^freetype-zig]: \n\nAfter you download the source code of FreeType from the official website[^freetype],\nyou can start writing the `build.zig` module. We begin by defining the target object\nthat defines the binary file that we want to compile.\n\nAs an example, I will build the project as a static library file using the `addStaticLibrary()` method\nto create the target object.\nAlso, since FreeType is a C library, I will also link the library\nagainst `libc` through the `linkLibC()` method, to guarantee that any use\nof the C Standard Library is covered in the compilation process.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst target = b.standardTargetOptions(.{});\nconst opti = b.standardOptimizeOption(.{});\nconst lib = b.addStaticLibrary(.{\n .name = \"freetype\",\n .optimize = opti,\n .target = target,\n});\nlib.linkLibC();\n```\n:::\n\n\n\n\n### Creating C compiler flags\n\nCompiler flags are also known as \"compiler options\" by many programmers,\nor also, as \"command options\" in the GCC official documentation.\nIt's fair to also call them as the \"command-line arguments\" of the C compiler.\nIn general, we use compiler flags to turn on (or turn off) some features from the compiler,\nor to tweak the compilation process to fit the needs of our project.\n\nIn build scripts written in Zig, we normally list the C compiler flags to be used in the compilation process\nin a simple array, like in the example below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c_flags = [_][]const u8{\n \"-Wall\",\n \"-Wextra\",\n \"-Werror\",\n};\n```\n:::\n\n\n\n\nIn theory, there is nothing stopping you from using this array to add \"include paths\" (with the `-I` flag)\nor \"library paths\" (with the `-L` flag) to the compilation process. But there are formal ways in Zig to\nadd these types of paths in the compilation process. Both are discussed in @sec-include-paths\nand @sec-library-paths.\n\nAnyway, in Zig, we add C flags to the build process together with the C files that we want to compile, by using the\n`addCSourceFile()` and `addCSourceFiles()` methods. In the example above, we have just declared\nthe C flags that we want to use. But we haven't added them to the build process yet.\nTo do that, we also need to list the C files to be compiled.\n\n### Listing your C files\n\nThe C files that contains \"cross-platform\" source code are listed in the `c_source_files`\nobject below. These are the C files that are included by default in every platform\nsupported by the FreeType library. Now, since the amount of C files in the FreeType library is big,\nI have omitted the rest of the files in the code example below, for brevity purposes.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c_source_files = [_][]const u8{\n \"src/autofit/autofit.c\",\n \"src/base/ftbase.c\",\n // ... and many other C files.\n};\n```\n:::\n\n\n\n\nNow, in addition to \"cross-platform\" source code, we also have some C files in the FreeType project\nthat are platform-specific, meaning that, they contain source code that can only be compiled in specific platforms,\nand, as a result, they are only included in the build process on these specific target platforms.\nThe objects that list these C files are exposed in the code example below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst windows_c_source_files = [_][]const u8{\n \"builds/windows/ftdebug.c\",\n \"builds/windows/ftsystem.c\"\n};\nconst linux_c_source_files = [_][]const u8{\n \"src/base/ftsystem.c\",\n \"src/base/ftdebug.c\"\n};\n```\n:::\n\n\n\n\nNow that we declared both the files that we want to include and the C compiler flags to be used,\nwe can add them to the target object that describes the FreeType library, by using the\n`addCSourceFile()` and `addCSourceFiles()` methods.\n\nBoth of these functions are methods from a `Compile` object (i.e., a target object).\nThe `addCSourceFile()` method is capable of adding a single C file to the target object,\nwhile the `addCSourceFiles()` method is used to add multiple C files in a single command.\nYou might prefer to use `addCSourceFile()` when you need to use different compiler flags\non specific C files in your project. But, if you can use the same compiler flags\nacross all C files, then, you will probably find `addCSourceFiles()` a better choice.\n\nNotice that we are using the `addCSourceFiles()` method in the example below,\nto add both the C files and the C compiler flags. Also notice that we\nare using the `os.tag` that we learned about in @sec-detect-os, to add the platform-specific\nC files.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nlib.addCSourceFiles(\n &c_source_files, &c_flags\n);\n\nswitch (builtin.target.os.tag) {\n .windows => {\n lib.addCSourceFiles(\n &windows_c_source_files,\n &c_flags\n );\n },\n .linux => {\n lib.addCSourceFiles(\n &linux_c_source_files,\n &c_flags\n );\n },\n else => {},\n}\n```\n:::\n\n\n\n\n\n### Defining C Macros\n\nC Macros are an essential part of the C programming language,\nand they are commonly defined through the `-D` flag from a C compiler.\nIn Zig, you can define a C Macro to be used in your build process\nby using the `defineCMacro()` method from the target object that\ndefines the binary file that you are building.\n\nIn the example below, we are using the `lib` object that we have defined\nin the previous sections to define some C Macros used by the FreeType project\nin the compilation process. These C Macros specify if FreeType\nshould (or should not) include functionalities from different\nexternal libraries.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nlib.defineCMacro(\"FT_DISABLE_ZLIB\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_PNG\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_HARFBUZZ\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_BZIP2\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_BROTLI\", \"TRUE\");\nlib.defineCMacro(\"FT2_BUILD_LIBRARY\", \"TRUE\");\n```\n:::\n\n\n\n\n\n### Adding library paths {#sec-library-paths}\n\nLibrary paths are paths in your computer where the C compiler will look (or search) for\nlibrary files to link against your source code. In other words, when you use a library in your\nC source code, and you ask the C compiler to link your source code against this library,\nthe C compiler will search for the binary files of this library across the paths listed\nin this \"library paths\" set.\n\nThese paths are platform specific, and, by default, the C compiler starts by looking at a\npre-defined set of places in your computer. But you can add more paths (or more places)\nto this list. For example, you may have a library installed in a non-conventional place of your\ncomputer, and you can make the C compiler \"see\" this \"non-conventional place\" by adding this path\nto this list of pre-defined paths.\n\nIn Zig, you can add more paths to this set by using the `addLibraryPath()` method from your target object.\nFirst, you defined a `LazyPath` object, containing the path you want to add, then,\nyou provide this object as input to the `addLibraryPath()` method, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst lib_path: std.Build.LazyPath = .{\n .cwd_relative = \"/usr/local/lib/\"\n};\nlib.addLibraryPath(lib_path);\n```\n:::\n\n\n\n\n\n\n\n### Adding include paths {#sec-include-paths}\n\nThe preprocessor search path is a popular concept from the\nC community, but it's also known by many C programmers as \"include paths\", because\nthe paths in this \"search path\" relate to the `#include` statements found in the C files.\n\nInclude paths are similar to library paths. They are a set of pre-defined places in your computer where\nthe C compiler will look for files during the compilation process. But instead of looking for\nlibrary files, the include paths are places where the compiler looks for header files included\nin your C source code.\nThis is why many C programmers prefer to call these paths as the \"preprocessor search path\".\nBecause header files are processed during the preprocessor stage of the compilation\nprocess.\n\nSo, every header file that you include in your C source code, through a `#include` statements needs to\nbe found somewhere, and the C compiler will search for this header file across the paths listed in this \"include paths\" set.\nInclude paths are added to the compilation process through the `-I` flag.\n\nIn Zig, you can add new paths to this pre-defined set of paths, by using the `addIncludePath()` method\nfrom your target object. This method also accepts a `LazyPath` object as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst inc_path: std.Build.LazyPath = .{\n .path = \"./include\"\n};\nlib.addIncludePath(inc_path);\n```\n:::\n", + "supporting": [ + "07-build-system_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/09-data-structures/execute-results/html.json b/_freeze/Chapters/09-data-structures/execute-results/html.json index 7f635a42..3bbf890a 100644 --- a/_freeze/Chapters/09-data-structures/execute-results/html.json +++ b/_freeze/Chapters/09-data-structures/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "cabd5fbe8584b5427f83c698f124df64", + "hash": "ec46a394836e999ef1cdcb2a2a2407a2", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Data Structures\n\nIn this chapter, I want to present the most common Data Structures that are available from\nthe Zig Standard Library, especially `ArrayList` and also `HashMap`. These are generic Data Structures\nthat you can use to store and control any type of data that is produced by your application.\n\n## Dynamic Arrays {#sec-dynamic-array}\n\nIn high level languages, arrays are usually dynamic. They can easily grow\nin size when they have to, and you don't need to worry about it.\nIn contrast, arrays in low level languages are usually static by default.\nThis is the reality of C, C++, Rust and also Zig. Static arrays were presented at\n@sec-arrays, but in this section, we are going to talk about dynamic arrays in Zig.\n\nDynamic arrays are simply arrays that can grow in size during the runtime\nof your program. Most low level languages have some implementation of\na dynamic array in their standard library. C++ have `std::vector`, Rust have `Vec`,\nand Zig have `std.ArrayList`.\n\nThe `std.ArrayList` struct provides a contiguous and growable array for you.\nIt works like any other dynamic array, it allocates a contiguous block of memory, and when this block have no space left,\n`ArrayList` allocates another contiguous and bigger block of memory, copies the\nelements to this new location, and erases (or frees) the previous block of memory.\n\n\n### Capacity vs Length\n\nWhen we talk about dynamic arrays, we usually have two similar concepts that\nare very essential to how a dynamic array works behind the hood.\nThese concepts are *capacity* and *length*. In some contexts, especially\nin C++, *length* is also called of *size*.\n\nAlthough they look similar, these concepts represent different things\nin the context of a dynamic array. *Capacity* is the number of items (or elements)\nthat your dynamic array can currently hold without the need to allocate more memory.\n\nIn contrast, the *length* refers to how many elements in the array\nare currently being used, or, in other words, how many elements in this array\nthat you have assigned a value to. Every dynamic array works around\na block of allocated memory, which represents an array with total capacity for $n$ elements.\nHowever, only a portion of these $n$ elements are being used most of the time. This portion\nof $n$ is the *length* of the array. So every time you append a new value\nto the array, you are incrementing its *length* by one.\n\nThis means that a dynamic array usually works with an extra margin, or, an extra space\nwhich is currently empty, but it is waiting and ready to be used. This \"extra space\"\nis essentially the difference between *capacity* and *length*. *Capacity* represents\nthe total number of elements that the array can hold without the need to re-allocate\nor re-expand the array, while the *length* represents how much of this capacity\nis currently being used to hold/store values.\n\n@fig-capacity-length presents this idea visually. Notice that, at first,\nthe capacity of the array is greater than the length of the array.\nSo, the dynamic array have extra space that is currently empty, but it\nis ready to receive a value to be stored.\n\n![Difference between capacity and length in a dynamic array](./../Figures/dynamic-array.png){#fig-capacity-length}\n\nWe can also see at @fig-capacity-length that, when *length* and *capacity* are equal, it means that the array have no space left.\nWe have reached the ceiling of our capacity, and because of that, if we want to store more values\nin this array, we need to expand it. We need to get a bigger space that can hold more values\nthan what we currently have.\n\nA dynamic array works by expanding the underlying array, whenever the *length* becomes equal\nto the *capacity* of the array. It basically allocates a new contiguous block of memory that is bigger\nthan the previous one, then, it copies all values that are currently being stored to this new\nlocation (i.e. this new block of memory), then, it frees the previous block of\nmemory. At the end of this process, the new underlying array have a bigger *capacity*, and, therefore,\nthe *length* becomes, once again, smaller than the *capacity* of the array.\n\nThis is the cycle of an dynamic array. Notice that, throughout this cycle, the *capacity* is always\neither equal to or higher than the *length* of the array. If youh have an `ArrayList` object (let's suppose\nyou named it `buffer`), you can check the current capacity of your array by accessing the `capacity`\nattribute of your `ArrayList` object, while the current *length* of it is available at the `items.len`\nattribute.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// Check capacity\nbuffer.capacity;\n// Check length\nbuffer.items.len;\n```\n:::\n\n\n\n\n\n### Creating an `ArrayList` object\n\nIn order to use `ArrayList`, you must provide an allocator object to it.\nRemember, Zig does not have a default memory allocator. And as I described at @sec-allocators, all memory\nallocations must be done by an allocator object that you define, that\nyou have control over. In our example here, I'm going to use\na general purpose allocator, but you can use any other allocator\nof your preference.\n\nWhen you initialize an `ArrayList` object, you must provide the data type of the elements of\nthe array. In other words, this defines the type of data that this array (or container) will\nstore. Therefore, if I provide the `u8` type to it, then, I will create a dynamic\narray of `u8` values. However, if I provide a struct that I have defined instead, like the struct `User`\nfrom @sec-structs-and-oop, then, a dynamic array of `User` values\nwill be created. In the example below, with the expression `ArrayList(u8)` we\nare creating a dynamic array of `u8` values.\n\nAfter you provide the data type of the elements of the array, you can initialize\nan `ArrayList` object by either using the `init()` or the `initCapacity()` methods.\nThe former method receives only the allocator object\nas input, while the latter method receives both the allocator object and a capacity number as inputs.\nWith the latter method, you not only initialize the struct, but you\nalso set the starting capacity of the allocated array.\n\nUsing the `initCapacity()` method is the preferred way to initialize your dynamic array.\nBecause reallocations, or, in other words, the process of expanding the capacity of the array,\nis always a high cost operation. You should take any possible opportunity to avoid reallocations in\nyour array. If you know how much space your array needs to occupy at the beginning,\nyou should always use `initCapacity()` to create your dynamic array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 100);\ndefer buffer.deinit();\n```\n:::\n\n\n\n\n\nIn the example above, the `buffer` object starts as an array of 100 elements. If this\n`buffer` object needs to create more space to accomodate more elements during the runtime of your program, the `ArrayList`\ninternals will perform the necessary actions for you automatically.\nAlso notice the `deinit()` method being used to destroy the `buffer` object at the\nend of the current scope, by freeing all the memory that was allocated for the dynamic\narray stored in this `buffer` object.\n\n\n### Adding new elements to the array\n\nNow that we have created our dynamic array, we can start to use it. You can append (a.k.a \"add\")\nnew values to this array by using the `append()` method. This method works the same way\nas the `append()` method from a Python list, or, the `emplace_back()` method from `std::vector` of C++.\nYou provide a single value to this method, and the method appends this value to the array.\n\nYou can also use the `appendSlice()` method to append multiple values at once. You provide\na slice (slices were described at @sec-arrays) to this method, and the method adds all values present\nin this slice to your dynamic array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry buffer.append('H');\ntry buffer.append('e');\ntry buffer.append('l');\ntry buffer.append('l');\ntry buffer.append('o');\ntry buffer.appendSlice(\" World!\");\n```\n:::\n\n\n\n\n### Removing elements from the array {#sec-dynamic-array-remove}\n\nYou can use the `pop()` method to \"pop\" or remove\nthe last element in the array. Is worth noting that this method\ndo not change the capacity of the array. It just deletes or erases\nthe last value stored in the array.\n\nAlso, this method returns as result the value that got deleted. That is, you can\nuse this method to both get the last value in the array, and also, remove\nit from the array. It is a \"get and remove value\" type of method.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exclamation_mark = buffer.pop();\n```\n:::\n\n\n\n\nNow, if you want to remove specific elements from specific positions\nof your array, you can use the `orderedRemove()` method from your\n`ArrayList` object. With this method, you can provide an index as input,\nthen, the method will delete the value that is at this index in the array.\nYou are effectively reducing the *length* of the array everytime you execute\nan `orderedRemove()` operation.\n\nIn the example below, we first create an `ArrayList` object, and we fill it\nwith numbers. Then, we use `orderedRemove()` to remove the value at\nindex 3 in the array, two consecutive times.\n\nAlso, notice that we are assigning the result of `orderedRemove()` to the\nunderscore character. So we are discarding the result value of this method.\nThe `orderedRemove()` method returns the value that got deleted, in a similar\nstyle to the `pop()` method.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 100);\ndefer buffer.deinit();\n\nfor (0..10) |i| {\n const index: u8 = @intCast(i);\n try buffer.append(index);\n}\n\nstd.debug.print(\n \"{any}\\n\", .{buffer.items}\n);\n_ = buffer.orderedRemove(3);\n_ = buffer.orderedRemove(3);\n\nstd.debug.print(\"{any}\\n\", .{buffer.items});\nstd.debug.print(\"{any}\\n\", .{buffer.items.len});\n```\n:::\n\n\n\n\n```\n{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }\n{ 0, 1, 2, 5, 6, 7, 8, 9 }\n8\n```\n\nOne key characteristic about `orderedRemove()` is that it preserves the order\nof the values in the array. So, it deletes the value that you asked it to\nremove, but it also makes sure that the order of the values that remain in the array\nstay the same as before.\n\nNow, if you don't care about the order of the values, for example, maybe you want to treat\nyour dynamic array as a set of values, like the `std::unordered_set`\nstructure from C++, you can use the `swapRemove()` method instead. This method\nworks similarly to the `orderedRemove()` method. You give an index to this\nmethod, then, it deletes the value that is at this index in the array.\nBut this method does not preserve the original order of the values that remain\nin the array. As a result, `swapRemove()` is, in general, faster than `orderedRemove()`.\n\n\n### Inserting elements at specific indexes\n\nWhen you need to insert values in the middle of your array,\ninstead of just appending them to the end of the array, you need to use\nthe `insert()` and `insertSlice()` methods, instead of\nthe `append()` and `appendSlice()` methods.\n\nThese two methods work very similarly to `insert()` and `insert_range()`\nfrom the C++ `std::vector` class. You provide an index to these methods,\nand they insert the values that you provide at that index in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 10);\ndefer buffer.deinit();\n\ntry buffer.appendSlice(\"My Pedro\");\ntry buffer.insert(4, '3');\ntry buffer.insertSlice(2, \" name\");\nfor (buffer.items) |char| {\n try stdout.print(\"{c}\", .{char});\n}\n```\n:::\n\n\n\n\n```\nMy name P3edro\n```\n\n\n### Conclusion\n\nIf you feel the lack of some other method, I recommend\nyou to read the [official documentation for the `ArrayListAligned`](https://ziglang.org/documentation/master/std/#std.array_list.ArrayListAligned)[^zig-array2]\nstruct, which describes most of the methods available\nthrough the `ArrayList` object.\n\nYou will notice that there is a lot of other methods in this page that\nI did not described here, and I recommend you to explore these methods,\nand understand how they work.\n\n[^zig-array2]: \n\n\n\n## Maps or HashTables {#sec-maps-hashtables}\n\nSome professionals know this type of data structure by different terms, like \"map\",\n\"hashmap\" or \"associative arrays\". But the most common term used is *hashtable*.\nEvery programming language normally have some implementation of a hashtable in their\nstandard libraries. Python have `dict()`, C++ have `std::map` and `std::unordered_map`, Rust\nhave `HashMap`, Javascript have `Object()` and `Map()`, etc.\n\n\n\n### What is a hashtable?\n\nA hashtable is a data structure based on key-value pairs.\nYou provide a key and a value to this structure, then, the hashtable will store\nthe input value at a location that can be identified by the input\nkey that you provided.\nIt does that by using an underlying array and a hash function.\nThese two components are essential to how a hashtable works.\n\nUnder the hood, the hashtable contains an array. This array is where the values\nare stored, and the elements of this array are usually called of *buckets*.\nSo the values that you provide to the hashtable are stored inside buckets,\nand you access each bucket by using an index.\n\nWhen you provide a key to a hashtable, it passes this key to the\nhash function. This hash function uses some sort of hashing algorithm to transform\nthis key into an index. This index is actually an array index. It is a position\nin the underlying array of the hashtable.\nThis is how a key identifies a specific position (or location) inside the hashtable\nstructure.\n\nTherefore, you provide a key to the hashtable, and this key identifies a specific location\ninside the hashtable, then, the hashtable takes the input value that you provided,\nand stores this value in the location identified by this input key.\nYou could say that the key maps to the value stored in the hashtable. You find\nthe value, by using the key that identifies the location where the value is stored.\nThe @fig-hashtable presents this process visually.\n\n\n![A diagram of a Hashtable. Source: Wikipedia, the free encyclopedia.](./../Figures/hashtable.svg){#fig-hashtable}\n\n\nThe operation described in the previous paragraph is normally called an *insertion* operation.\nBecause you are inserting new values into the hashtable.\nBut there are other types of operations in hashtables such as *delete* and *lookup*.\nDelete is self describing, it is when you delete (or remove) a value from the hashtable.\nWhile lookup corresponds to when you look at a value that is stored in\nthe hashtable, by using the key that identifies the location where this value is stored.\n\nSometimes, instead of storing the values directly, the underlying array of the hashtable might be an array of pointers,\ni.e. the buckets of the array stores pointers that points to the value,\nor also, may be an array of linked lists.\nThese cases are common on hashtables that allows duplicate keys, or, in other words,\non hashtables that effectively handle \"collisions\" that may arise from the hash function.\n\nDuplicate keys, or this \"collision\" thing that I'm talking about, is when you have two different keys\nthat points to the same location (i.e. to the same index)\nin the underlying array of the hashtable. This might happen depending on the characteristics of the hash function\nthat is being used in the hashtable. Some implementations of the hashtable will actively deal with collisions,\nmeaning that, they will handle this case in some way. For example, the hashtable\nmight transform all buckets into linked lists. Because with a linked list you can store\nmultiple values into a single bucket.\n\nThere are different techniques to handle collisions in hashtables, which I will not describe\nin this book, because it is not our main scope here. But you can find a good description of\nsome of the most common techniques at the Wikipedia page of hashtables [@wikipedia_hashtables].\n\n\n### Hashtables in Zig {#sec-hashmap}\n\nThe Zig Standard Library provides different implementations of a hashtable.\nEach implementation have its own cons and pros, which we will\ndiscuss later on, and all of them are available through the `std.hash_map` module.\n\nThe `HashMap` struct is a general-purpose hashtable,\nwhich have very fast operations (lookup, insertion, delete), and also,\nquite high load factors for low memory usage. You can create and provide a context object\nto the `HashMap` constructor. This context object allows you to tailor\nthe behaviour of the hashtable itself, because you can\nprovide a hash function implementation to be used by the hashtable\nthrough this context object.\n\nBut let's not worry about this context object now, because it is meant to be used\nby \"experts in the field of hashtables\". Since we are most likely not\nexperts in this field, we are going to take the easy way to create\na hashtable. Which is by using the `AutoHashMap()` function.\n\n\nThis `AutoHashMap()` function is essentially a \"create a hashtable object that uses the default settings\"\ntype of function. It automatically chooses a context object, and, therefore, a hash function implementation,\nfor you. This function receives two data types as input, the first input is the data type of the keys\nthat will be used in this hashtable, while the second input is the data type of the data that will be\nstored inside the hashtable, that is, the data type of the values to be stored.\n\nIn the example below, we are providing the data type `u32` in the first argument, and `u16` in the second argument of this\nfunction. This means that we are going to use `u32` values as keys in this hashtable, while `u16` values are the actual values\nthat are going to be stored into this hashtable.\nAt the end of this process, the `hash_table` object contains a `HashMap` object\nthat uses the default settings and context.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst AutoHashMap = std.hash_map.AutoHashMap;\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var hash_table = AutoHashMap(u32, u16).init(allocator);\n defer hash_table.deinit();\n\n try hash_table.put(54321, 89);\n try hash_table.put(50050, 55);\n try hash_table.put(57709, 41);\n std.debug.print(\n \"N of values stored: {d}\\n\",\n .{hash_table.count()}\n );\n std.debug.print(\n \"Value at key 50050: {d}\\n\",\n .{hash_table.get(50050).?}\n );\n\n if (hash_table.remove(57709)) {\n std.debug.print(\n \"Value at key 57709 successfully removed!\\n\",\n .{}\n );\n }\n std.debug.print(\n \"N of values stored: {d}\\n\",\n .{hash_table.count()}\n );\n}\n```\n:::\n\n\n\n\n```\nN of values stored: 3\nValue at key 50050: 55\nValue at key 57709 successfully removed!\nN of values stored: 2\n```\n\nYou can add/put new values into the hashtable by using the `put()` method. The first argument\nis the key to be used, and the second argument is the actual value that you want to store inside\nthe hashtable. In the example below, we first add the value 89 using the key 54321, next, we add\nthe value 55 using the key 50050, etc.\n\nNotice that we have used the method `count()` to see how many values are currently stored in the\nhashtable. After that, we also use the `get()` method to access (or look) at the value stored in\nthe position identified by the key 500050. The output of this `get()` method is an optional value.\nThis is why we use the `?` method at the end to get the actual value.\n\nAlso notice that we can remove (or delete) values from the hashtable by using the `remove()` method.\nYou provide the key that identifies the value that you want to delete, then, the method will\ndelete this value and return a `true` value as output. This `true` value essentially tells us\nthat the method successfully deleted the value.\n\nBut this delete operation might not be always successful. For example, you might provide the wrong\nkey to this method. I mean, maybe you provide\n(either intentionally or unintentionally) a key that points to an empty bucket,\ni.e. a bucket that still doesn't have a value in it.\nIn this case, the `remove()` method would return a `false` value.\n\n\n\n### Iterating through the hashtable\n\nIterating through the keys and values that are currently being stored in\nthe hashtable is a very common necessity.\nYou can do that in Zig by using an iterator object that can iterate\nthrough the elements of your hashtable object.\n\nThis iterator object works like any other iterator object that you would\nfind in languages such as C++ and Rust. It is basically a pointer object\nthat points to some value in the container, and has a `next()` method\nthat you can use to navigate (or iterate) through the values in the\ncontainer.\n\nYou can create such iterator object by using the `iterator()` method of the hashtable object.\nThis method returns an iterator object, from which you can use the `next()` method in conjunction\nwith a while loop to iterate through the elements of your hashtable. The `next()` method returns an optional\n`Entry` value, and therefore, you must unwrap this optional value to get the actual `Entry` value\nfrom which you can access the key and also the value identified by this key.\n\nWith this `Entry` value at hand, you can access the key of this current entry by using the `key_ptr`\nattribute and dereferencing the pointer that lives inside of it, while the value identified by this\nkey is accessed through the `value_ptr` attribute instead, which is also a pointer to be dereferenced.\nThe code example below demonstrates the use of these elements:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst AutoHashMap = std.hash_map.AutoHashMap;\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var hash_table = AutoHashMap(u32, u16).init(allocator);\n defer hash_table.deinit();\n\n try hash_table.put(54321, 89);\n try hash_table.put(50050, 55);\n try hash_table.put(57709, 41);\n\n var it = hash_table.iterator();\n while (it.next()) |kv| {\n // Access the current key\n std.debug.print(\"Key: {d} | \", .{kv.key_ptr.*});\n // Access the current value\n std.debug.print(\"Value: {d}\\n\", .{kv.value_ptr.*});\n }\n}\n```\n:::\n\n\n\n\n```\nKey: 54321 | Value: 89\nKey: 50050 | Value: 55\nKey: 57709 | Value: 41\n```\n\n\nIf you want to iterate specifically through the values or the keys of your hashtable,\nyou can create a key iterator or a value iterator object. These are also iterator\nobjects, which have the same `next()` method that you can use to iterate through the\nhashtable.\n\nKey iterators are created from the `keyIterator()` method of your\nhashtable object, while value iterators are created from the `valueIterator()` method.\nAll you have to do is to unwrap the value from the `next()` method and deference it\ndirectly to access the key or the value that you are iterating over.\nThe code example below demonstrates the use of a key iterator,\nbut you can replicate the same logic to a value iterator.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar kit = hash_table.keyIterator();\nwhile (kit.next()) |key| {\n std.debug.print(\"Key: {d}\\n\", .{key.*});\n}\n```\n:::\n\n\n\n\n```\nKey: 54321\nKey: 50050\nKey: 57709\n```\n\n\n### The `ArrayHashMap` hashtable {#sec-array-map}\n\nIf you need to iterate through the elements of your hashtable constantly,\nyou might want to use the `ArrayHashMap` struct for your specific case,\ninstead of going with the usual and general-purpose `HashMap` struct.\n\nThe `ArrayHashMap` struct creates a hashtable that is faster to iterate over.\nThat is why this specific type of hashtable might be valuable to you.\nSome other properties of a `ArrayHashMap` hashtable are:\n\n- the order of insertion is preserved, i.e. the order of the values that you find while iterating through this hashtable is actually the order in which these values were inserted in the hashtable.\n- the key-value pairs are stored sequentially, one after another.\n\n\nYou can create an `ArrayHashMap` object by using, once again, a helper function that\nchooses automatically for you a hash function implementation. This is the\n`AutoArrayHashMap()` function, which works very similarly to the `AutoHashMap()`\nfunction that we presented at @sec-hashmap.\n\nYou provide two data types to this function. The data type of the keys that will be\nused in this hashtable, and the data type of the values that will be stored in\nthis hashtable.\n\nAn `ArrayHashMap` object have essentially the exact same methods from the `HashMap` struct.\nSo you can insert new values into the hashtable by using the `put()` method, and you can look (or get)\na value from the hashtable by using the `get()` method. But the `remove()` method is not available\nin this specific type of hashtable.\n\nIn order to delete values from the hashtable, you would use the same methods that you find in\nan `ArrayList` object, i.e. a dynamic array. I presented these methods at @sec-dynamic-array-remove,\nwhich are the `swapRemove()` and `orderedRemove()` methods. These methods have the same meaning here, or,\nthe same effect that they have in an `ArrayList` object.\n\nThis means that, with `swapRemove()` you remove the value from the hashtable, but you do not preserve\nthe order in which the values were inserted into the structure. While `orderedRemove()` is able\nto retain the order in which these values were inserted.\n\nBut instead of providing an index as input to `swapRemove()` or `orderedRemove()`, like I described\nat @sec-dynamic-array-remove, these methods here in an `ArrayHashMap` take a key as input, like\nthe `remove()` method from a `HashMap` object. If you want to provide an index as input, instead\nof a key, you should use the `swapRemoveAt()` and `orderedRemoveAt()` methods.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar hash_table = AutoArrayHashMap(u32, u16)\n .init(allocator);\ndefer hash_table.deinit();\n```\n:::\n\n\n\n\n\n\n### The `StringHashMap` hashtable {#sec-string-hash-map}\n\nOne thing that you will notice in the other two types of hashtables that I have\npresented over the last sections, is that neither of them accepts a slice data type\nin their keys.\nWhat this means is that you cannot use a slice value to represent a key in\nthese types of hashtable.\n\nThe most obvious consequence of this, is that you cannot use strings as keys\nin these hashtables. But it is extremely common to use strings as keys\nin hashtables.\n\nTake this very simple Javascript code snippet as an example. We are creating\na simple hashtable object named `people`. Then, we add a new entry to this\nhashtable, which is identified by the string `'Pedro'`. This string is the\nkey in this case, while the object containing different personal information such as\nage, height and city, is the value to be stored in the hashtable.\n\n```js\nvar people = new Object();\npeople['Pedro'] = {\n 'age': 25,\n 'height': 1.67,\n 'city': 'Belo Horizonte'\n};\n```\n\nThis pattern of using strings as keys is very common in\nall sorts of situations. That is why the Zig Standard Library offers a\nspecific type of hashtable for this purpose, which is created through the `StringHashMap()` function.\nThis function creates a hashtable that uses strings as keys. The only input of this\nfunction is the data type of the values that will be stored into this hashtable.\n\nIn the example below, I'm creating a hashtable to store the ages of different people.\nEach key in this hashtable is represented by the name of each person, while the value stored in the\nhashtable is the age of this person identified by the key.\n\nThat is why I provide the `u8` data type (which is the data type used by the age values) as input to this `StringHashMap()` function.\nAs the result, it creates a hashtable that uses string values as keys, and, that stores\n`u8` values in it. Notice that an allocator object is provided at the `init()` method of the\nresulting object from the `StringHashMap()` function.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var ages = std.StringHashMap(u8).init(allocator);\n defer ages.deinit();\n\n try ages.put(\"Pedro\", 25);\n try ages.put(\"Matheus\", 21);\n try ages.put(\"Abgail\", 42);\n\n var it = ages.iterator();\n while (it.next()) |kv| {\n std.debug.print(\"Key: {s} | \", .{kv.key_ptr.*});\n std.debug.print(\"Age: {d}\\n\", .{kv.value_ptr.*});\n }\n}\n```\n:::\n\n\n\n\n```\nKey: Pedro | Age: 25\nKey: Abgail | Age: 42\nKey: Matheus | Age: 21\n```\n\n\n### The `StringArrayHashMap` hashtable\n\nThe Zig Standard Library also provides a type of hashtable that mix the cons and pros of the\n`StringHashMap` and `ArrayHashMap` together. That is, a hashtable\nthat uses strings as keys, but also have the advantages from `ArrayHashMap`.\nIn other words, you can have a hashtable that is fast to iterate over,\nthat preserves insertion order, and also, that uses strings as keys.\n\nYou can create such type of hashtable by using the `StringArrayHashMap()` function.\nThis function accepts a data type as input, which is the data type of the values that are\ngoing to be stored inside this hashtable, in the same style as the function presented\nat @sec-string-hash-map.\n\nYou can insert new values into this hashtable by using the same `put()` method that\nwe have discussed at @sec-string-hash-map. And you can also get values from the hashtable\nby using the same `get()` method.\nLike its `ArrayHashMap` brother, to delete values from this specific type of hashtable,\nwe also use the `orderedRemove()` and `swapRemove()` methods, with the same effects that\nI have described at @sec-array-map.\n\nIf we take the code example that was exposed at @sec-string-hash-map, we can\nachieve the exact same result with `StringArrayHashMap()`:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar ages = std.StringArrayHashMap(u8).init(allocator);\n```\n:::\n\n\n\n\n\n\n\n## Linked lists\n\nThe Zig Standard Library provides an implementation for both singly and doubly linked lists.\nA linked list is a linear data structure that looks like a chain, or, a rope.\nThe main advantage of this data structure is that you normally have very fast\ninsertion and deletion operations. But, as a disadvantage, iterating through\nthis data structure is usually not so fast as iterating through an array.\n\nThe idea behind a linked list is to build a structure that consists of a sequence of nodes\nconnected to each other by pointers. This means that linked lists are usually not contiguous\nin memory, because each node might be anywhere in memory. They do not need to be close to\none another.\n\nAt @fig-linked-list we can see a diagram of a singly linked list. We begin at the first node\n(which is usually called \"the head of the linked list\"). Then, from this\nfirst node we uncover the remaining nodes in the structure, by following the locations pointed\nby the pointers found in each node.\n\nEach node has two things in it. It has the value that is stored in the current node\n, and also, a pointer. This pointer points to the next node in the list. If this pointer\nis null, then, it means that we have reached the end of our linked list.\n\n![A diagram of a singly linked list.](./../Figures/linked-list.png){#fig-linked-list}\n\n\nAt @fig-linked-list2 we can see a diagram of a doubly linked list. The only thing that really\nchanges now is that every node in the linked list has both a pointer to the previous node,\nand, a pointer to the next node. So every node in a doubly linked list has two pointers in it. These are\nusually called the `prev` (for \"previous\") and the `next` (for \"next\") pointers of the node.\n\nIn the singly linked list example, we had only one single pointer in each node, and this singular\npointer was always pointing to the next node in the sequence. This means that singly linked lists\nnormally have only the `next` pointer in them.\n\n![A diagram of a doubly linked list.](./../Figures/doubly-linked-list.png){#fig-linked-list2}\n\n\nLinked lists are available in Zig through the functions `SinglyLinkedList()` and\n`DoublyLinkedList()`, for \"singly linked lists\" and \"doubly linked lists\", respectively. These functions are\nactually generic functions, which we are going to talk more about at @sec-generic-fun.\n\nFor now, just understand that, in order to create a linked list object,\nwe begin by providing a data type to these functions. This data type defines\nthe type of data that each node in this linked list will store. In the example below,\nwe are creating a singly linked list of `u32` values.\nSo each node in this linked list will store a `u32` value.\n\nBoth the `SinglyLinkedList()` and `DoublyLinkedList()` functions returns a type,\ni.e. a struct definition, as output. Therefore, the object `Lu32` is actually\na struct definition. It defines the type \"singly linked list of `u32` values\".\n\nNow that we have the definition of the struct, we need to instantiate a `Lu32` object.\nWe normally instantiate struct objects in Zig by using an `init()` method.\nBut in this case, we are instantiating the struct directly, by using an empty\n`struct` literal, in the expression `Lu32{}`.\n\nIn this example, we first create multiple node objects, and after we create them,\nwe start to insert and connect these nodes to build the linked list, using the\n`prepend()` and `insertAfter()` methods. Notice that the `prepend()` method\nis a method from the linked list object, while the `insertAfter()` is a method\npresent in the node objects.\n\nIn essence, the `prepend()` method inserts a node at the beginning of the linked\nlist. In other words, the node that you provide to this method, becomes the new\n\"head node\" of the linked list. It becomes the first node in the list (see @fig-linked-list).\n\nOn the other side, the `insertAfter()` method is used to basically connect two nodes together.\nWhen you provide a node to this method, it creates a pointer to this input node,\nand stores this pointer in the `next` attribute of the current node, from which the method was called from.\n\nBecause doubly linked lists have both a `next` and a `prev` attributes in each node\n(as described at @fig-linked-list2), a node object created from\na `DoublyLinkedList` object have both an `insertBefore()` (for `prev`)\nand an `insertAfter()` (for `next`) methods available.\n\nThus, if we have used a doubly linked list, we can use the `insertBefore()` method\nto store the pointer to the input node in the `prev` attribute. This would put the input\nnode as the \"previous node\", or, the node before the current node. In contrast, the `insertAfter()` method\nputs the pointer created to the input node in the `next` attribute of the current node,\nand as result, the input node becomes the \"next node\" of the current node.\n\nSince we are using a singly linked list in this example, we have only the `insertAfter()` method\navailable in the node objects that we create from our `Lu32` type.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SinglyLinkedList = std.SinglyLinkedList;\nconst Lu32 = SinglyLinkedList(u32);\n\npub fn main() !void {\n var list = Lu32{};\n var one = Lu32.Node{ .data = 1 };\n var two = Lu32.Node{ .data = 2 };\n var three = Lu32.Node{ .data = 3 };\n var four = Lu32.Node{ .data = 4 };\n var five = Lu32.Node{ .data = 5 };\n\n list.prepend(&two); // {2}\n two.insertAfter(&five); // {2, 5}\n list.prepend(&one); // {1, 2, 5}\n two.insertAfter(&three); // {1, 2, 3, 5}\n three.insertAfter(&four); // {1, 2, 3, 4, 5}\n}\n```\n:::\n\n\n\n\n\nThere are other methods available from the linked list object, depending if this object is\na singly linked list or a doubly linked list, that might be very useful for you. You can find a\nsummary of them in the bullet points below:\n\n- `remove()` to remove a specific node from the linked list.\n- if singly linked list, `len()` to count how many nodes there is in the linked list.\n- if doubly linked list, checkout the `len` attribute to see how many nodes there is in the linked list.\n- if singly linked list, `popFirst()` to remove the first node (i.e. the \"head\") from the linked list.\n- if doubly linked list, `pop()` and `popFirst()` to remove the last and first nodes from the linked list, respectively.\n- if doubly linked list, `append()` to add a new node to end of the linked list (i.e. inverse of `prepend()`).\n\n\n\n## Multi array structure\n\nZig introduces a new data structure called `MultiArrayList()`. It is a different version of the dynamic array\nthat we have introduced at @sec-dynamic-array. The difference between this structure and the `ArrayList()`\nthat we know from @sec-dynamic-array, is that `MultiArrayList()` creates a separate dynamic array\nfor each field of the struct that you provide as input.\n\nConsider the following code example. We create a new custom struct called `Person`. This\nstruct contains three different data members, or, three different fields. As consequence,\nwhen we provide this `Person` data type as input to `MultiArrayList()`, this\ncreates a \"struct of three different arrays\" called `PersonArray`. In other words,\nthis `PersonArray` is a struct that contains three internal dynamic arrays in it.\nOne array for each field found in the `Person` struct definition.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Person = struct {\n name: []const u8,\n age: u8,\n height: f32,\n};\nconst PersonArray = std.MultiArrayList(Person);\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var people = PersonArray{};\n defer people.deinit(allocator);\n\n try people.append(allocator, .{\n .name = \"Auguste\", .age = 15, .height = 1.54\n });\n try people.append(allocator, .{\n .name = \"Elena\", .age = 26, .height = 1.65\n });\n try people.append(allocator, .{\n .name = \"Michael\", .age = 64, .height = 1.87\n });\n}\n```\n:::\n\n\n\n\nIn other words, instead of creating an array of \"persons\", the `MultiArrayList()` function\ncreates a \"struct of arrays\". Each data member of this struct is a different array that stores\nthe values of a specific field from the `Person` values that were added (or, appended) to this \"struct of arrays\".\nOne important detail is that each of these separate internal arrays stored inside `PersonArray`\nare dynamic arrays. This means that these arrays can grow in capacity automatically as needed, to accomodate\nmore values.\n\nThe @fig-multi-array exposed below presents a diagram that describes the `PersonArray` struct\nthat we have created in the previous code example. Notice that the values of the data members\npresent in each of the three `Person` values that we have appended into the `PersonArray` object\n, are scattered across three different internal arrays of the `PersonArray` object.\n\n![A diagram of the `PersonArray` struct.](./../Figures/multi-array.png){#fig-multi-array}\n\nYou can easily access each of these arrays separately, and iterate over the values of each array.\nFor that, you will need to call the `items()` method from the `PersonArray` object, and provide as input\nto this method, the name of the field that you want to iterate over.\nIf you want to iterate through the `.age` array for example, then, you need to call `items(.age)` from\nthe `PersonArray` object, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (people.items(.age)) |*age| {\n try stdout.print(\"Age: {d}\\n\", .{age.*});\n}\n```\n:::\n\n\n\n\n```\nAge: 15\nAge: 26\nAge: 64\n```\n\n\nIn the above example, we are iterating over the values of the `.age` array, or,\nthe internal array of the `PersonArray` object that contains the values of the `age`\ndata member from the `Person` values that were added to the multi array struct.\n\nIn this example we are calling the `items()` method directly from the `PersonArray`\nobject. However, it is recommended on most situations to call this `items()` method\nfrom a \"slice object\", which you can create from the `slice()` method.\nThe reason for this is that calling `items()` multiple times have better performance\nif you use a slice object.\n\nTherefore, if you are planning to access only one of the\ninternal arrays from your \"multi array struct\", it is fine to call `items()` directly\nfrom the multi array object. But if you need to access many of the internal arrays\nfrom your \"multi array struct\", then, you will likely need to call `items()` more\nthan once, and, in such circumstance, is better to call `items()` through a slice object.\nThe example below demonstrates the use of such object:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar slice = people.slice();\nfor (slice.items(.age)) |*age| {\n age.* += 10;\n}\nfor (slice.items(.name), slice.items(.age)) |*n,*a| {\n try stdout.print(\n \"Name: {s}, Age: {d}\\n\", .{n.*, a.*}\n );\n}\n```\n:::\n\n\n\n\n```\nName: Auguste, Age: 25\nName: Elena, Age: 36\nName: Michael, Age: 74\n```\n\n\n## Conclusion\n\nThere are many other data structures that I haven't presented here.\nBut you can check them out at the official Zig Standard Library documentation page.\nActually, when you get into the [homepage of the documentation](https://ziglang.org/documentation/master/std/#)[^home], the first thing\nthat appears to you in this page, is a list of types and data structures that\nare available in the Zig Standard Library.\nThere are some very specific data structures in this list, like a\n[`BoundedArray` struct](https://ziglang.org/documentation/master/std/#std.bounded_array.BoundedArray)[^bounded]\n, but there is also some more general structures, such as a\n[`PriorityQueue` struct](https://ziglang.org/documentation/master/std/#std.priority_queue.PriorityQueue)[^priority].\n\n\n[^home]: \n[^priority]: .\n[^bounded]: \n\n\n\n\n\n\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Data Structures\n\nIn this chapter, I want to present the most common Data Structures that are available from\nthe Zig Standard Library, especially `ArrayList` and also `HashMap`. These are generic Data Structures\nthat you can use to store and control any type of data that is produced by your application.\n\n## Dynamic Arrays {#sec-dynamic-array}\n\nIn high level languages, arrays are usually dynamic. They can easily grow\nin size when they have to, and you don't need to worry about it.\nIn contrast, arrays in low level languages are usually static by default.\nThis is the reality of C, C++, Rust and also Zig. Static arrays were presented at\n@sec-arrays, but in this section, we are going to talk about dynamic arrays in Zig.\n\nDynamic arrays are simply arrays that can grow in size during the runtime\nof your program. Most low level languages have some implementation of\na dynamic array in their standard library. C++ have `std::vector`, Rust have `Vec`,\nand Zig have `std.ArrayList`.\n\nThe `std.ArrayList` struct provides a contiguous and growable array for you.\nIt works like any other dynamic array, it allocates a contiguous block of memory, and when this block have no space left,\n`ArrayList` allocates another contiguous and bigger block of memory, copies the\nelements to this new location, and erases (or frees) the previous block of memory.\n\n\n### Capacity vs Length\n\nWhen we talk about dynamic arrays, we usually have two similar concepts that\nare very essential to how a dynamic array works behind the hood.\nThese concepts are *capacity* and *length*. In some contexts, especially\nin C++, *length* is also called of *size*.\n\nAlthough they look similar, these concepts represent different things\nin the context of a dynamic array. *Capacity* is the number of items (or elements)\nthat your dynamic array can currently hold without the need to allocate more memory.\n\nIn contrast, the *length* refers to how many elements in the array\nare currently being used, or, in other words, how many elements in this array\nthat you have assigned a value to. Every dynamic array works around\na block of allocated memory, which represents an array with total capacity for $n$ elements.\nHowever, only a portion of these $n$ elements are being used most of the time. This portion\nof $n$ is the *length* of the array. So every time you append a new value\nto the array, you are incrementing its *length* by one.\n\nThis means that a dynamic array usually works with an extra margin, or an extra space\nthat is currently empty, but waiting and ready to be used. This \"extra space\"\nis essentially the difference between *capacity* and *length*. *Capacity* represents\nthe total number of elements that the array can hold without the need to re-allocate\nor re-expand the array, while the *length* represents how much of this capacity\nis currently being used to hold/store values.\n\n@fig-capacity-length presents this idea visually. Notice that, at first,\nthe capacity of the array is greater than the length of the array.\nSo, the dynamic array have extra space that is currently empty, but it\nis ready to receive a value to be stored.\n\n![Difference between capacity and length in a dynamic array](./../Figures/dynamic-array.png){#fig-capacity-length}\n\nWe can also see in @fig-capacity-length that, when *length* and *capacity* are equal, it means that the array have no space left.\nWe have reached the ceiling of our capacity, and because of that, if we want to store more values\nin this array, we need to expand it. We need to get a bigger space that can hold more values\nthan what we currently have.\n\nA dynamic array works by expanding the underlying array, whenever the *length* becomes equal\nto the *capacity* of the array. It basically allocates a new contiguous block of memory that is bigger\nthan the previous one, then, it copies all values that are currently being stored to this new\nlocation (i.e., this new block of memory), then, it frees the previous block of\nmemory. At the end of this process, the new underlying array have a bigger *capacity*, and, therefore,\nthe *length* becomes, once again, smaller than the *capacity* of the array.\n\nThis is the cycle of a dynamic array. Notice that, throughout this cycle, the *capacity* is always\neither equal to or higher than the *length* of the array. If you have an `ArrayList` object (let's suppose\nyou named it `buffer`), you can check the current capacity of your array by accessing the `capacity`\nattribute of your `ArrayList` object, while the current *length* of it is available at the `items.len`\nattribute.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// Check capacity\nbuffer.capacity;\n// Check length\nbuffer.items.len;\n```\n:::\n\n\n\n\n\n### Creating an `ArrayList` object\n\nIn order to use `ArrayList`, you must provide an allocator object to it.\nRemember, Zig does not have a default memory allocator. And as I described in @sec-allocators, all memory\nallocations must be done by an allocator object that you define, that\nyou have control over. In our example here, I'm going to use\na general purpose allocator, but you can use any other allocator\nof your preference.\n\nWhen you initialize an `ArrayList` object, you must provide the data type of the elements of\nthe array. In other words, this defines the type of data that this array (or container) will\nstore. Therefore, if I provide the `u8` type to it, then, I will create a dynamic\narray of `u8` values. However, if I provide a struct that I have defined instead, like the struct `User`\nfrom @sec-structs-and-oop, then, a dynamic array of `User` values\nwill be created. In the example below, with the expression `ArrayList(u8)` we\nare creating a dynamic array of `u8` values.\n\nAfter you provide the data type of the elements of the array, you can initialize\nan `ArrayList` object by either using the `init()` or the `initCapacity()` methods.\nThe former method receives only the allocator object\nas input, while the latter method receives both the allocator object and a capacity number as inputs.\nWith the latter method, you not only initialize the struct, but you\nalso set the starting capacity of the allocated array.\n\nUsing the `initCapacity()` method is the preferred way to initialize your dynamic array.\nBecause reallocations, or, in other words, the process of expanding the capacity of the array,\nis always a high cost operation. You should take any possible opportunity to avoid reallocations in\nyour array. If you know how much space your array needs to occupy at the beginning,\nyou should always use `initCapacity()` to create your dynamic array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 100);\ndefer buffer.deinit();\n```\n:::\n\n\n\n\n\nIn the example above, the `buffer` object starts as an array of 100 elements. If this\n`buffer` object needs to create more space to accomodate more elements during the runtime of your program, the `ArrayList`\ninternals will perform the necessary actions for you automatically.\nAlso notice the `deinit()` method being used to destroy the `buffer` object at the\nend of the current scope, by freeing all the memory that was allocated for the dynamic\narray stored in this `buffer` object.\n\n\n### Adding new elements to the array\n\nNow that we have created our dynamic array, we can start to use it. You can append (a.k.a \"add\")\nnew values to this array by using the `append()` method. This method works the same way\nas the `append()` method from a Python list, or, the `emplace_back()` method from `std::vector` of C++.\nYou provide a single value to this method, and the method appends this value to the array.\n\nYou can also use the `appendSlice()` method to append multiple values at once. You provide\na slice (slices were described in @sec-arrays) to this method, and the method adds all values present\nin this slice to your dynamic array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry buffer.append('H');\ntry buffer.append('e');\ntry buffer.append('l');\ntry buffer.append('l');\ntry buffer.append('o');\ntry buffer.appendSlice(\" World!\");\n```\n:::\n\n\n\n\n### Removing elements from the array {#sec-dynamic-array-remove}\n\nYou can use the `pop()` method to \"pop\" or remove\nthe last element in the array. It's worth noting that this method\ndo not change the capacity of the array. It just deletes or erases\nthe last value stored in the array.\n\nAlso, this method returns as result the value that got deleted. That is, you can\nuse this method to both get the last value in the array, and also, remove\nit from the array. It's a \"get and remove value\" type of method.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exclamation_mark = buffer.pop();\n```\n:::\n\n\n\n\nNow, if you want to remove specific elements from specific positions\nof your array, you can use the `orderedRemove()` method from your\n`ArrayList` object. With this method, you can provide an index as input,\nthen, the method will delete the value that is at this index in the array.\nYou are effectively reducing the *length* of the array everytime you execute\nan `orderedRemove()` operation.\n\nIn the example below, we first create an `ArrayList` object, and we fill it\nwith numbers. Then, we use `orderedRemove()` to remove the value at\nindex 3 in the array, two consecutive times.\n\nAlso, notice that we are assigning the result of `orderedRemove()` to the\nunderscore character. So we are discarding the result value of this method.\nThe `orderedRemove()` method returns the value that got deleted, in a similar\nstyle to the `pop()` method.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 100);\ndefer buffer.deinit();\n\nfor (0..10) |i| {\n const index: u8 = @intCast(i);\n try buffer.append(index);\n}\n\nstd.debug.print(\n \"{any}\\n\", .{buffer.items}\n);\n_ = buffer.orderedRemove(3);\n_ = buffer.orderedRemove(3);\n\nstd.debug.print(\"{any}\\n\", .{buffer.items});\nstd.debug.print(\"{any}\\n\", .{buffer.items.len});\n```\n:::\n\n\n\n\n```\n{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }\n{ 0, 1, 2, 5, 6, 7, 8, 9 }\n8\n```\n\nOne key characteristic about `orderedRemove()` is that it preserves the order\nof the values in the array. So, it deletes the value that you asked it to\nremove, but it also makes sure that the order of the values that remain in the array\nstay the same as before.\n\nNow, if you don't care about the order of the values, for example, maybe you want to treat\nyour dynamic array as a set of values, like the `std::unordered_set`\nstructure from C++, you can use the `swapRemove()` method instead. This method\nworks similarly to the `orderedRemove()` method. You give an index to this\nmethod, then, it deletes the value that is at this index in the array.\nBut this method does not preserve the original order of the values that remain\nin the array. As a result, `swapRemove()` is, in general, faster than `orderedRemove()`.\n\n\n### Inserting elements at specific indexes\n\nWhen you need to insert values in the middle of your array,\ninstead of just appending them to the end of the array, you need to use\nthe `insert()` and `insertSlice()` methods, instead of\nthe `append()` and `appendSlice()` methods.\n\nThese two methods work very similarly to `insert()` and `insert_range()`\nfrom the C++ `std::vector` class. You provide an index to these methods,\nand they insert the values that you provide at that index in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 10);\ndefer buffer.deinit();\n\ntry buffer.appendSlice(\"My Pedro\");\ntry buffer.insert(4, '3');\ntry buffer.insertSlice(2, \" name\");\nfor (buffer.items) |char| {\n try stdout.print(\"{c}\", .{char});\n}\n```\n:::\n\n\n\n\n```\nMy name P3edro\n```\n\n\n### Conclusion\n\nIf you feel the lack of some other method, I recommend\nyou to read the [official documentation for the `ArrayListAligned`](https://ziglang.org/documentation/master/std/#std.array_list.ArrayListAligned)[^zig-array2]\nstruct, which describes most of the methods available\nthrough the `ArrayList` object.\n\nYou will notice that there is a lot of other methods in this page that\nI did not described here, and I recommend you to explore these methods,\nand understand how they work.\n\n[^zig-array2]: \n\n\n\n## Maps or HashTables {#sec-maps-hashtables}\n\nSome professionals know this type of data structure by different terms, like \"map\",\n\"hashmap\" or \"associative arrays\". But the most common term used is *hashtable*.\nEvery programming language normally have some implementation of a hashtable in their\nstandard libraries. Python have `dict()`, C++ have `std::map` and `std::unordered_map`, Rust\nhave `HashMap`, Javascript have `Object()` and `Map()`, etc.\n\n\n\n### What is a hashtable?\n\nA hashtable is a data structure based on key-value pairs.\nYou provide a key and a value to this structure, then, the hashtable will store\nthe input value at a location that can be identified by the input\nkey that you provided.\nIt does that by using an underlying array and a hash function.\nThese two components are essential to how a hashtable works.\n\nUnder the hood, the hashtable contains an array. This array is where the values\nare stored, and the elements of this array are usually called of *buckets*.\nSo the values that you provide to the hashtable are stored inside buckets,\nand you access each bucket by using an index.\n\nWhen you provide a key to a hashtable, it passes this key to the\nhash function. This hash function uses some sort of hashing algorithm to transform\nthis key into an index. This index is actually an array index. It's a position\nin the underlying array of the hashtable.\nThis is how a key identifies a specific position (or location) inside the hashtable\nstructure.\n\nTherefore, you provide a key to the hashtable, and this key identifies a specific location\ninside the hashtable, then, the hashtable takes the input value that you provided,\nand stores this value in the location identified by this input key.\nYou could say that the key maps to the value stored in the hashtable. You find\nthe value, by using the key that identifies the location where the value is stored.\nThe @fig-hashtable presents this process visually.\n\n\n![A diagram of a Hashtable. Source: Wikipedia, the free encyclopedia.](./../Figures/hashtable.svg){#fig-hashtable}\n\n\nThe operation described in the previous paragraph is normally called an *insertion* operation.\nBecause you are inserting new values into the hashtable.\nBut there are other types of operations in hashtables such as *delete* and *lookup*.\nDelete is self describing, it's when you delete (or remove) a value from the hashtable.\nWhile lookup corresponds to when you look at a value that is stored in\nthe hashtable, by using the key that identifies the location where this value is stored.\n\nSometimes, instead of storing the values directly, the underlying array of the hashtable might be an array of pointers,\ni.e., the buckets of the array stores pointers that points to the value,\nor also, may be an array of linked lists.\nThese cases are common on hashtables that allows duplicate keys, or, in other words,\non hashtables that effectively handle \"collisions\" that may arise from the hash function.\n\nDuplicate keys, or this \"collision\" thing that I'm talking about, is when you have two different keys\nthat points to the same location (i.e., to the same index)\nin the underlying array of the hashtable. This might happen depending on the characteristics of the hash function\nthat is being used in the hashtable. Some implementations of the hashtable will actively deal with collisions,\nmeaning that, they will handle this case in some way. For example, the hashtable\nmight transform all buckets into linked lists. Because with a linked list you can store\nmultiple values into a single bucket.\n\nThere are different techniques to handle collisions in hashtables, which I will not describe\nin this book, because it's not our main scope here. But you can find a good description of\nsome of the most common techniques at the Wikipedia page of hashtables [@wikipedia_hashtables].\n\n\n### Hashtables in Zig {#sec-hashmap}\n\nThe Zig Standard Library provides different implementations of a hashtable.\nEach implementation have its own cons and pros, which we will\ndiscuss later on, and all of them are available through the `std.hash_map` module.\n\nThe `HashMap` struct is a general-purpose hashtable,\nwhich have very fast operations (lookup, insertion, delete), and also,\nquite high load factors for low memory usage. You can create and provide a context object\nto the `HashMap` constructor. This context object allows you to tailor\nthe behaviour of the hashtable itself, because you can\nprovide a hash function implementation to be used by the hashtable\nthrough this context object.\n\nBut let's not worry about this context object now, because it's meant to be used\nby \"experts in the field of hashtables\". Since we are most likely not\nexperts in this field, we are going to take the easy way to create\na hashtable. Which is by using the `AutoHashMap()` function.\n\n\nThis `AutoHashMap()` function is essentially a \"create a hashtable object that uses the default settings\"\ntype of function. It automatically chooses a context object, and, therefore, a hash function implementation,\nfor you. This function receives two data types as input, the first input is the data type of the keys\nthat will be used in this hashtable, while the second input is the data type of the data that will be\nstored inside the hashtable, that is, the data type of the values to be stored.\n\nIn the example below, we are providing the data type `u32` in the first argument, and `u16` in the second argument of this\nfunction. This means that we are going to use `u32` values as keys in this hashtable, while `u16` values are the actual values\nthat are going to be stored into this hashtable.\nAt the end of this process, the `hash_table` object contains a `HashMap` object\nthat uses the default settings and context.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst AutoHashMap = std.hash_map.AutoHashMap;\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var hash_table = AutoHashMap(u32, u16).init(allocator);\n defer hash_table.deinit();\n\n try hash_table.put(54321, 89);\n try hash_table.put(50050, 55);\n try hash_table.put(57709, 41);\n std.debug.print(\n \"N of values stored: {d}\\n\",\n .{hash_table.count()}\n );\n std.debug.print(\n \"Value at key 50050: {d}\\n\",\n .{hash_table.get(50050).?}\n );\n\n if (hash_table.remove(57709)) {\n std.debug.print(\n \"Value at key 57709 successfully removed!\\n\",\n .{}\n );\n }\n std.debug.print(\n \"N of values stored: {d}\\n\",\n .{hash_table.count()}\n );\n}\n```\n:::\n\n\n\n\n```\nN of values stored: 3\nValue at key 50050: 55\nValue at key 57709 successfully removed!\nN of values stored: 2\n```\n\nYou can add/put new values into the hashtable by using the `put()` method. The first argument\nis the key to be used, and the second argument is the actual value that you want to store inside\nthe hashtable. In the example below, we first add the value 89 using the key 54321, next, we add\nthe value 55 using the key 50050, etc.\n\nNotice that we have used the method `count()` to see how many values are currently stored in the\nhashtable. After that, we also use the `get()` method to access (or look) at the value stored in\nthe position identified by the key 500050. The output of this `get()` method is an optional value.\nThis is why we use the `?` method at the end to get the actual value.\n\nAlso notice that we can remove (or delete) values from the hashtable by using the `remove()` method.\nYou provide the key that identifies the value that you want to delete, then, the method will\ndelete this value and return a `true` value as output. This `true` value essentially tells us\nthat the method successfully deleted the value.\n\nBut this delete operation might not be always successful. For example, you might provide the wrong\nkey to this method. I mean, maybe you provide\n(either intentionally or unintentionally) a key that points to an empty bucket,\ni.e., a bucket that still doesn't have a value in it.\nIn this case, the `remove()` method would return a `false` value.\n\n\n\n### Iterating through the hashtable\n\nIterating through the keys and values that are currently being stored in\nthe hashtable is a very common necessity.\nYou can do that in Zig by using an iterator object that can iterate\nthrough the elements of your hashtable object.\n\nThis iterator object works like any other iterator object that you would\nfind in languages such as C++ and Rust. It's basically a pointer object\nthat points to some value in the container, and has a `next()` method\nthat you can use to navigate (or iterate) through the values in the\ncontainer.\n\nYou can create such iterator object by using the `iterator()` method of the hashtable object.\nThis method returns an iterator object, from which you can use the `next()` method in conjunction\nwith a while loop to iterate through the elements of your hashtable. The `next()` method returns an optional\n`Entry` value, and therefore, you must unwrap this optional value to get the actual `Entry` value\nfrom which you can access the key and also the value identified by this key.\n\nWith this `Entry` value at hand, you can access the key of this current entry by using the `key_ptr`\nattribute and dereferencing the pointer that lives inside of it, while the value identified by this\nkey is accessed through the `value_ptr` attribute instead, which is also a pointer to be dereferenced.\nThe code example below demonstrates the use of these elements:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst AutoHashMap = std.hash_map.AutoHashMap;\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var hash_table = AutoHashMap(u32, u16).init(allocator);\n defer hash_table.deinit();\n\n try hash_table.put(54321, 89);\n try hash_table.put(50050, 55);\n try hash_table.put(57709, 41);\n\n var it = hash_table.iterator();\n while (it.next()) |kv| {\n // Access the current key\n std.debug.print(\"Key: {d} | \", .{kv.key_ptr.*});\n // Access the current value\n std.debug.print(\"Value: {d}\\n\", .{kv.value_ptr.*});\n }\n}\n```\n:::\n\n\n\n\n```\nKey: 54321 | Value: 89\nKey: 50050 | Value: 55\nKey: 57709 | Value: 41\n```\n\n\nIf you want to iterate specifically through the values or the keys of your hashtable,\nyou can create a key iterator or a value iterator object. These are also iterator\nobjects, which have the same `next()` method that you can use to iterate through the\nhashtable.\n\nKey iterators are created from the `keyIterator()` method of your\nhashtable object, while value iterators are created from the `valueIterator()` method.\nAll you have to do is to unwrap the value from the `next()` method and deference it\ndirectly to access the key or the value that you are iterating over.\nThe code example below demonstrates the use of a key iterator,\nbut you can replicate the same logic to a value iterator.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar kit = hash_table.keyIterator();\nwhile (kit.next()) |key| {\n std.debug.print(\"Key: {d}\\n\", .{key.*});\n}\n```\n:::\n\n\n\n\n```\nKey: 54321\nKey: 50050\nKey: 57709\n```\n\n\n### The `ArrayHashMap` hashtable {#sec-array-map}\n\nIf you need to iterate through the elements of your hashtable constantly,\nyou might want to use the `ArrayHashMap` struct for your specific case,\ninstead of going with the usual and general-purpose `HashMap` struct.\n\nThe `ArrayHashMap` struct creates a hashtable that is faster to iterate over.\nThat is why this specific type of hashtable might be valuable to you.\nSome other properties of a `ArrayHashMap` hashtable are:\n\n- the order of insertion is preserved, i.e., the order of the values that you find while iterating through this hashtable is actually the order in which these values were inserted in the hashtable.\n- the key-value pairs are stored sequentially, one after another.\n\n\nYou can create an `ArrayHashMap` object by using, once again, a helper function that\nchooses automatically for you a hash function implementation. This is the\n`AutoArrayHashMap()` function, which works very similarly to the `AutoHashMap()`\nfunction that we presented in @sec-hashmap.\n\nYou provide two data types to this function. The data type of the keys that will be\nused in this hashtable, and the data type of the values that will be stored in\nthis hashtable.\n\nAn `ArrayHashMap` object have essentially the exact same methods from the `HashMap` struct.\nSo you can insert new values into the hashtable by using the `put()` method, and you can look (or get)\na value from the hashtable by using the `get()` method. But the `remove()` method is not available\nin this specific type of hashtable.\n\nIn order to delete values from the hashtable, you would use the same methods that you find in\nan `ArrayList` object, i.e., a dynamic array. I presented these methods in @sec-dynamic-array-remove,\nwhich are the `swapRemove()` and `orderedRemove()` methods. These methods have the same meaning here, or,\nthe same effect that they have in an `ArrayList` object.\n\nThis means that, with `swapRemove()` you remove the value from the hashtable, but you do not preserve\nthe order in which the values were inserted into the structure. While `orderedRemove()` is able\nto retain the order in which these values were inserted.\n\nBut instead of providing an index as input to `swapRemove()` or `orderedRemove()`, like I described\nin @sec-dynamic-array-remove, these methods here in an `ArrayHashMap` take a key as input, like\nthe `remove()` method from a `HashMap` object. If you want to provide an index as input, instead\nof a key, you should use the `swapRemoveAt()` and `orderedRemoveAt()` methods.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar hash_table = AutoArrayHashMap(u32, u16)\n .init(allocator);\ndefer hash_table.deinit();\n```\n:::\n\n\n\n\n\n\n### The `StringHashMap` hashtable {#sec-string-hash-map}\n\nOne thing that you will notice in the other two types of hashtables that I have\npresented over the last sections, is that neither of them accepts a slice data type\nin their keys.\nWhat this means is that you cannot use a slice value to represent a key in\nthese types of hashtable.\n\nThe most obvious consequence of this, is that you cannot use strings as keys\nin these hashtables. But it's extremely common to use strings as keys\nin hashtables.\n\nTake this very simple Javascript code snippet as an example. We are creating\na simple hashtable object named `people`. Then, we add a new entry to this\nhashtable, which is identified by the string `'Pedro'`. This string is the\nkey in this case, while the object containing different personal information such as\nage, height and city, is the value to be stored in the hashtable.\n\n```js\nvar people = new Object();\npeople['Pedro'] = {\n 'age': 25,\n 'height': 1.67,\n 'city': 'Belo Horizonte'\n};\n```\n\nThis pattern of using strings as keys is very common in\nall sorts of situations. That is why the Zig Standard Library offers a\nspecific type of hashtable for this purpose, which is created through the `StringHashMap()` function.\nThis function creates a hashtable that uses strings as keys. The only input of this\nfunction is the data type of the values that will be stored into this hashtable.\n\nIn the example below, I'm creating a hashtable to store the ages of different people.\nEach key in this hashtable is represented by the name of each person, while the value stored in the\nhashtable is the age of this person identified by the key.\n\nThat is why I provide the `u8` data type (which is the data type used by the age values) as input to this `StringHashMap()` function.\nAs the result, it creates a hashtable that uses string values as keys, and, that stores\n`u8` values in it. Notice that an allocator object is provided at the `init()` method of the\nresulting object from the `StringHashMap()` function.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var ages = std.StringHashMap(u8).init(allocator);\n defer ages.deinit();\n\n try ages.put(\"Pedro\", 25);\n try ages.put(\"Matheus\", 21);\n try ages.put(\"Abgail\", 42);\n\n var it = ages.iterator();\n while (it.next()) |kv| {\n std.debug.print(\"Key: {s} | \", .{kv.key_ptr.*});\n std.debug.print(\"Age: {d}\\n\", .{kv.value_ptr.*});\n }\n}\n```\n:::\n\n\n\n\n```\nKey: Pedro | Age: 25\nKey: Abgail | Age: 42\nKey: Matheus | Age: 21\n```\n\n\n### The `StringArrayHashMap` hashtable\n\nThe Zig Standard Library also provides a type of hashtable that mix the cons and pros of the\n`StringHashMap` and `ArrayHashMap` together. That is, a hashtable\nthat uses strings as keys, but also have the advantages from `ArrayHashMap`.\nIn other words, you can have a hashtable that is fast to iterate over,\nthat preserves insertion order, and also, that uses strings as keys.\n\nYou can create such type of hashtable by using the `StringArrayHashMap()` function.\nThis function accepts a data type as input, which is the data type of the values that are\ngoing to be stored inside this hashtable, in the same style as the function presented\nin @sec-string-hash-map.\n\nYou can insert new values into this hashtable by using the same `put()` method that\nwe have discussed in @sec-string-hash-map. And you can also get values from the hashtable\nby using the same `get()` method.\nLike its `ArrayHashMap` brother, to delete values from this specific type of hashtable,\nwe also use the `orderedRemove()` and `swapRemove()` methods, with the same effects that\nI have described in @sec-array-map.\n\nIf we take the code example that was exposed in @sec-string-hash-map, we can\nachieve the exact same result with `StringArrayHashMap()`:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar ages = std.StringArrayHashMap(u8).init(allocator);\n```\n:::\n\n\n\n\n\n\n\n## Linked lists\n\nThe Zig Standard Library provides an implementation for both singly and doubly linked lists.\nA linked list is a linear data structure that looks like a chain, or, a rope.\nThe main advantage of this data structure is that you normally have very fast\ninsertion and deletion operations. But, as a disadvantage, iterating through\nthis data structure is usually not so fast as iterating through an array.\n\nThe idea behind a linked list is to build a structure that consists of a sequence of nodes\nconnected to each other by pointers. This means that linked lists are usually not contiguous\nin memory, because each node might be anywhere in memory. They do not need to be close to\none another.\n\nIn @fig-linked-list we can see a diagram of a singly linked list. We begin at the first node\n(which is usually called \"the head of the linked list\"). Then, from this\nfirst node we uncover the remaining nodes in the structure, by following the locations pointed\nby the pointers found in each node.\n\nEach node has two things in it. It has the value that is stored in the current node\n, and also, a pointer. This pointer points to the next node in the list. If this pointer\nis null, then, it means that we have reached the end of our linked list.\n\n![A diagram of a singly linked list.](./../Figures/linked-list.png){#fig-linked-list}\n\n\nIn @fig-linked-list2 we can see a diagram of a doubly linked list. The only thing that really\nchanges now is that every node in the linked list has both a pointer to the previous node,\nand, a pointer to the next node. So every node in a doubly linked list has two pointers in it. These are\nusually called the `prev` (for \"previous\") and the `next` (for \"next\") pointers of the node.\n\nIn the singly linked list example, we had only one single pointer in each node, and this singular\npointer was always pointing to the next node in the sequence. This means that singly linked lists\nnormally have only the `next` pointer in them.\n\n![A diagram of a doubly linked list.](./../Figures/doubly-linked-list.png){#fig-linked-list2}\n\n\nLinked lists are available in Zig through the functions `SinglyLinkedList()` and\n`DoublyLinkedList()`, for \"singly linked lists\" and \"doubly linked lists\", respectively. These functions are\nactually generic functions, which we are going to talk more about in @sec-generic-fun.\n\nFor now, just understand that, in order to create a linked list object,\nwe begin by providing a data type to these functions. This data type defines\nthe type of data that each node in this linked list will store. In the example below,\nwe are creating a singly linked list of `u32` values.\nSo each node in this linked list will store a `u32` value.\n\nBoth the `SinglyLinkedList()` and `DoublyLinkedList()` functions returns a type,\ni.e., a struct definition, as output. Therefore, the object `Lu32` is actually\na struct definition. It defines the type \"singly linked list of `u32` values\".\n\nNow that we have the definition of the struct, we need to instantiate a `Lu32` object.\nWe normally instantiate struct objects in Zig by using an `init()` method.\nBut in this case, we are instantiating the struct directly, by using an empty\n`struct` literal, in the expression `Lu32{}`.\n\nIn this example, we first create multiple node objects, and after we create them,\nwe start to insert and connect these nodes to build the linked list, using the\n`prepend()` and `insertAfter()` methods. Notice that the `prepend()` method\nis a method from the linked list object, while the `insertAfter()` is a method\npresent in the node objects.\n\nIn essence, the `prepend()` method inserts a node at the beginning of the linked\nlist. In other words, the node that you provide to this method, becomes the new\n\"head node\" of the linked list. It becomes the first node in the list (see @fig-linked-list).\n\nOn the other side, the `insertAfter()` method is used to basically connect two nodes together.\nWhen you provide a node to this method, it creates a pointer to this input node,\nand stores this pointer in the `next` attribute of the current node, from which the method was called from.\n\nBecause doubly linked lists have both a `next` and a `prev` attributes in each node\n(as described in @fig-linked-list2), a node object created from\na `DoublyLinkedList` object have both an `insertBefore()` (for `prev`)\nand an `insertAfter()` (for `next`) methods available.\n\nThus, if we have used a doubly linked list, we can use the `insertBefore()` method\nto store the pointer to the input node in the `prev` attribute. This would put the input\nnode as the \"previous node\", or, the node before the current node. In contrast, the `insertAfter()` method\nputs the pointer created to the input node in the `next` attribute of the current node,\nand as result, the input node becomes the \"next node\" of the current node.\n\nSince we are using a singly linked list in this example, we have only the `insertAfter()` method\navailable in the node objects that we create from our `Lu32` type.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SinglyLinkedList = std.SinglyLinkedList;\nconst Lu32 = SinglyLinkedList(u32);\n\npub fn main() !void {\n var list = Lu32{};\n var one = Lu32.Node{ .data = 1 };\n var two = Lu32.Node{ .data = 2 };\n var three = Lu32.Node{ .data = 3 };\n var four = Lu32.Node{ .data = 4 };\n var five = Lu32.Node{ .data = 5 };\n\n list.prepend(&two); // {2}\n two.insertAfter(&five); // {2, 5}\n list.prepend(&one); // {1, 2, 5}\n two.insertAfter(&three); // {1, 2, 3, 5}\n three.insertAfter(&four); // {1, 2, 3, 4, 5}\n}\n```\n:::\n\n\n\n\n\nThere are other methods available from the linked list object, depending if this object is\na singly linked list or a doubly linked list, that might be very useful for you. You can find a\nsummary of them in the bullet points below:\n\n- `remove()` to remove a specific node from the linked list.\n- if singly linked list, `len()` to count how many nodes there is in the linked list.\n- if doubly linked list, checkout the `len` attribute to see how many nodes there is in the linked list.\n- if singly linked list, `popFirst()` to remove the first node (i.e., the \"head\") from the linked list.\n- if doubly linked list, `pop()` and `popFirst()` to remove the last and first nodes from the linked list, respectively.\n- if doubly linked list, `append()` to add a new node to end of the linked list (i.e., inverse of `prepend()`).\n\n\n\n## Multi array structure\n\nZig introduces a new data structure called `MultiArrayList()`. It's a different version of the dynamic array\nthat we have introduced in @sec-dynamic-array. The difference between this structure and the `ArrayList()`\nthat we know from @sec-dynamic-array, is that `MultiArrayList()` creates a separate dynamic array\nfor each field of the struct that you provide as input.\n\nConsider the following code example. We create a new custom struct called `Person`. This\nstruct contains three different data members, or, three different fields. As consequence,\nwhen we provide this `Person` data type as input to `MultiArrayList()`, this\ncreates a \"struct of three different arrays\" called `PersonArray`. In other words,\nthis `PersonArray` is a struct that contains three internal dynamic arrays in it.\nOne array for each field found in the `Person` struct definition.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Person = struct {\n name: []const u8,\n age: u8,\n height: f32,\n};\nconst PersonArray = std.MultiArrayList(Person);\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var people = PersonArray{};\n defer people.deinit(allocator);\n\n try people.append(allocator, .{\n .name = \"Auguste\", .age = 15, .height = 1.54\n });\n try people.append(allocator, .{\n .name = \"Elena\", .age = 26, .height = 1.65\n });\n try people.append(allocator, .{\n .name = \"Michael\", .age = 64, .height = 1.87\n });\n}\n```\n:::\n\n\n\n\nIn other words, instead of creating an array of \"persons\", the `MultiArrayList()` function\ncreates a \"struct of arrays\". Each data member of this struct is a different array that stores\nthe values of a specific field from the `Person` values that were added (or, appended) to this \"struct of arrays\".\nOne important detail is that each of these separate internal arrays stored inside `PersonArray`\nare dynamic arrays. This means that these arrays can grow in capacity automatically as needed, to accomodate\nmore values.\n\nThe @fig-multi-array exposed below presents a diagram that describes the `PersonArray` struct\nthat we have created in the previous code example. Notice that the values of the data members\npresent in each of the three `Person` values that we have appended into the `PersonArray` object\n, are scattered across three different internal arrays of the `PersonArray` object.\n\n![A diagram of the `PersonArray` struct.](./../Figures/multi-array.png){#fig-multi-array}\n\nYou can easily access each of these arrays separately, and iterate over the values of each array.\nFor that, you will need to call the `items()` method from the `PersonArray` object, and provide as input\nto this method, the name of the field that you want to iterate over.\nIf you want to iterate through the `.age` array for example, then, you need to call `items(.age)` from\nthe `PersonArray` object, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (people.items(.age)) |*age| {\n try stdout.print(\"Age: {d}\\n\", .{age.*});\n}\n```\n:::\n\n\n\n\n```\nAge: 15\nAge: 26\nAge: 64\n```\n\n\nIn the above example, we are iterating over the values of the `.age` array, or,\nthe internal array of the `PersonArray` object that contains the values of the `age`\ndata member from the `Person` values that were added to the multi array struct.\n\nIn this example we are calling the `items()` method directly from the `PersonArray`\nobject. However, in most situations it's recommened to call this `items()` method\nfrom a \"slice object\", which you can create from the `slice()` method.\nThe reason for this is that calling `items()` multiple times have better performance\nif you use a slice object.\n\nTherefore, if you are planning to access only one of the\ninternal arrays from your \"multi array struct\", it's fine to call `items()` directly\nfrom the multi array object. But if you need to access many of the internal arrays\nfrom your \"multi array struct\", then, you will likely need to call `items()` more\nthan once, and, in such circumstance, is better to call `items()` through a slice object.\nThe example below demonstrates the use of such object:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar slice = people.slice();\nfor (slice.items(.age)) |*age| {\n age.* += 10;\n}\nfor (slice.items(.name), slice.items(.age)) |*n,*a| {\n try stdout.print(\n \"Name: {s}, Age: {d}\\n\", .{n.*, a.*}\n );\n}\n```\n:::\n\n\n\n\n```\nName: Auguste, Age: 25\nName: Elena, Age: 36\nName: Michael, Age: 74\n```\n\n\n## Conclusion\n\nThere are many other data structures that I haven't presented here.\nBut you can check them out at the official Zig Standard Library documentation page.\nActually, when you get into the [homepage of the documentation](https://ziglang.org/documentation/master/std/#)[^home], the first thing\nthat appears to you in this page, is a list of types and data structures that\nare available in the Zig Standard Library.\nThere are some very specific data structures in this list, like a\n[`BoundedArray` struct](https://ziglang.org/documentation/master/std/#std.bounded_array.BoundedArray)[^bounded]\n, but there is also some more general structures, such as a\n[`PriorityQueue` struct](https://ziglang.org/documentation/master/std/#std.priority_queue.PriorityQueue)[^priority].\n\n\n[^home]: \n[^priority]: .\n[^bounded]: \n", + "supporting": [ + "09-data-structures_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/09-error-handling/execute-results/html.json b/_freeze/Chapters/09-error-handling/execute-results/html.json index 39ca6f04..aaffaa3e 100644 --- a/_freeze/Chapters/09-error-handling/execute-results/html.json +++ b/_freeze/Chapters/09-error-handling/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "0e6b825195db1ba992b740206fa34ec0", + "hash": "1ef4c69c6b1bfd8553723d38f6a46fb8", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Error handling and unions {#sec-error-handling}\n\nIn this chapter, I want to discuss how error handling is done in Zig.\nWe already briefly learned about one of the available strategies to handle errors in Zig,\nwhich is the `try` keyword presented at @sec-main-file. But we still haven't learned about\nthe other methods, such as the `catch` keyword.\nI also want to discuss in this chapter how union types are created in Zig.\n\n## Learning more about errors in Zig\n\nBefore we get into how error handling is done, we need to learn more about what errors are in Zig.\nAn error is actually a value in Zig [@zigoverview]. In other words, when an error occurs inside your Zig program,\nit means that somewhere in your Zig codebase, an error value is being generated.\nAn error value is similar to any integer value that you create in your Zig code.\nYou can take an error value and pass it as input to a function,\nand you can also cast (or coerce) it into a different type of an error value.\n\nThis have some similarities with exceptions in C++ and Python.\nBecause in C++ and Python, when an exception happens inside a `try` block,\nyou can use a `catch` block (in C++) or an `except` block (in Python)\nto capture the exception produced in the `try` block,\nand pass it to functions as an input.\n\nHowever, error values in Zig are treated very differently than exceptions.\nFirst, you cannot ignore error values in your Zig code. Meaning that, if an error\nvalue appears somewhere in your source code, this error value must be explicitly handled in some way.\nThis also means that you cannot discard error values by assigning them to an underscore,\nas you could do with normal values and objects.\n\nTake the source code below as an example. Here we are trying to open a file that does not exist\nin my computer, and as a result, an obvious error value of `FileNotFound` is returned from the `openFile()`\nfunction. But because I'm assigning the result of this function to an underscore, I end up\ntrying to discard an error value.\n\nThe `zig` compiler detects this mistake, and raises a compile\nerror telling me that I'm trying to discard an error value.\nIt also adds a note message that suggests the use of `try`,\n`catch` or an if statement to explicitly handle this error value\nThis note is reinforcing that every possible error value must be explicitly handled in Zig.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst dir = std.fs.cwd();\n_ = dir.openFile(\"doesnt_exist.txt\", .{});\n```\n:::\n\n\n\n\n```\nt.zig:8:17: error: error set is discarded\nt.zig:8:17: note: consider using 'try', 'catch', or 'if'\n```\n\n\n### Returning errors from functions\n\nAs we described at @sec-main-file, when we have a function that might return an error\nvalue, this function normally includes an exclamation mark (`!`) in its return type\nannotation. The presence of this exclamation mark indicates that this function might\nreturn an error value as result, and, the `zig` compiler forces you to always handle explicitly\nthe case of this function returning an error value.\n\nTake a look at the `print_name()` function below. This function might return an error in the `stdout.print()` function call,\nand, as a consequence, its return type (`!void`) includes an exclamation mark in it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_name() !void {\n const stdout = std.getStdOut().writer();\n try stdout.print(\"My name is Pedro!\", .{});\n}\n```\n:::\n\n\n\n\nIn the example above, we are using the exclamation mark to tell the `zig` compiler\nthat this function might return some error. But which error exactly is returned from\nthis function? For now, we are not specifying a specific error value. We only\nknown for now that some error value (whatever it is) might be returned.\n\nBut in fact, you can (if you want to) specify clearly which exact error values\nmight be returned from this function. There are lot of examples of\nthis in the Zig Standard Library. Take this `fill()` function from\nthe `http.Client` module as an example. This function returns\neither a error value of type `ReadError`, or `void`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn fill(conn: *Connection) ReadError!void {\n // The body of this function ...\n}\n```\n:::\n\n\n\n\nThis idea of specifying the exact error values that you expect to be returned\nfrom the function is interesting. Because they automatically become some sort of documentation\nof your function, and also, it allows the `zig` compiler to perform some extra checks over\nyour code. Because it can check if there is any other type of error value\nthat is being generated inside your function, and, that it is not being accounted\nfor in this return type annotation.\n\nAnyway, you can list the types of errors that can be returned from the function\nby listing them on the left side of the exclamation mark. While the valid values\nstay on the right side of the exclamation mark. So the syntax format become:\n\n```\n!\n```\n\n\n### Error sets\n\nBut what about when we have a single function that might return different types of errors?\nWhen you have such a function, you can list\nall of these different types of errors that can be returned from this function,\nthrough a structure in Zig that we call of an *error set*.\n\nAn error set is a special case of an union type. It is an union that contains error values in it.\nNot all programming languages have a notion of an \"union object\".\nBut in summary, an union is just a set of data types.\nUnions are used to allow an object to have multiple data types.\nFor example, a union of `x`, `y` and `z`, means that\nan object can be either of type `x`, or type `y` or type `z`.\n\nWe are going to talk in more depth about unions at @sec-unions.\nBut you can write an error set by writing the keyword `error` before\na pair of curly braces, then you list the error values that can be\nreturned from the function inside this pair of curly braces.\n\nTake the `resolvePath()` function below as an example, which comes from the\n`introspect.zig` module of the Zig Standard Library. We can see in its return type annotation, that this\nfunction return either: 1) a valid slice of `u8` values (`[]u8`); or, 2) one of the three different\ntypes of error values listed inside the error set (`OutOfMemory`, `Unexpected`, etc.).\nThis is an usage example of an error set.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn resolvePath(\n ally: mem.Allocator,\n p: []const u8,\n) error{\n OutOfMemory,\n CurrentWorkingDirectoryUnlinked,\n Unexpected,\n}![]u8 {\n // The body of the function ...\n}\n```\n:::\n\n\n\n\n\nThis is a valid way of annotating the return value of a Zig function. But, if you navigate through\nthe modules that composes the Zig Standard Library, you will notice that, for the majority of cases,\nthe programmers prefer to give a descriptive name to this error set, and then, use this name (or this \"label\")\nof the error set in the return type annotation, instead of using the error set directly.\n\nWe can see that in the `ReadError` error set that we showed earlier in the `fill()` function,\nwhich is defined in the `http.Client` module.\nSo yes, I presented the `ReadError` as if it was just a standard and single error value, but in fact,\nit is an error set defined in the `http.Client` module, and therefore, it actually represents\na set of different error values that might happen inside the `fill()` function.\n\n\nTake a look at the `ReadError` definition reproduced below. Notice that we are grouping all of these\ndifferent error values into a single object, and then, we use this object into the return type annotation of the function.\nLike the `fill()` function that we showed earlier, or, the `readvDirect()` function from the same module,\nwhich is reproduced below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const ReadError = error{\n TlsFailure,\n TlsAlert,\n ConnectionTimedOut,\n ConnectionResetByPeer,\n UnexpectedReadFailure,\n EndOfStream,\n};\n// Some lines of code\npub fn readvDirect(\n conn: *Connection,\n buffers: []std.posix.iovec\n ) ReadError!usize {\n // The body of the function ...\n}\n```\n:::\n\n\n\n\nSo, an error set is just a convenient way of grouping a set of\npossible error values into a single object, or a single type of an error value.\n\n\n### Casting error values\n\nLet's suppose you have two different error sets, named `A` and `B`.\nIf error set `A` is a superset of error set `B`, then, you can cast (or coerce)\nerror values from `B` into error values of `A`.\n\nError sets are just a set of error values. So, if the error set `A`\ncontains all error values from the error set `B`, then `A`\nbecomes a superset of `B`. You could also say\nthat the error set `B` is a subset of error set `A`.\n\nThe example below demonstrates this idea. Because `A` contains all\nvalues from `B`, `A` is a superset of `B`.\nIn math notation, we would say that $A \\supset B$.\nAs a consequence, we can give an error value from `B` as input to the `cast()`\nfunction, and, implicitly cast this input into the same error value, but from the `A` set.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst A = error{\n ConnectionTimeoutError,\n DatabaseNotFound,\n OutOfMemory,\n InvalidToken,\n};\nconst B = error {\n OutOfMemory,\n};\n\nfn cast(err: B) A {\n return err;\n}\n\ntest \"coerce error value\" {\n const error_value = cast(B.OutOfMemory);\n try std.testing.expect(\n error_value == A.OutOfMemory\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filea64e1da1167c.test.coerce error value...OKA\n All 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n## How to handle errors\n\nNow that we learned more about what errors are in Zig,\nlet's discuss the available strategies to handle these errors,\nwhich are:\n\n- `try` keyword;\n- `catch` keyword;\n- an if statement;\n- `errdefer` keyword;\n\n\n\n### What `try` means?\n\nAs I described over the previous sections, when we say that an expression might\nreturn an error, we are basically referring to an expression that have\na return type in the format `!T`.\nThe `!` indicates that this expression returns either an error value, or a value of type `T`.\n\nAt @sec-main-file, I presented the `try` keyword and where to use it.\nBut I did not talked about what exactly this keyword does to your code,\nor, in other words, I have not explained yet what `try` means in your code.\n\nIn essence, when you use the `try` keyword in an expression, you are telling\nthe `zig` compiler the following: \"Hey! Execute this expression for me,\nand, if this expression return an error, please, return this error for me\nand stop the execution of my program. But if this expression return a valid\nvalue, then, return this value, and move on\".\n\nIn other words, the `try` keyword is essentially, a strategy to enter in panic mode, and stop\nthe execution of your program in case an error occurs.\nWith the `try` keyword, you are telling the `zig` compiler, that stopping the execution\nof your program is the most reasonable strategy to take if an error occurs\nin that particular expression.\n\n### The `catch` keyword\n\nOk, now that we understand properly what `try` means, let's discuss `catch` now.\nOne important detail here, is that you can use `try` or `catch` to handle your errors,\nbut you **cannot use `try` and `catch` together**. In other words, `try` and `catch`\nare different and completely separate strategies in the Zig language.\n\nThis is uncommon, and different than what happens in other languages. Most\nprogramming languages that adopts the *try catch* pattern (such as C++, R, Python, Javascript, etc.), normally use\nthese two keywords together to form the complete logic to\nproperly handle the errors.\nAnyway, Zig tries a different approach in the *try catch* pattern.\n\nSo, we learned already about what `try` means, and we also known that both\n`try` and `catch` should be used alone, separate from each other. But\nwhat exactly `catch` do in Zig? With `catch`, we can construct a block of\nlogic to handle the error value, in case it happens in the current expression.\n\nLook at the code example below. Once again, we go back to the previous\nexample where we were trying to open a file that doesn't exist in my computer,\nbut this time, I use `catch` to actually implement a logic to handle the error, instead of\njust stopping the execution right away.\n\nMore specifically, in this example, I'm using a logger object to record some logs into\nthe system, before I return the error, and stop the execution of the program. For example,\nthis could be some part of the codebase of a complex system that I do not have full control over,\nand I want to record these logs before the program crashes, so that I can debug it later\n(e.g. maybe I cannot compile the full program, and properly debug it with a debugger. So, these logs might\nbe a valid strategy to surpass this barrier).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst dir = std.fs.cwd();\nconst file = dir.openFile(\n \"doesnt_exist.txt\", .{}\n) catch |err| {\n logger.record_context();\n logger.log_error(err);\n return err;\n};\n```\n:::\n\n\n\n\n\nTherefore, we use `catch` to create a block of expressions that will handle the error.\nI can return the error value from this block of expressions, like I did in the above example,\nwhich, will make the program enter in panic mode, and, stop the execution.\nBut I could also, return a valid value from this block of code, which would\nbe stored in the `file` object.\n\nNotice that, instead of writing the keyword before the expression that might return the error,\nlike we do with `try`, we write `catch` after the expression. We can open the pair of pipes (`|`),\nwhich captures the error value returned by the expression, and makes\nthis error value available in the scope of the `catch` block as the object named `err`.\nIn other words, because I wrote `|err|` in the code, I can access the error value\nreturned by the expression, by using the `err` object.\n\nAlthough this being the most common use of `catch`, you can also use this keyword\nto handle the error in a \"default value\" style. That is, if the expression returns\nan error, we use the default value instead. Otherwise, we use the valid value returned\nby the expression.\n\nThe Zig official language reference, provides a great example of this \"default value\"\nstrategy with `catch`. This example is reproduced below. Notice that we are trying to parse\nsome unsigned integer from a string object named `str`. In other words, this function\nis trying to transform an object of type `[]const u8` (i.e. an array of characters, a string, etc.)\ninto an object of type `u64`.\n\nBut this parsing process done by the function `parseU64()` may fail, resulting in a runtime error.\nThe `catch` keyword used in this example provides an alternative value (13) to be used in case\nthis `parseU64()` function raises an error. So, the expression below essentially means:\n\"Hey! Please, parse this string into a `u64` for me, and store the results into the\nobject `number`. But, if an error occurs, then, use the value `13` instead\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number = parseU64(str, 10) catch 13;\n```\n:::\n\n\n\n\nSo, at the end of this process, the object `number` will contain either a `u64` integer\nthat was parsed successfully from the input string `str`, or, if an error occurs in the\nparsing process, it will contain the `u64` value `13` that was provided by the `catch`\nkeyword as the \"default\", or, the \"alternative\" value.\n\n\n\n### Using if statements\n\nNow, you can also use if statements to handle errors in your Zig code.\nIn the example below, I'm reproducing the previous example, where\nwe try to parse an integer value from an input string with a function\nnamed `parseU64()`.\n\nWe execute the expression inside the \"if\". If this expression returns an\nerror value, the \"if branch\" (or, the \"true branch\") of the if statement is not executed.\nBut if this expression returns a valid value instead, then, this value is unwrapped\ninto the `number` object.\n\nThis means that, if the `parseU64()` expression returns a valid value, this value becomes available\ninside the scope of this \"if branch\" (i.e. the \"true branch\") through the object that we listed inside the pair\nof pipe character (`|`), which is the object `number`.\n\nIf an error occurs, we can use an \"else branch\" (or the \"false branch\") of the if statement\nto handle the error. In the example below, we are using the `else` in the if statement\nto unwrap the error value (that was returned by `parseU64()`) into the `err` object,\nand handle the error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (parseU64(str, 10)) |number| {\n // do something with `number` here\n} else |err| {\n // handle the error value.\n}\n```\n:::\n\n\n\n\nNow, if the expression that you are executing returns different types of error values,\nand you want to take a different action in each of these types of error values, the\n`try` and `catch` keywords, and the if statement strategy, becomes limited.\n\nFor this type of situation, the official documentation of the language suggests\nthe use of a switch statement together with an if statement [@zigdocs].\nThe basic idea is, to use the if statement to execute the expression, and\nuse the \"else branch\" to pass the error value to a switch statement, where\nyou define a different action for each type of error value that might be\nreturned by the expression executed in the if statement.\n\nThe example below demonstrates this idea. We first try to add (or register) a set of\ntasks to a queue. If this \"registration process\" occurs well, we then try\nto distribute these tasks across the workers of our system. But\nif this \"registration process\" returns an error value, we then use a switch\nstatement in the \"else branch\" to handle each possible error value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (add_tasks_to_queue(&queue, tasks)) |_| {\n distribute_tasks(&queue);\n} else |err| switch (err) {\n error.InvalidTaskName => {\n // do something\n },\n error.TimeoutTooBig => {\n // do something\n },\n error.QueueNotFound => {\n // do something\n },\n // and all the other error options ...\n}\n```\n:::\n\n\n\n\n\n### The `errdefer` keyword {#sec-errdefer2}\n\nA common pattern in C programs in general, is to clean resources when an error occurs during\nthe execution of the program. In other words, one common way to handle errors, is to perform\n\"cleanup actions\" before we exit our program. This guarantees that a runtime error does not make\nour program to leak resources of the system.\n\n\nThe `errdefer` keyword is a tool to perform such \"cleanup actions\" in hostile situations.\nThis keyword is commonly used to clean (or to free) allocated resources, before the execution of our program\nget's stopped because of an error value being generated.\n\nThe basic idea is to provide an expression to the `errdefer` keyword. Then,\n`errdefer` executes this expression if, and only if, an error occurs\nduring the execution of the current scope.\nIn the example below, we are using an allocator object (that we have presented at @sec-allocators)\nto create a new `User` object. If we are successful in creating and registering this new user,\nthis `create_user()` function will return this new `User` object as its return value.\n\nHowever, if for some reason, an error value is generated by some expression\nthat is after the `errdefer` line, for example, in the `db.add(user)` expression,\nthe expression registered by `errdefer` get's executed before the error value is returned\nfrom the function, and before the program enters in panic mode and stops the\ncurrent execution.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn create_user(db: Database, allocator: Allocator) !User {\n const user = try allocator.create(User);\n errdefer allocator.destroy(user);\n\n // Register new user in the Database.\n _ = try db.register_user(user);\n return user;\n}\n```\n:::\n\n\n\n\nBy using `errdefer` to destroy the `user` object that we have just created,\nwe guarantee that the memory allocated for this `user` object\nget's freed, before the execution of the program stops.\nBecause if the expression `try db.add(user)` returns an error value,\nthe execution of our program stops, and we lose all references and control over the memory\nthat we have allocated for the `user` object.\nAs a result, if we do not free the memory associated with the `user` object before the program stops,\nwe cannot free this memory anymore. We simply lose our chance to do the right thing.\nThat is why `errdefer` is essential in this situation.\n\nJust to state clearly the differences between `defer` and `errdefer`\n(which I described at @sec-defer and @sec-errdefer1), it might be worth\nto discuss the subject a bit further. You might still have the question\n\"why use `errdefer` if we can use `defer` instead?\" in your mind.\n\nAlthough being similar, the key difference between `errdefer` and `defer` keyword\nis when the provided expression get's executed.\nThe `defer` keyword always execute the provided expression at the end of the\ncurrent scope, no matter how your code exits this scope.\nIn contrast, `errdefer` executes the provided expression only when an error occurs in the\ncurrent scope.\n\nThis becomes important if a resource that you allocate in the\ncurrent scope get's freed later in your code, in a different scope.\nThe `create_user()` functions is an example of this. If you think\nclosely about this function, you will notice that this function returns\nthe `user` object as the result.\n\nIn other words, the allocated memory for the `user` object does not get\nfreed inside the `create_user()` function, if it returns successfully.\nSo, if an error does not occur inside this function, the `user` object\nis returned from the function, and probably, the code that runs after\nthis `create_user()` function will be responsible for freeing\nthe memory of the `user` object.\n\nBut what if an error occurs inside the `create_user()` function? What happens then?\nThis would mean that the execution of your code would stop in this `create_user()`\nfunction, and, as a consequence, the code that runs after this `create_user()`\nfunction would simply not run, and, as a result, the memory of the `user` object\nwould not be freed before your program stops.\n\nThis is the perfect scenario for `errdefer`. We use this keyword to guarantee\nthat our program will free the allocated memory for the `user` object,\neven if an error occurs inside the `create_user()` function.\n\nIf you allocate and free some memory for an object inside the same scope, then,\njust use `defer` and be happy, i.e. `errdefer` have no use for you in such situation.\nBut if you allocate some memory in a scope A, but you only free this memory\nlater, in a scope B for example, then, `errdefer` becomes useful to avoid leaking memory\nin sketchy situations.\n\n\n\n## Union type in Zig {#sec-unions}\n\nAn union type defines a set of types that an object can be. It is like a list of\noptions. Each option is a type that an object can assume. Therefore, unions in Zig\nhave the same meaning, or, the same role as unions in C. They are used for the same purpose.\nYou could also say that unions in Zig produces a similar effect to\n[using `typing.Union` in Python](https://docs.python.org/3/library/typing.html#typing.Union)[^pyunion].\n\n[^pyunion]: \n\nFor example, you might be creating an API that sends data to a data lake, hosted\nin some private cloud infrastructure. Suppose you have created different structs in your codebase,\nto store the necessary information that you need, in order to connect to the services of\neach mainstream data lake service (Amazon S3, Azure Blob, etc.).\n\nNow, suppose you also have a function named `send_event()` that receives an event as input,\nand, a target data lake, and it sends the input event to the data lake specified in the\ntarget data lake argument. But this target data lake could be any of the three mainstream data lakes\nservices (Amazon S3, Azure Blob, etc.). Here is where an union can help you.\n\nThe union `LakeTarget` defined below allows the `lake_target` argument of `send_event()`\nto be either an object of type `AzureBlob`, or type `AmazonS3`, or type `GoogleGCP`.\nThis union allows the `send_event()` function to receive an object of any of these three types\nas input in the `lake_target` argument.\n\nRemember that each of these three types (`AmazonS3`, `GoogleGCP` and `AzureBlob`)\nare separate structs that we have defined in our source code. So, at first glance,\nthey are separate data types in our source code. But is the `union` keyword that\nunifies them into a single data type called `LakeTarget`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst LakeTarget = union {\n azure: AzureBlob,\n amazon: AmazonS3,\n google: GoogleGCP,\n};\n\nfn send_event(\n event: Event,\n lake_target: LakeTarget\n) bool {\n // body of the function ...\n}\n```\n:::\n\n\n\n\nAn union definition is composed by a list of data members. Each data member is of a specific data type.\nIn the example above, the `LakeTarget` union have three data members (`azure`, `amazon`, `google`).\nWhen you instantiate an object that uses an union type, you can only use one of its data members\nin this instantiation.\n\nYou could also interpret this as: only one data member of an union type can be activated at a time, the other data\nmembers remain deactivated and unaccessible. For example, if you create a `LakeTarget` object that uses\nthe `azure` data member, you can no longer use or access the data members `google` or `amazon`.\nIt is like if these other data members didn't exist at all in the `LakeTarget` type.\n\nYou can see this logic in the example below. Notice that, we first instantiate the union\nobject using the `azure` data member. As a result, this `target` object contains only\nthe `azure` data member inside of it. Only this data member is active in this object.\nThat is why the last line in this code example is invalid. Because we are trying to instantiate the data member\n`google`, which is currently inactive for this `target` object, and as a result, the program\nenters in panic mode warning us about this mistake through a loud error message.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar target = LakeTarget {\n .azure = AzureBlob.init()\n};\n// Only the `azure` data member exist inside\n// the `target` object, and, as a result, this\n// line below is invalid:\ntarget.google = GoogleGCP.init();\n```\n:::\n\n\n\n\n```\nthread 2177312 panic: access of union field 'google' while\n field 'azure' is active:\n target.google = GoogleGCP.init();\n ^\n```\n\nSo, when you instantiate an union object, you must choose one of the data types (or, one of the data members)\nlisted in the union type. In the example above, I choose to use the `azure` data member, and, as a result,\nall other data members were automatically deactivated,\nand you can no longer use them after you instantiate the object.\n\nYou can activate another data member by completely redefining the entire enum object.\nIn the example below, I initially use the `azure` data member. But then, I redefine the\n`target` object to use a new `LakeTarget` object, which uses the `google` data member.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar target = LakeTarget {\n .azure = AzureBlob.init()\n};\ntarget = LakeTarget {\n .google = GoogleGCP.init()\n};\n```\n:::\n\n\n\n\nA curious fact about union types, is that, at first, you cannot use them in switch statements (which were presented at @sec-switch).\nIn other words, if you have an object of type `LakeTarget` for example, you cannot give this object\nas input to a switch statement.\n\nBut what if you really need to do so? What if you actually need to\nprovide an \"union object\" to a switch statement? The answer to this question relies on another special type in Zig,\nwhich are the *tagged unions*. To create a tagged union, all you have to do is to add\nan enum type into your union declaration.\n\nAs an example of a tagged union in Zig, take the `Registry` type exposed\nbelow. This type comes from the\n[`grammar.zig` module](https://github.com/ziglang/zig/blob/30b4a87db711c368853b3eff8e214ab681810ef9/tools/spirv/grammar.zig)[^grammar]\nfrom the Zig repository. This union type lists different types of registries.\nBut notice this time, the use of `(enum)` after the `union` keyword. This is what makes\nthis union type a tagged union. By being a tagged union, an object of this `Registry` type\ncan be used as input in a switch statement. This is all you have to do. Just add `(enum)`\nto your `union` declaration, and you can use it in switch statements.\n\n[^grammar]: .\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Registry = union(enum) {\n core: CoreRegistry,\n extension: ExtensionRegistry,\n};\n```\n:::\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Error handling and unions {#sec-error-handling}\n\nIn this chapter, I want to discuss how error handling is done in Zig.\nWe already briefly learned about one of the available strategies to handle errors in Zig,\nwhich is the `try` keyword presented in @sec-main-file. But we still haven't learned about\nthe other methods, such as the `catch` keyword.\nI also want to discuss in this chapter how union types are created in Zig.\n\n## Learning more about errors in Zig\n\nBefore we get into how error handling is done, we need to learn more about what errors are in Zig.\nAn error is actually a value in Zig [@zigoverview]. In other words, when an error occurs inside your Zig program,\nit means that somewhere in your Zig codebase, an error value is being generated.\nAn error value is similar to any integer value that you create in your Zig code.\nYou can take an error value and pass it as input to a function,\nand you can also cast (or coerce) it into a different type of an error value.\n\nThis have some similarities with exceptions in C++ and Python.\nBecause in C++ and Python, when an exception happens inside a `try` block,\nyou can use a `catch` block (in C++) or an `except` block (in Python)\nto capture the exception produced in the `try` block,\nand pass it to functions as an input.\n\nHowever, error values in Zig are treated very differently than exceptions.\nFirst, you cannot ignore error values in your Zig code. Meaning that, if an error\nvalue appears somewhere in your source code, this error value must be explicitly handled in some way.\nThis also means that you cannot discard error values by assigning them to an underscore,\nas you could do with normal values and objects.\n\nTake the source code below as an example. Here we are trying to open a file that does not exist\nin my computer, and as a result, an obvious error value of `FileNotFound` is returned from the `openFile()`\nfunction. But because I'm assigning the result of this function to an underscore, I end up\ntrying to discard an error value.\n\nThe `zig` compiler detects this mistake, and raises a compile\nerror telling me that I'm trying to discard an error value.\nIt also adds a note message that suggests the use of `try`,\n`catch` or an if statement to explicitly handle this error value\nThis note is reinforcing that every possible error value must be explicitly handled in Zig.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst dir = std.fs.cwd();\n_ = dir.openFile(\"doesnt_exist.txt\", .{});\n```\n:::\n\n\n\n\n```\nt.zig:8:17: error: error set is discarded\nt.zig:8:17: note: consider using 'try', 'catch', or 'if'\n```\n\n\n### Returning errors from functions\n\nAs we described in @sec-main-file, when we have a function that might return an error\nvalue, this function normally includes an exclamation mark (`!`) in its return type\nannotation. The presence of this exclamation mark indicates that this function might\nreturn an error value as result, and, the `zig` compiler forces you to always handle explicitly\nthe case of this function returning an error value.\n\nTake a look at the `print_name()` function below. This function might return an error in the `stdout.print()` function call,\nand, as a consequence, its return type (`!void`) includes an exclamation mark in it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_name() !void {\n const stdout = std.getStdOut().writer();\n try stdout.print(\"My name is Pedro!\", .{});\n}\n```\n:::\n\n\n\n\nIn the example above, we are using the exclamation mark to tell the `zig` compiler\nthat this function might return some error. But which error exactly is returned from\nthis function? For now, we are not specifying a specific error value. For now,\nwe only know that some error value (whatever it is) might be returned.\n\nBut in fact, you can (if you want to) specify clearly which exact error values\nmight be returned from this function. There are lot of examples of\nthis in the Zig Standard Library. Take this `fill()` function from\nthe `http.Client` module as an example. This function returns\neither a error value of type `ReadError`, or `void`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn fill(conn: *Connection) ReadError!void {\n // The body of this function ...\n}\n```\n:::\n\n\n\n\nThis idea of specifying the exact error values that you expect to be returned\nfrom the function is interesting. Because they automatically become some sort of documentation\nof your function, and also, this allows the `zig` compiler to perform some extra checks over\nyour code. Because the compiler can check if there is any other type of error value\nthat is being generated inside your function, and, that it's not being accounted\nfor in this return type annotation.\n\nAnyway, you can list the types of errors that can be returned from the function\nby listing them on the left side of the exclamation mark. While the valid values\nstay on the right side of the exclamation mark. So the syntax format become:\n\n```\n!\n```\n\n\n### Error sets\n\nBut what about when we have a single function that might return different types of errors?\nWhen you have such a function, you can list\nall of these different types of errors that can be returned from this function,\nthrough a structure in Zig that we call of an *error set*.\n\nAn error set is a special case of a union type. It's a union that contains error values in it.\nNot all programming languages have a notion of a \"union object\".\nBut in summary, a union is just a set of data types.\nUnions are used to allow an object to have multiple data types.\nFor example, a union of `x`, `y` and `z`, means that\nan object can be either of type `x`, or type `y` or type `z`.\n\nWe are going to talk in more depth about unions in @sec-unions.\nBut you can write an error set by writing the keyword `error` before\na pair of curly braces, then you list the error values that can be\nreturned from the function inside this pair of curly braces.\n\nTake the `resolvePath()` function below as an example, which comes from the\n`introspect.zig` module of the Zig Standard Library. We can see in its return type annotation, that this\nfunction return either: 1) a valid slice of `u8` values (`[]u8`); or, 2) one of the three different\ntypes of error values listed inside the error set (`OutOfMemory`, `Unexpected`, etc.).\nThis is an usage example of an error set.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn resolvePath(\n ally: mem.Allocator,\n p: []const u8,\n) error{\n OutOfMemory,\n CurrentWorkingDirectoryUnlinked,\n Unexpected,\n}![]u8 {\n // The body of the function ...\n}\n```\n:::\n\n\n\n\n\nThis is a valid way of annotating the return value of a Zig function. But, if you navigate through\nthe modules that composes the Zig Standard Library, you will notice that, for the majority of cases,\nthe programmers prefer to give a descriptive name to this error set, and then, use this name (or this \"label\")\nof the error set in the return type annotation, instead of using the error set directly.\n\nWe can see that in the `ReadError` error set that we showed earlier in the `fill()` function,\nwhich is defined in the `http.Client` module.\nSo yes, I presented the `ReadError` as if it was just a standard and single error value, but in fact,\nit's an error set defined in the `http.Client` module, and therefore, it actually represents\na set of different error values that might happen inside the `fill()` function.\n\n\nTake a look at the `ReadError` definition reproduced below. Notice that we are grouping all of these\ndifferent error values into a single object, and then, we use this object into the return type annotation of the function.\nLike the `fill()` function that we showed earlier, or, the `readvDirect()` function from the same module,\nwhich is reproduced below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const ReadError = error{\n TlsFailure,\n TlsAlert,\n ConnectionTimedOut,\n ConnectionResetByPeer,\n UnexpectedReadFailure,\n EndOfStream,\n};\n// Some lines of code\npub fn readvDirect(\n conn: *Connection,\n buffers: []std.posix.iovec\n ) ReadError!usize {\n // The body of the function ...\n}\n```\n:::\n\n\n\n\nSo, an error set is just a convenient way of grouping a set of\npossible error values into a single object, or a single type of an error value.\n\n\n### Casting error values\n\nLet's suppose you have two different error sets, named `A` and `B`.\nIf error set `A` is a superset of error set `B`, then, you can cast (or coerce)\nerror values from `B` into error values of `A`.\n\nError sets are just a set of error values. So, if the error set `A`\ncontains all error values from the error set `B`, then `A`\nbecomes a superset of `B`. You could also say\nthat the error set `B` is a subset of error set `A`.\n\nThe example below demonstrates this idea. Because `A` contains all\nvalues from `B`, `A` is a superset of `B`.\nIn math notation, we would say that $A \\supset B$.\nAs a consequence, we can give an error value from `B` as input to the `cast()`\nfunction, and, implicitly cast this input into the same error value, but from the `A` set.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst A = error{\n ConnectionTimeoutError,\n DatabaseNotFound,\n OutOfMemory,\n InvalidToken,\n};\nconst B = error {\n OutOfMemory,\n};\n\nfn cast(err: B) A {\n return err;\n}\n\ntest \"coerce error value\" {\n const error_value = cast(B.OutOfMemory);\n try std.testing.expect(\n error_value == A.OutOfMemory\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file826379a872a1.test.coerce error value...OKA\n All 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n## How to handle errors\n\nNow that we learned more about what errors are in Zig,\nlet's discuss the available strategies to handle these errors,\nwhich are:\n\n- `try` keyword;\n- `catch` keyword;\n- an if statement;\n- `errdefer` keyword;\n\n\n\n### What `try` means?\n\nAs I described over the previous sections, when we say that an expression might\nreturn an error, we are basically referring to an expression that have\na return type in the format `!T`.\nThe `!` indicates that this expression returns either an error value, or a value of type `T`.\n\nIn @sec-main-file, I presented the `try` keyword and where to use it.\nBut I did not talked about what exactly this keyword does to your code,\nor, in other words, I have not explained yet what `try` means in your code.\n\nIn essence, when you use the `try` keyword in an expression, you are telling\nthe `zig` compiler the following: \"Hey! Execute this expression for me,\nand, if this expression return an error, please, return this error for me\nand stop the execution of my program. But if this expression return a valid\nvalue, then, return this value, and move on\".\n\nIn other words, the `try` keyword is essentially, a strategy to enter in panic mode, and stop\nthe execution of your program in case an error occurs.\nWith the `try` keyword, you are telling the `zig` compiler, that stopping the execution\nof your program is the most reasonable strategy to take if an error occurs\nin that particular expression.\n\n### The `catch` keyword\n\nOk, now that we understand properly what `try` means, let's discuss `catch` now.\nOne important detail here, is that you can use `try` or `catch` to handle your errors,\nbut you **cannot use `try` and `catch` together**. In other words, `try` and `catch`\nare different and completely separate strategies in the Zig language.\n\nThis is uncommon, and different than what happens in other languages. Most\nprogramming languages that adopts the *try catch* pattern (such as C++, R, Python, Javascript, etc.), normally use\nthese two keywords together to form the complete logic to\nproperly handle the errors.\nAnyway, Zig tries a different approach in the *try catch* pattern.\n\nSo, we learned already about what `try` means, and we also known that both\n`try` and `catch` should be used alone, separate from each other. But\nwhat exactly `catch` do in Zig? With `catch`, we can construct a block of\nlogic to handle the error value, in case it happens in the current expression.\n\nLook at the code example below. Once again, we go back to the previous\nexample where we were trying to open a file that doesn't exist in my computer,\nbut this time, I use `catch` to actually implement a logic to handle the error, instead of\njust stopping the execution right away.\n\nMore specifically, in this example, I'm using a logger object to record some logs into\nthe system, before I return the error, and stop the execution of the program. For example,\nthis could be some part of the codebase of a complex system that I do not have full control over,\nand I want to record these logs before the program crashes, so that I can debug it later\n(e.g. maybe I cannot compile the full program, and properly debug it with a debugger. So, these logs might\nbe a valid strategy to surpass this barrier).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst dir = std.fs.cwd();\nconst file = dir.openFile(\n \"doesnt_exist.txt\", .{}\n) catch |err| {\n logger.record_context();\n logger.log_error(err);\n return err;\n};\n```\n:::\n\n\n\n\n\nTherefore, we use `catch` to create a block of expressions that will handle the error.\nI can return the error value from this block of expressions, like I did in the above example,\nwhich, will make the program enter in panic mode, and, stop the execution.\nBut I could also, return a valid value from this block of code, which would\nbe stored in the `file` object.\n\nNotice that, instead of writing the keyword before the expression that might return the error,\nlike we do with `try`, we write `catch` after the expression. We can open the pair of pipes (`|`),\nwhich captures the error value returned by the expression, and makes\nthis error value available in the scope of the `catch` block as the object named `err`.\nIn other words, because I wrote `|err|` in the code, I can access the error value\nreturned by the expression, by using the `err` object.\n\nAlthough this being the most common use of `catch`, you can also use this keyword\nto handle the error in a \"default value\" style. That is, if the expression returns\nan error, we use the default value instead. Otherwise, we use the valid value returned\nby the expression.\n\nThe Zig official language reference, provides a great example of this \"default value\"\nstrategy with `catch`. This example is reproduced below. Notice that we are trying to parse\nsome unsigned integer from a string object named `str`. In other words, this function\nis trying to transform an object of type `[]const u8` (i.e., an array of characters, a string, etc.)\ninto an object of type `u64`.\n\nBut this parsing process done by the function `parseU64()` may fail, resulting in a runtime error.\nThe `catch` keyword used in this example provides an alternative value (13) to be used in case\nthis `parseU64()` function raises an error. So, the expression below essentially means:\n\"Hey! Please, parse this string into a `u64` for me, and store the results into the\nobject `number`. But, if an error occurs, then, use the value `13` instead\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number = parseU64(str, 10) catch 13;\n```\n:::\n\n\n\n\nSo, at the end of this process, the object `number` will contain either a `u64` integer\nthat was parsed successfully from the input string `str`, or, if an error occurs in the\nparsing process, it will contain the `u64` value `13` that was provided by the `catch`\nkeyword as the \"default\", or, the \"alternative\" value.\n\n\n\n### Using if statements\n\nNow, you can also use if statements to handle errors in your Zig code.\nIn the example below, I'm reproducing the previous example, where\nwe try to parse an integer value from an input string with a function\nnamed `parseU64()`.\n\nWe execute the expression inside the \"if\". If this expression returns an\nerror value, the \"if branch\" (or, the \"true branch\") of the if statement is not executed.\nBut if this expression returns a valid value instead, then, this value is unwrapped\ninto the `number` object.\n\nThis means that, if the `parseU64()` expression returns a valid value, this value becomes available\ninside the scope of this \"if branch\" (i.e., the \"true branch\") through the object that we listed inside the pair\nof pipe character (`|`), which is the object `number`.\n\nIf an error occurs, we can use an \"else branch\" (or the \"false branch\") of the if statement\nto handle the error. In the example below, we are using the `else` in the if statement\nto unwrap the error value (that was returned by `parseU64()`) into the `err` object,\nand handle the error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (parseU64(str, 10)) |number| {\n // do something with `number` here\n} else |err| {\n // handle the error value.\n}\n```\n:::\n\n\n\n\nNow, if the expression that you are executing returns different types of error values,\nand you want to take a different action in each of these types of error values, the\n`try` and `catch` keywords, and the if statement strategy, becomes limited.\n\nFor this type of situation, the official documentation of the language suggests\nthe use of a switch statement together with an if statement [@zigdocs].\nThe basic idea is, to use the if statement to execute the expression, and\nuse the \"else branch\" to pass the error value to a switch statement, where\nyou define a different action for each type of error value that might be\nreturned by the expression executed in the if statement.\n\nThe example below demonstrates this idea. We first try to add (or register) a set of\ntasks to a queue. If this \"registration process\" occurs well, we then try\nto distribute these tasks across the workers of our system. But\nif this \"registration process\" returns an error value, we then use a switch\nstatement in the \"else branch\" to handle each possible error value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (add_tasks_to_queue(&queue, tasks)) |_| {\n distribute_tasks(&queue);\n} else |err| switch (err) {\n error.InvalidTaskName => {\n // do something\n },\n error.TimeoutTooBig => {\n // do something\n },\n error.QueueNotFound => {\n // do something\n },\n // and all the other error options ...\n}\n```\n:::\n\n\n\n\n\n### The `errdefer` keyword {#sec-errdefer2}\n\nA common pattern in C programs in general, is to clean resources when an error occurs during\nthe execution of the program. In other words, one common way to handle errors, is to perform\n\"cleanup actions\" before we exit our program. This guarantees that a runtime error does not make\nour program to leak resources of the system.\n\n\nThe `errdefer` keyword is a tool to perform such \"cleanup actions\" in hostile situations.\nThis keyword is commonly used to clean (or to free) allocated resources, before the execution of our program\ngets stopped because of an error value being generated.\n\nThe basic idea is to provide an expression to the `errdefer` keyword. Then,\n`errdefer` executes this expression if, and only if, an error occurs\nduring the execution of the current scope.\nIn the example below, we are using an allocator object (that we have presented in @sec-allocators)\nto create a new `User` object. If we are successful in creating and registering this new user,\nthis `create_user()` function will return this new `User` object as its return value.\n\nHowever, if for some reason, an error value is generated by some expression\nthat is after the `errdefer` line, for example, in the `db.add(user)` expression,\nthe expression registered by `errdefer` gets executed before the error value is returned\nfrom the function, and before the program enters in panic mode and stops the\ncurrent execution.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn create_user(db: Database, allocator: Allocator) !User {\n const user = try allocator.create(User);\n errdefer allocator.destroy(user);\n\n // Register new user in the Database.\n _ = try db.register_user(user);\n return user;\n}\n```\n:::\n\n\n\n\nBy using `errdefer` to destroy the `user` object that we have just created,\nwe guarantee that the memory allocated for this `user` object\ngets freed, before the execution of the program stops.\nBecause if the expression `try db.add(user)` returns an error value,\nthe execution of our program stops, and we lose all references and control over the memory\nthat we have allocated for the `user` object.\nAs a result, if we do not free the memory associated with the `user` object before the program stops,\nwe cannot free this memory anymore. We simply lose our chance to do the right thing.\nThat is why `errdefer` is essential in this situation.\n\nJust to state clearly the differences between `defer` and `errdefer`\n(which I described in @sec-defer and @sec-errdefer1), it might be worth\nto discuss the subject a bit further. You might still have the question\n\"why use `errdefer` if we can use `defer` instead?\" in your mind.\n\nAlthough being similar, the key difference between `errdefer` and `defer` keyword\nis when the provided expression gets executed.\nThe `defer` keyword always execute the provided expression at the end of the\ncurrent scope, no matter how your code exits this scope.\nIn contrast, `errdefer` executes the provided expression only when an error occurs in the\ncurrent scope.\n\nThis becomes important if a resource that you allocate in the\ncurrent scope gets freed later in your code, in a different scope.\nThe `create_user()` functions is an example of this. If you think\nclosely about this function, you will notice that this function returns\nthe `user` object as the result.\n\nIn other words, the allocated memory for the `user` object does not get\nfreed inside the `create_user()` function, if it returns successfully.\nSo, if an error does not occur inside this function, the `user` object\nis returned from the function, and probably, the code that runs after\nthis `create_user()` function will be responsible for freeing\nthe memory of the `user` object.\n\nBut what if an error occurs inside the `create_user()` function? What happens then?\nThis would mean that the execution of your code would stop in this `create_user()`\nfunction, and, as a consequence, the code that runs after this `create_user()`\nfunction would simply not run, and, as a result, the memory of the `user` object\nwould not be freed before your program stops.\n\nThis is the perfect scenario for `errdefer`. We use this keyword to guarantee\nthat our program will free the allocated memory for the `user` object,\neven if an error occurs inside the `create_user()` function.\n\nIf you allocate and free some memory for an object inside the same scope, then,\njust use `defer` and be happy, i.e., `errdefer` have no use for you in such situation.\nBut if you allocate some memory in a scope A, but you only free this memory\nlater, in a scope B for example, then, `errdefer` becomes useful to avoid leaking memory\nin sketchy situations.\n\n\n\n## Union type in Zig {#sec-unions}\n\nA union type defines a set of types that an object can be. It's like a list of\noptions. Each option is a type that an object can assume. Therefore, unions in Zig\nhave the same meaning, or, the same role as unions in C. They are used for the same purpose.\nYou could also say that unions in Zig produces a similar effect to\n[using `typing.Union` in Python](https://docs.python.org/3/library/typing.html#typing.Union)[^pyunion].\n\n[^pyunion]: \n\nFor example, you might be creating an API that sends data to a data lake, hosted\nin some private cloud infrastructure. Suppose you have created different structs in your codebase,\nto store the necessary information that you need, in order to connect to the services of\neach mainstream data lake service (Amazon S3, Azure Blob, etc.).\n\nNow, suppose you also have a function named `send_event()` that receives an event as input,\nand, a target data lake, and it sends the input event to the data lake specified in the\ntarget data lake argument. But this target data lake could be any of the three mainstream data lakes\nservices (Amazon S3, Azure Blob, etc.). Here is where an union can help you.\n\nThe union `LakeTarget` defined below allows the `lake_target` argument of `send_event()`\nto be either an object of type `AzureBlob`, or type `AmazonS3`, or type `GoogleGCP`.\nThis union allows the `send_event()` function to receive an object of any of these three types\nas input in the `lake_target` argument.\n\nRemember that each of these three types (`AmazonS3`, `GoogleGCP` and `AzureBlob`)\nare separate structs that we have defined in our source code. So, at first glance,\nthey are separate data types in our source code. But is the `union` keyword that\nunifies them into a single data type called `LakeTarget`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst LakeTarget = union {\n azure: AzureBlob,\n amazon: AmazonS3,\n google: GoogleGCP,\n};\n\nfn send_event(\n event: Event,\n lake_target: LakeTarget\n) bool {\n // body of the function ...\n}\n```\n:::\n\n\n\n\nAn union definition is composed by a list of data members. Each data member is of a specific data type.\nIn the example above, the `LakeTarget` union have three data members (`azure`, `amazon`, `google`).\nWhen you instantiate an object that uses an union type, you can only use one of its data members\nin this instantiation.\n\nYou could also interpret this as: only one data member of an union type can be activated at a time, the other data\nmembers remain deactivated and unaccessible. For example, if you create a `LakeTarget` object that uses\nthe `azure` data member, you can no longer use or access the data members `google` or `amazon`.\nIt's like if these other data members didn't exist at all in the `LakeTarget` type.\n\nYou can see this logic in the example below. Notice that, we first instantiate the union\nobject using the `azure` data member. As a result, this `target` object contains only\nthe `azure` data member inside of it. Only this data member is active in this object.\nThat is why the last line in this code example is invalid. Because we are trying to instantiate the data member\n`google`, which is currently inactive for this `target` object, and as a result, the program\nenters in panic mode warning us about this mistake through a loud error message.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar target = LakeTarget {\n .azure = AzureBlob.init()\n};\n// Only the `azure` data member exist inside\n// the `target` object, and, as a result, this\n// line below is invalid:\ntarget.google = GoogleGCP.init();\n```\n:::\n\n\n\n\n```\nthread 2177312 panic: access of union field 'google' while\n field 'azure' is active:\n target.google = GoogleGCP.init();\n ^\n```\n\nSo, when you instantiate an union object, you must choose one of the data types (or, one of the data members)\nlisted in the union type. In the example above, I choose to use the `azure` data member, and, as a result,\nall other data members were automatically deactivated,\nand you can no longer use them after you instantiate the object.\n\nYou can activate another data member by completely redefining the entire enum object.\nIn the example below, I initially use the `azure` data member. But then, I redefine the\n`target` object to use a new `LakeTarget` object, which uses the `google` data member.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar target = LakeTarget {\n .azure = AzureBlob.init()\n};\ntarget = LakeTarget {\n .google = GoogleGCP.init()\n};\n```\n:::\n\n\n\n\nA curious fact about union types, is that, at first, you cannot use them in switch statements (which were presented in @sec-switch).\nIn other words, if you have an object of type `LakeTarget` for example, you cannot give this object\nas input to a switch statement.\n\nBut what if you really need to do so? What if you actually need to\nprovide an \"union object\" to a switch statement? The answer to this question relies on another special type in Zig,\nwhich are the *tagged unions*. To create a tagged union, all you have to do is to add\nan enum type into your union declaration.\n\nAs an example of a tagged union in Zig, take the `Registry` type exposed\nbelow. This type comes from the\n[`grammar.zig` module](https://github.com/ziglang/zig/blob/30b4a87db711c368853b3eff8e214ab681810ef9/tools/spirv/grammar.zig)[^grammar]\nfrom the Zig repository. This union type lists different types of registries.\nBut notice this time, the use of `(enum)` after the `union` keyword. This is what makes\nthis union type a tagged union. By being a tagged union, an object of this `Registry` type\ncan be used as input in a switch statement. This is all you have to do. Just add `(enum)`\nto your `union` declaration, and you can use it in switch statements.\n\n[^grammar]: .\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Registry = union(enum) {\n core: CoreRegistry,\n extension: ExtensionRegistry,\n};\n```\n:::\n", + "supporting": [ + "09-error-handling_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/10-stack-project/execute-results/html.json b/_freeze/Chapters/10-stack-project/execute-results/html.json index 2bc7f08f..398f20fc 100644 --- a/_freeze/Chapters/10-stack-project/execute-results/html.json +++ b/_freeze/Chapters/10-stack-project/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "0c651ab91f56f6b099ea4bfebc8882dd", + "hash": "fe2d7fa4c6d4bcadd97ff3ab647083a0", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 3 - Building a stack data structure\n\nIn this chapter we are going to implement a stack data structure as our next small project\nin this book. Implementing basic data structures in any language is kind of a\n\"kindergarten task\" (if this term even exist) in computer science (CS), because\nwe normally learn and implement them in the first semesters of CS.\n\nBut this is actually good! Since this should be a very easy task, we don't need much to explain\nwhat a stack is, then, we can concentrate on what is really important here, which is learning\nhow the concept of \"generics\" is implemented in the Zig language, and how one of the key\nfeatures of Zig, which is comptime, works, and use the stack data structure to demonstrate\nthese concepts on the fly.\n\nBut before we get into building the stack data structure, we first need to understand\nwhat the `comptime` keyword does to your code, and after that, we also need to learn about\nhow generics work in Zig.\n\n\n## Understanding `comptime` in Zig {#sec-comptime}\n\nOne of the key features of Zig is `comptime`. This keyword introduces a whole\nnew concept and paradigm, that is tightly connected with the compilation process.\nAt @sec-compile-time we have described the importance and the role that \"compile-time versus runtime\"\nplays into Zig. At that section, we learned that the rules applied to a value/object change\na lot depending on whether this value is known at compile-time, or just at runtime.\n\nThe `comptime` keyword is strongly related to these two spaces in time (compile-time and runtime).\nLet's quickly recap the differences. Compile-time is the period of time when your\nZig source code is being compiled by the `zig` compiler, while the runtime is\nthe period of time when your Zig program is being executed, i.e. when we execute\nthe binary files that were generated by the `zig` compiler.\n\nThere are three ways in which you can apply the `comptime` keyword, which are:\n\n- apply `comptime` on a function argument.\n- apply `comptime` on an object.\n- apply `comptime` on a block of expressions.\n\n\n\n### Applying over a function argument\n\nWhen you apply the `comptime` keyword on a function argument, you are saying to the `zig` compiler\nthat the value assigned to that particular function argument must be known at compile-time.\nWe explained in details at @sec-compile-time what exactly \"value known at compile-time\" means, so,\nin case you have doubts about this idea, come back to that section.\n\nNow let's think about the consequences of this idea. First of all, we are imposing a limit, or, a requirement\nto that particular function argument. If the programmer accidentally tries to give a value to this\nfunction argument that is not known at compile time, the `zig` compiler will notice this problem, and\nas a consequence, it will raise a compilation error saying that it cannot compile your program. Because\nyou are providing a value that is \"runtime known\" to a function argument that must be \"compile-time known\".\n\nTake a look at this very simple example below, where we define a `twice()` function, that simply\ndoubles the input value named `num`. Notice that we use the `comptime` keyword before the name\nof the function argument. This keyword is marking the function argument `num` as a \"comptime argument\".\n\nThat is a function argument whose value must be compile-time known. This is why the expression\n`twice(5678)` is valid, and no compilation errors are raised. Because the value `5678`\nis compile-time known, so this is the expected behaviour for this function.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\ntest \"test comptime\" {\n _ = twice(5678);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filea72d248f97f8.test.test comptime...OKAll 1 \n tests passed.\n```\n\n\n:::\n:::\n\n\n\n\nBut what if we provide a number that is not compile-time known to this function?\nFor example, we might provide a different input value to this function depending\non the target OS of our compilation process. The code example below demonstrates such case.\n\nBecause the value of the object `n` is determined at runtime, we cannot provide this object\nas input to the `twice()` function. The `zig` compiler will not allow it, because we marked\nthe `num` argument as a \"comptime argument\". That is why the `zig` compiler raises\nthe compile-time error exposed below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\ntest \"test comptime\" {\n var n: u32 = undefined;\n if (builtin.target.os.tag == .windows) {\n n = 1234;\n } else {\n n = 5678;\n }\n _ = twice(n);\n}\n```\n:::\n\n\n\n\n```\nt.zig:12:16: error: runtime-known argument passed to comptime parameter \n```\n\nComptime arguments are frequently used on functions that return some sort\nof generic structure. In fact, `comptime` is the essence (or the basis) to make generics in Zig.\nWe are going to talk more about generics at @sec-generics.\n\nFor now, let's take a look at this code example from @karlseguin_generics. You\ncan see that this `IntArray()` function have one argument named `length`.\nThis argument is marked as comptime, and receives a value of type `usize` as input. So the value given to this argument\nmust be compile-time known.\nWe can also see that this function returns an array of `i64` values as output.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn IntArray(comptime length: usize) type {\n return [length]i64;\n}\n```\n:::\n\n\n\n\nNow, the key component of this function is the `length` argument. This argument\nis used to determine the size of the array that is produced by the function. Let's\nthink about the consequences of that. If the size of the array is dependent on\nthe value assigned to the `length` argument, this means that the data type of the\noutput of the function depends on the value of this `length` argument.\n\nLet this statement sink for a bit in your mind. As I described at @sec-root-file,\nZig is a strongly-typed language, especially on function declarations.\nSo every time we write a function in Zig, we have to annotate the data type of\nthe value returned by the function. But how can we do that, if this data type\ndepends on the value given to the argument of the function?\n\nThink about this for a second. If `length` is equal to 3 for example, then, the\nreturn type of the function is `[3]i64`. But if `length` is equal to 40, then,\nthe return type becomes `[40]i64`. At this point the `zig` compiler would be confused,\nand raise a compilation error, saying something like this:\n\n> Hey! You have annotated that this function should return a `[3]i64` value, but I got a `[40]i64` value instead! This doesn't look right!\n\nSo how can you solve this problem? How do we overcome this barrier? This is when\nthe `type` keyword comes in. This `type` keyword is basically saying to the\n`zig` compiler that this function will return some data type as output, but it doesn't know yet\nwhat exactly data type that is. We will talk more about this at @sec-generics.\n\n\n\n### Applying over an expression\n\nWhen you apply the `comptime` keyword over an expression, then, it is guaranteed that the `zig` compiler will\nexecute this expression at compile-time. If for some reason, this expression cannot be executed at compile-time\n(e.g. for example, maybe this expression depends on a value that is only known at runtime), then, the `zig` compiler\nwill raise a compilation error.\n\nTake this example from the official documentation of Zig [@zigdocs]. We\nare executing the same `fibonacci()` function both at runtime, and, at compile-time.\nThe function is by default executed at runtime, but because we use the `comptime`\nkeyword at the second \"try expression\", this expression is executed at compile-time.\n\nThis might be a bit confusing for some people. Yes! When I say that this expression\nis executed at compile-time, I mean that this expression is compiled and executed\nwhile the `zig` compiler is compiling your Zig source code.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci\" {\n // test fibonacci at run-time\n try expect(fibonacci(7) == 13);\n // test fibonacci at compile-time\n try comptime expect(fibonacci(7) == 13);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filea72d3cf7abe2.test.fibonacci...OKAll 1 test\n ts passed.\n```\n\n\n:::\n:::\n\n\n\n\nA lot of your Zig source code might be potentially executed at compile-time,\nbecause the `zig` compiler can figure it out the output of some expressions.\nEspecially if these expressions depends only at compile-time known values.\nWe have talked about this at @sec-compile-time.\n\nBut when you use the `comptime` keyword on an expression, there is no \"it might be executed\nat compile-time\" anymore. With the `comptime` keyword you are ordering the `zig` compiler\nto execute this expression at compile-time. You are imposing this rule, it is guaranteed\nthat the compiler will always execute it at compile-time. Or, at least, the compiler\nwill try to execute it. If the compiler cannot execute the expression for whatever reason,\nthe compiler will raise a compilation error.\n\n\n### Applying over a block\n\nBlocks were described at @sec-blocks. When you apply the `comptime` keyword over a\nblock of expressions, you get essentially the same effect when you apply this keyword to\na single expression. That is, the entire block of expressions is executed at\ncompile-time by the `zig` compiler.\n\nIn the example below, we mark the block labeled of `blk` as a comptime block,\nand, therefore, the expressions inside this block are executed at compile-time.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci in a block\" {\n const x = comptime blk: {\n const n1 = 5;\n const n2 = 2;\n const n3 = n1 + n2;\n try expect(fibonacci(n3) == 13);\n break :blk n3;\n };\n _ = x;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filea72d6353d586.test.fibonacci in a block...O\n OKAll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## Introducing Generics {#sec-generics}\n\nFirst of all, what is a generic? Generic is the idea to allow a type\n(`f64`, `u8`, `u32`, `bool`, and also, user-defined types, like the `User` struct\nthat we defined at @sec-structs-and-oop) to be a parameter to methods, classes and\ninterfaces [@geeks_generics]. In other words, a \"generic\" is a class (or a method) that can work\nwith multiple data types.\n\nFor example, in Java, generics are created through the operator `<>`. With this operator,\na Java class is capable of receiving a data type as input, and therefore, the class can fit\nits features according to this input data type.\nAs another example, generics in C++ are supported through the concept of templates.\nClass templates in C++ are generics.\n\nIn Zig, generics are implemented through `comptime`. The `comptime` keyword\nallows us to collect a data type at compile time, and pass this data type as\ninput to a piece of code.\n\n\n### A generic function {#sec-generic-fun}\n\nTake the `max()` function exposed below as a first example.\nThis function is essentially a \"generic function\".\nIn this function, we have a comptime function argument named `T`.\nNotice that this `T` argument have a data type of `type`. Weird right? This `type` keyword is the\n\"father of all types\", or, \"the type of types\" in Zig.\n\nBecause we have used this `type` keyword in the `T` argument, we are telling\nthe `zig` compiler that this `T` argument will receive some data type as input.\nAlso notice the use of the `comptime` keyword in this argument.\nAs I described at @sec-comptime, every time you use this keyword in a function argument,\nthis means that the value of this argument must be known at compile-time.\nThis makes sense, right? Because there is no data type that is not known at compile-time.\n\nThink about this. Every data type that you will ever write is always\nknown at compile-time. Especially because data types are an essential\ninformation for the compiler to actually compile your source code.\nHaving this in mind, makes sense to mark this argument as a comptime argument.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn max(comptime T: type, a: T, b: T) T {\n return if (a > b) a else b;\n}\n```\n:::\n\n\n\n\nAlso notice that the value of the `T` argument is actually used\nto define the data type of the other arguments in the function, `a` and `b`, and also at the\nreturn type annotation of the function.\nThat is, the data type of these arguments (`a` and `b`), and, the return data type of the function itself,\nare determined by the input value given to the `T` argument.\n\nAs a result, we have a generic function that works with different data types.\nFor example, I can provide `u8` values to this `max()` function, and it will work as expected.\nBut if I provide `f64` values instead, it will also work as expected.\nWithout a generic function, I would have to write a different `max()` function\nfor each one of the data types that I wanted to use.\nThis generic function provides a very useful shortcut for us.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn max(comptime T: type, a: T, b: T) T {\n return if (a > b) a else b;\n}\ntest \"test max\" {\n const n1 = max(u8, 4, 10);\n std.debug.print(\"Max n1: {d}\\n\", .{n1});\n const n2 = max(f64, 89.24, 64.001);\n std.debug.print(\"Max n2: {d}\\n\", .{n2});\n}\n```\n:::\n\n\n\n\n```\nMax n1: 10\nMax n2: 89.24\n```\n\n\n### A generic data structure {#sec-generic-struct}\n\nEvery data structure that you find in the Zig Standard Library (e.g. `ArrayList`, `HashMap`, etc.)\nis essentially a generic data structure.\nThese data structures are generic in the sense that they work with any data type you want.\nYou just say which is the data type of the values that are going to be stored in this data\nstructure, and they just work as expected.\n\nA generic data structure in Zig is how you replicate a generic class from Java,\nor, a class template from C++. But you may quest yourself: how do we build a\ngeneric data structure in Zig?\n\nThe basic idea is to write a generic function that creates the data structure definition\nfor the specific type we want. In other words, this generic function behaves as a \"factory of data structures\".\nThe generic function outputs the `struct` definition that defines this data structure for a\nspecific data type.\n\nTo create such function, we need to add a comptime argument to this function that receives a data type\nas input. We already learned how to do this at the previous section (@sec-generic-fun).\nI think the best way to demonstrate how to create a generic data structure is to actually write one.\nThis where we go into our next small project in this book. This one is a very small project,\nwhich is to write a generic stack data structure.\n\n\n\n\n## What is a stack? {#sec-what-stack}\n\nA stack data structure is a structure that follows a LIFO (*last in, first out*) principle.\nOnly two operations are normally supported in a stack data structure, which are `push` and `pop`.\nThe `push` operation is used to add new values to the stack, while `pop` is used to remove\nvalues from the stack.\n\nWhen people try to explain how the stack data structure works, the most common analogy\nthat they use is a stack of plates. Imagine that you have a stack of plates,\nfor example, a stack of 10 plates in your table. Each plate represents a value that\nis currently stored in this stack.\n\nWe begin with a stack of 10 different values, or 10 different plates. Now, imagine that you want to\nadd a new plate (or a new value) to this stack, which translates to the `push` operation.\nYou would add this plate (or this value) by just putting the new plate\non the top of the stack. Then, you would increase the stack to 11 plates.\n\nBut how would you remove plates (or remove values) from this stack (a.k.a. the `pop` operation) ?\nTo do that, we would have to remove the plate on the top of the stack, and, as a result, we would\nhave, once again, 10 plates in the stack.\n\nThis demonstrates the LIFO concept, because the first plate in the stack, which is the plate\nin the bottom of the stack, is always the last plate to get out of the stack. Think about it. In order\nto remove this specific plate from the stack, we have to remove all plates in the\nstack. So every operation in the stack, either insertion or deletion, is always made at the top of the stack.\nThe @fig-stack below exposes this logic visually:\n\n![A diagram of a stack structure. Source: Wikipedia, the free encyclopedia.](./../Figures/lifo-stack.svg){#fig-stack}\n\n\n\n## Writing the stack data structure\n\nWe are going to write the stack data structure in two steps. First, we are going\nto implement a stack that can only store `u32` values. Then, after that, we are going\nto extend our implementation to make it generic, so that it works with any data type\nwe want.\n\nFirst, we need to decide how the values will be stored inside the stack. There are multiple\nways to implement the storage behind a stack structure. Some people prefer to use a doubly linked list,\nsome others prefer to use a dynamic array, etc. In this example we are going to use an array behind the hood,\nto store the values in the stack, which is the `items` data member of our `Stack` struct definition.\n\nAlso notice in our `Stack` struct that we have three other data members: `capacity`, `length` and `allocator`.\nThe `capacity` member contains the capacity of the underlying array that stores the values in the stack.\nThe `length` contains the number of values that are currently being stored in the stack.\nAnd the `allocator` contains the allocator object that will be used by the stack structure whenever it\nneeds to allocate more space for the values that are being stored.\n\nWe begin by defining an `init()` method of this struct, which is going to be\nresponsible for instantiating a `Stack` object. Notice that, inside this\n`init()` method, we start by allocating an array with the capacity specified\nin the `capacity` argument.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst Stack = struct {\n items: []u32,\n capacity: usize,\n length: usize,\n allocator: Allocator,\n\n pub fn init(allocator: Allocator, capacity: usize) !Stack {\n var buf = try allocator.alloc(u32, capacity);\n return .{\n .items = buf[0..],\n .capacity = capacity,\n .length = 0,\n .allocator = allocator,\n };\n }\n};\n```\n:::\n\n\n\n\n\n### Implementing the `push` operation\n\nNow that we have written the basic logic to create a new `Stack` object,\nwe can start writing the logic responsible for performing a push operation.\nRemember, a push operation in a stack data structure is the operation\nresponsible for adding a new value to the stack.\n\nSo how can we add a new value to the `Stack` object that we have?\nThe `push()` function exposed below is a possible answer to this question.\nRemember from what we discussed at @sec-what-stack that values are always added to the top of the stack.\nThis means that this `push()` function must always find the element in the underlying array\nthat currently represents the top position of the stack, and then, add the input value there.\n\nFirst, we have an if statement in this function. This if statement is\nchecking whether we need to expand the underlying array to store\nthis new value that we are adding to the stack. In other words, maybe\nthe underlying array does not have enough capacity to store this new\nvalue, and, in this case, we need to expand our array to get the capacity that we need.\n\nSo, if the logical test in this if statement returns true, it means that the array\ndoes not have enough capacity, and we need to expand it before we store this new value.\nSo inside this if statement we are executing the necessary expressions to expand the underlying array.\nNotice that we use the allocator object to allocate a new array that is twice as bigger\nthan the current array (`self.capacity * 2`).\n\nAfter that, we use a different built-in function named `@memcpy()`. This built-in function\nis equivalent to the `memcpy()` function from the C Standard Library[^cmemcpy]. It is used to\ncopy the values from one block of memory to another block of memory. In other words,\nyou can use this function to copy the values from one array into another array.\n\n[^cmemcpy]: \n\nWe are using this `@memcpy()` built-in function to copy the values that are currently stored\nin the underlying array of the stack object (`self.items`) into our new and bigger array that\nwe have allocated (`new_buf`). After we execute this function, the `new_buf` contains a copy\nof the values that are present at `self.items`.\n\nNow that we have secured a copy of our current values in the `new_buf` object, we\ncan now free the memory currently allocated at `self.items`. After that, we just need\nto assign our new and bigger array to `self.items`. This is the sequence\nof steps necessary to expand our array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn push(self: *Stack, val: u32) !void {\n if ((self.length + 1) > self.capacity) {\n var new_buf = try self.allocator.alloc(\n u32, self.capacity * 2\n );\n @memcpy(\n new_buf[0..self.capacity], self.items\n );\n self.allocator.free(self.items);\n self.items = new_buf;\n self.capacity = self.capacity * 2;\n }\n\n self.items[self.length] = val;\n self.length += 1;\n}\n```\n:::\n\n\n\n\nAfter we make sure that we have enough room to store this new value\nthat we are adding to the stack, all we have to do is to assign\nthis value to the top element in this stack, and, increase the\nvalue of the `length` attribute by one. We find the top element\nin the stack by using the `length` attribute.\n\n\n\n### Implementing the `pop` operation\n\nNow we can implement the pop operation of our stack object.\nThis is a much easier operation to implement, and the `pop()` method below summarises\nall the logic that is needed.\n\nWe just have to find the element in the underlying array that currently represents the top\nof the stack, and set this element to \"undefined\", to indicate that\nthis element is \"empty\". After that, we also need to decrease\nthe `length` attribute of the stack by one.\n\nIf the current length of the stack is zero, it means that there is\nno values being stored in the stack currently. So, in this case,\nwe could just return from the function and do nothing really.\nThis is what the if statement inside this function is checking for.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn pop(self: *Stack) void {\n if (self.length == 0) return;\n\n self.items[self.length - 1] = undefined;\n self.length -= 1;\n}\n```\n:::\n\n\n\n\n\n\n### Implementing the `deinit` method\n\nWe have implemented the methods responsible for the two main operations\nassociated with the stack data structure, which is `pop()` and `push()`,\nand we also have implemented the method responsible for instantiating\na new `Stack` object, which is the `init()` method.\n\nBut now, we need to implement also the method responsible for destroying\na `Stack` object. In Zig, this task is commonly associated with the method\nnamed `deinit()`. Most struct objects in Zig have such method, and it\nis commonly nicknamed \"the destructor method\".\n\nIn theory, all we have to do to destroy the `Stack` object is to make\nsure that we free the allocated memory for the underlying array, using\nthe allocator object that is stored inside the `Stack` object.\nThis is what the `deinit()` method below is doing.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn deinit(self: *Stack) void {\n self.allocator.free(self.items);\n}\n```\n:::\n\n\n\n\n\n\n\n## Making it generic\n\nNow that we have implemented the basic skeleton of our stack data structure,\nwe can now focus on discussing how can we make it generic. How can we make\nthis basic skeleton to work not only with `u32` values, but also, with any other\ndata type we want?\nFor example, we might need to create a stack object to store `User` values\nin it. How can we make this possible? The answer lies on the use of generics\nand `comptime`.\n\nAs I described at @sec-generic-struct, the basic idea is to write a generic\nfunction that returns a struct definition as output.\nIn theory, we do not need much to transform our `Stack` struct into a generic\ndata structure. All that we need to do is to transform the underlying array\nof the stack into a generic array.\n\nIn other words, this underlying array needs to be a \"chameleon\". It needs to adapt,\nand transform it into an array of any data type that we want. For example, if we need to create\na stack that will store `u8` values, then, this underlying array needs to be\na `u8` array (i.e. `[]u8`). But if we need to store `User` values instead, then,\nthis array needs to be a `User` array (i.e. `[]User`). Etc.\n\nWe do that by using a generic function. Because a generic function can receive a data type\nas input, and we can pass this data type to the struct definition of our `Stack` object.\nTherefore, we can use the generic function to create a `Stack` object that can store\nthe data type we want. If we want to create a stack structure that stores `User` values,\nwe pass the `User` data type to this generic function, and it will create for us\nthe struct definition that describes a `Stack` object that can store `User` values in it.\n\nLook at the code example below. I have omitted some parts of the `Stack` struct definition\nfor brevity reasons. However, if a specific part of our `Stack` struct is not exposed here\nin this example, then it is because this part did not change from the previous example.\nIt remains the same.\n\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn Stack(comptime T: type) type {\n return struct {\n items: []T,\n capacity: usize,\n length: usize,\n allocator: Allocator,\n const Self = @This();\n\n pub fn init(allocator: Allocator,\n capacity: usize) !Stack(T) {\n var buf = try allocator.alloc(T, capacity);\n return .{\n .items = buf[0..],\n .capacity = capacity,\n .length = 0,\n .allocator = allocator,\n };\n }\n\n pub fn push(self: *Self, val: T) !void {\n // Truncate the rest of the struct\n };\n}\n```\n:::\n\n\n\n\nNotice that we have created a function in this example named `Stack()`. This function\ntakes a type as input, and passes this type to the struct definition of our\n`Stack` object. The data member `items` is now, an array of type `T`, which is the\ndata type that we have provided as input to the function. The function argument\n`val` in the `push()` function is now a value of type `T` too.\n\nWe can just provide a data type to this function, and it will create a definition of a\n`Stack` object that can store values of the data type that we have provided. In the example below, we are creating\nthe definition of a\n`Stack` object that can store `u8` values in it. This definition is stored at the `Stacku8` object.\nThis `Stacku8` object becomes our new struct, it is the struct that we are going to use\nto create our `Stack` object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nconst Stacku8 = Stack(u8);\nvar stack = try Stacku8.init(allocator, 10);\ndefer stack.deinit();\ntry stack.push(1);\ntry stack.push(2);\ntry stack.push(3);\ntry stack.push(4);\ntry stack.push(5);\ntry stack.push(6);\n\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstd.debug.print(\"Stack capacity: {d}\\n\", .{stack.capacity});\n\nstack.pop();\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstack.pop();\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstd.debug.print(\n \"Stack state: {any}\\n\",\n .{stack.items[0..stack.length]}\n);\n```\n:::\n\n\n\n\n```\nStack len: 6\nStack capacity: 10\nStack len: 5\nStack len: 4\nStack state: { 1, 2, 3, 4, 0, 0, 0, 0, 0, 0 }\n```\n\nEvery generic data structure in the Zig Standard Library (`ArrayList`, `HashMap`, `SinlyLinkedList`, etc.)\nis implemented through this logic. They use a generic function to create the struct definition that can work\nwith the data type that you provided as input.\n\n\n\n\n## Conclusion\n\nThe full source code of the stack structure discussed in this chapter is freely available at the official\nrepository of this book. Just checkout the [`stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/stack.zig)[^zig-stack]\nfor the `u32` version of our stack,\nand the [`generic_stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/generic_stack.zig)[^zig-stack2]\nfor the generic version, available inside the `ZigExamples` folder of the repository.\n\n\n[^zig-stack]: \n[^zig-stack2]: \n\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 3 - Building a stack data structure\n\nIn this chapter we are going to implement a stack data structure as our next small project\nin this book. Implementing basic data structures in any language is kind of a\n\"kindergarten task\" (if this term even exist) in computer science (CS), because\nwe normally learn and implement them in the first semesters of CS.\n\nBut this is actually good! Since this should be a very easy task, we don't need much to explain\nwhat a stack is, then, we can concentrate on what is really important here, which is learning\nhow the concept of \"generics\" is implemented in the Zig language, and how one of the key\nfeatures of Zig, which is comptime, works, and use the stack data structure to demonstrate\nthese concepts on the fly.\n\nBut before we get into building the stack data structure, we first need to understand\nwhat the `comptime` keyword does to your code, and after that, we also need to learn about\nhow generics work in Zig.\n\n\n## Understanding `comptime` in Zig {#sec-comptime}\n\nOne of the key features of Zig is `comptime`. This keyword introduces a whole\nnew concept and paradigm, that is tightly connected with the compilation process.\nIn @sec-compile-time we have described the importance and the role that \"compile-time versus runtime\"\nplays into Zig. In that section, we learned that the rules applied to a value/object change\na lot depending on whether this value is known at compile-time, or just at runtime.\n\nThe `comptime` keyword is strongly related to these two spaces in time (compile-time and runtime).\nLet's quickly recap the differences. Compile-time is the period of time when your\nZig source code is being compiled by the `zig` compiler, while the runtime is\nthe period of time when your Zig program is being executed, i.e., when we execute\nthe binary files that were generated by the `zig` compiler.\n\nThere are three ways in which you can apply the `comptime` keyword, which are:\n\n- apply `comptime` on a function argument.\n- apply `comptime` on an object.\n- apply `comptime` on a block of expressions.\n\n\n\n### Applying over a function argument\n\nWhen you apply the `comptime` keyword on a function argument, you are saying to the `zig` compiler\nthat the value assigned to that particular function argument must be known at compile-time.\nWe explained in detail in @sec-compile-time what exactly \"value known at compile-time\" means. So\nif you have any doubts about this idea, refer back to that section.\n\nNow let's think about the consequences of this idea. First of all, we are imposing a limit, or, a requirement\nto that particular function argument. If the programmer accidentally tries to give a value to this\nfunction argument that is not known at compile time, the `zig` compiler will notice this problem, and\nas a consequence, it will raise a compilation error saying that it cannot compile your program. Because\nyou are providing a value that is \"runtime known\" to a function argument that must be \"compile-time known\".\n\nTake a look at this very simple example below, where we define a `twice()` function, that simply\ndoubles the input value named `num`. Notice that we use the `comptime` keyword before the name\nof the function argument. This keyword is marking the function argument `num` as a \"comptime argument\".\n\nThat is a function argument whose value must be compile-time known. This is why the expression\n`twice(5678)` is valid, and no compilation errors are raised. Because the value `5678`\nis compile-time known, so this is the expected behaviour for this function.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\ntest \"test comptime\" {\n _ = twice(5678);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file833f3ad20be9.test.test comptime...OKAll 1 \n tests passed.\n```\n\n\n:::\n:::\n\n\n\n\nBut what if we provide a number that is not compile-time known to this function?\nFor example, we might provide a different input value to this function depending\non the target OS of our compilation process. The code example below demonstrates such case.\n\nBecause the value of the object `n` is determined at runtime, we cannot provide this object\nas input to the `twice()` function. The `zig` compiler will not allow it, because we marked\nthe `num` argument as a \"comptime argument\". That is why the `zig` compiler raises\nthe compile-time error exposed below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\ntest \"test comptime\" {\n var n: u32 = undefined;\n if (builtin.target.os.tag == .windows) {\n n = 1234;\n } else {\n n = 5678;\n }\n _ = twice(n);\n}\n```\n:::\n\n\n\n\n```\nt.zig:12:16: error: runtime-known argument passed to comptime parameter\n```\n\nComptime arguments are frequently used on functions that return some sort\nof generic structure. In fact, `comptime` is the essence (or the basis) to make generics in Zig.\nWe are going to talk more about generics in @sec-generics.\n\nFor now, let's take a look at this code example from @karlseguin_generics. You\ncan see that this `IntArray()` function has one argument named `length`.\nThis argument is marked as comptime, and receives a value of type `usize` as input. So the value given to this argument\nmust be compile-time known.\nWe can also see that this function returns an array of `i64` values as output.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn IntArray(comptime length: usize) type {\n return [length]i64;\n}\n```\n:::\n\n\n\n\nNow, the key component of this function is the `length` argument. This argument\nis used to determine the size of the array that is produced by the function. Let's\nthink about the consequences of that. If the size of the array is dependent on\nthe value assigned to the `length` argument, this means that the data type of the\noutput of the function depends on the value of this `length` argument.\n\nLet this statement sink for a bit in your mind. As I described in @sec-root-file,\nZig is a strongly-typed language, especially on function declarations.\nSo every time we write a function in Zig, we have to annotate the data type of\nthe value returned by the function. But how can we do that, if this data type\ndepends on the value given to the argument of the function?\n\nThink about this for a second. If `length` is equal to 3 for example, then, the\nreturn type of the function is `[3]i64`. But if `length` is equal to 40, then,\nthe return type becomes `[40]i64`. At this point the `zig` compiler would be confused,\nand raise a compilation error, saying something like this:\n\n> Hey! You have annotated that this function should return a `[3]i64` value, but I got a `[40]i64` value instead! This doesn't look right!\n\nSo how can you solve this problem? How do we overcome this barrier? This is when\nthe `type` keyword comes in. This `type` keyword is basically saying to the\n`zig` compiler that this function will return some data type as output, but it doesn't know yet\nwhat exactly data type that is. We will talk more about this in @sec-generics.\n\n\n\n### Applying over an expression\n\nWhen you apply the `comptime` keyword over an expression, then, it is guaranteed that the `zig` compiler will\nexecute this expression at compile-time. If for some reason, this expression cannot be executed at compile-time\n(e.g. for example, maybe this expression depends on a value that is only known at runtime), then, the `zig` compiler\nwill raise a compilation error.\n\nTake this example from the official documentation of Zig [@zigdocs]. We\nare executing the same `fibonacci()` function both at runtime, and, at compile-time.\nThe function is executed by default at runtime, but because we use the `comptime`\nkeyword in the second \"try expression\", this expression is executed at compile-time.\n\nThis might be a bit confusing for some people. Yes! When I say that this expression\nis executed at compile-time, I mean that this expression is compiled and executed\nwhile the `zig` compiler is compiling your Zig source code.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci\" {\n // test fibonacci at run-time\n try expect(fibonacci(7) == 13);\n // test fibonacci at compile-time\n try comptime expect(fibonacci(7) == 13);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file833f119d55a3.test.fibonacci...OKAll 1 test\n ts passed.\n```\n\n\n:::\n:::\n\n\n\n\nA lot of your Zig source code might be potentially executed at compile-time,\nbecause the `zig` compiler can figure out the output of some expressions.\nEspecially if these expressions depend only on compile-time known values.\nWe have talked about this in @sec-compile-time.\n\nBut when you use the `comptime` keyword on an expression, there is no \"it might be executed\nat compile-time\" anymore. With the `comptime` keyword you are ordering the `zig` compiler\nto execute this expression at compile-time. You are imposing this rule, it is guaranteed\nthat the compiler will always execute it at compile-time. Or, at least, the compiler\nwill try to execute it. If the compiler cannot execute the expression for whatever reason,\nthe compiler will raise a compilation error.\n\n\n### Applying over a block\n\nBlocks were described in @sec-blocks. When you apply the `comptime` keyword to a\nblock of expressions, you get essentially the same effect as when you apply this keyword to\na single expression. That is, the entire block of expressions is executed at\ncompile-time by the `zig` compiler.\n\nIn the example below, we mark the block labeled of `blk` as a comptime block,\nand, therefore, the expressions inside this block are executed at compile-time.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci in a block\" {\n const x = comptime blk: {\n const n1 = 5;\n const n2 = 2;\n const n3 = n1 + n2;\n try expect(fibonacci(n3) == 13);\n break :blk n3;\n };\n _ = x;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file833f6ccf145c.test.fibonacci in a block...O\n OKAll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## Introducing Generics {#sec-generics}\n\nFirst of all, what is a generic? Generic is the idea to allow a type\n(`f64`, `u8`, `u32`, `bool`, and also, user-defined types, like the `User` struct\nthat we defined in @sec-structs-and-oop) to be a parameter to methods, classes and\ninterfaces [@geeks_generics]. In other words, a \"generic\" is a class (or a method) that can work\nwith multiple data types.\n\nFor example, in Java, generics are created through the operator `<>`. With this operator,\na Java class is capable of receiving a data type as input, and therefore, the class can fit\nits features according to this input data type.\nAs another example, generics in C++ are supported through the concept of templates.\nClass templates in C++ are generics.\n\nIn Zig, generics are implemented through `comptime`. The `comptime` keyword\nallows us to collect a data type at compile time, and pass this data type as\ninput to a piece of code.\n\n\n### A generic function {#sec-generic-fun}\n\nTake the `max()` function exposed below as a first example.\nThis function is essentially a \"generic function\".\nIn this function, we have a comptime function argument named `T`.\nNotice that this `T` argument has a data type of `type`. Weird right? This `type` keyword is the\n\"father of all types\", or, \"the type of types\" in Zig.\n\nBecause we have used this `type` keyword in the `T` argument, we are telling\nthe `zig` compiler that this `T` argument will receive some data type as input.\nAlso notice the use of the `comptime` keyword in this argument.\nAs I described in @sec-comptime, every time you use this keyword in a function argument,\nthis means that the value of this argument must be known at compile-time.\nThis makes sense, right? Because there is no data type that is not known at compile-time.\n\nThink about this. Every data type that you will ever write is always\nknown at compile-time. Especially because data types are an essential\ninformation for the compiler to actually compile your source code.\nHaving this in mind, makes sense to mark this argument as a comptime argument.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn max(comptime T: type, a: T, b: T) T {\n return if (a > b) a else b;\n}\n```\n:::\n\n\n\n\nAlso notice that the value of the `T` argument is actually used\nto define the data type of the other arguments in the function, `a` and `b`, and also at the\nreturn type annotation of the function.\nThat is, the data type of these arguments (`a` and `b`), and, the return data type of the function itself,\nare determined by the input value given to the `T` argument.\n\nAs a result, we have a generic function that works with different data types.\nFor example, I can provide `u8` values to this `max()` function, and it will work as expected.\nBut if I provide `f64` values instead, it will also work as expected.\nWithout a generic function, I would have to write a different `max()` function\nfor each data type I wanted to use.\nThis generic function provides a very useful shortcut for us.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn max(comptime T: type, a: T, b: T) T {\n return if (a > b) a else b;\n}\ntest \"test max\" {\n const n1 = max(u8, 4, 10);\n std.debug.print(\"Max n1: {d}\\n\", .{n1});\n const n2 = max(f64, 89.24, 64.001);\n std.debug.print(\"Max n2: {d}\\n\", .{n2});\n}\n```\n:::\n\n\n\n\n```\nMax n1: 10\nMax n2: 89.24\n```\n\n\n### A generic data structure {#sec-generic-struct}\n\nEvery data structure that you find in the Zig Standard Library (e.g. `ArrayList`, `HashMap`, etc.)\nis essentially a generic data structure.\nThese data structures are generic in the sense that they work with any data type you want.\nYou just say which is the data type of the values that are going to be stored in this data\nstructure, and they just work as expected.\n\nA generic data structure in Zig is how you replicate a generic class from Java,\nor, a class template from C++. But you may ask yourself: how do we build a\ngeneric data structure in Zig?\n\nThe basic idea is to write a generic function that creates the data structure definition\nfor the specific type we want. In other words, this generic function behaves as a \"factory of data structures\".\nThe generic function outputs the `struct` definition that defines this data structure for a\nspecific data type.\n\nTo create such function, we need to add a comptime argument to this function that receives a data type\nas input. We already learned how to do this in the previous section (@sec-generic-fun).\nI think the best way to demonstrate how to create a generic data structure is to actually write one.\nThis where we go into our next small project in this book. This one is a very small project,\nwhich is to write a generic stack data structure.\n\n\n\n\n## What is a stack? {#sec-what-stack}\n\nA stack data structure is a structure that follows a LIFO (*last in, first out*) principle.\nOnly two operations are normally supported in a stack data structure, which are `push` and `pop`.\nThe `push` operation is used to add new values to the stack, while `pop` is used to remove\nvalues from the stack.\n\nWhen people try to explain how the stack data structure works, the most common analogy\nthat they use is a stack of plates. Imagine that you have a stack of plates,\nfor example, a stack of 10 plates in your table. Each plate represents a value that\nis currently stored in this stack.\n\nWe begin with a stack of 10 different values, or 10 different plates. Now, imagine that you want to\nadd a new plate (or a new value) to this stack, which translates to the `push` operation.\nYou would add this plate (or this value) by just putting the new plate\non the top of the stack. Then, you would increase the stack to 11 plates.\n\nBut how would you remove plates (or remove values) from this stack (a.k.a. the `pop` operation) ?\nTo do that, we would have to remove the plate on the top of the stack, and, as a result, we would\nhave, once again, 10 plates in the stack.\n\nThis demonstrates the LIFO concept, because the first plate in the stack, which is the plate\nin the bottom of the stack, is always the last plate to get out of the stack. Think about it. In order\nto remove this specific plate from the stack, we have to remove all plates in the\nstack. So every operation in the stack, either insertion or deletion, is always made at the top of the stack.\nThe @fig-stack below exposes this logic visually:\n\n![A diagram of a stack structure. Source: Wikipedia, the free encyclopedia.](./../Figures/lifo-stack.svg){#fig-stack}\n\n\n\n## Writing the stack data structure\n\nWe are going to write the stack data structure in two steps. First, we are going\nto implement a stack that can only store `u32` values. Then, after that, we are going\nto extend our implementation to make it generic, so that it works with any data type\nwe want.\n\nFirst, we need to decide how the values will be stored inside the stack. There are multiple\nways to implement the storage behind a stack structure. Some people prefer to use a doubly linked list,\nothers prefer to use a dynamic array, etc. In this example we are going to use an array behind the hood,\nto store the values in the stack, which is the `items` data member of our `Stack` struct definition.\n\nAlso notice in our `Stack` struct that we have three other data members: `capacity`, `length` and `allocator`.\nThe `capacity` member contains the capacity of the underlying array that stores the values in the stack.\nThe `length` contains the number of values that are currently being stored in the stack.\nAnd the `allocator` contains the allocator object that will be used by the stack structure whenever it\nneeds to allocate more space for the values that are being stored.\n\nWe begin by defining an `init()` method of this struct, which is going to be\nresponsible for instantiating a `Stack` object. Notice that, inside this\n`init()` method, we start by allocating an array with the capacity specified\nin the `capacity` argument.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst Stack = struct {\n items: []u32,\n capacity: usize,\n length: usize,\n allocator: Allocator,\n\n pub fn init(allocator: Allocator, capacity: usize) !Stack {\n var buf = try allocator.alloc(u32, capacity);\n return .{\n .items = buf[0..],\n .capacity = capacity,\n .length = 0,\n .allocator = allocator,\n };\n }\n};\n```\n:::\n\n\n\n\n\n### Implementing the `push` operation\n\nNow that we have written the basic logic to create a new `Stack` object,\nwe can start writing the logic responsible for performing a push operation.\nRemember, a push operation in a stack data structure is the operation\nresponsible for adding a new value to the stack.\n\nSo how can we add a new value to the `Stack` object that we have?\nThe `push()` function exposed below is a possible answer to this question.\nRemember from what we discussed in @sec-what-stack that values are always added to the top of the stack.\nThis means that this `push()` function must always find the element in the underlying array\nthat currently represents the top position of the stack, and then, add the input value there.\n\nFirst, we have an if statement in this function. This if statement is\nchecking whether we need to expand the underlying array to store\nthis new value that we are adding to the stack. In other words, maybe\nthe underlying array does not have enough capacity to store this new\nvalue, and, in this case, we need to expand our array to get the capacity that we need.\n\nSo, if the logical test in this if statement returns true, it means that the array\ndoes not have enough capacity, and we need to expand it before we store this new value.\nSo inside this if statement we are executing the necessary expressions to expand the underlying array.\nNotice that we use the allocator object to allocate a new array that is twice as bigger\nthan the current array (`self.capacity * 2`).\n\nAfter that, we use a different built-in function named `@memcpy()`. This built-in function\nis equivalent to the `memcpy()` function from the C Standard Library[^cmemcpy]. It's used to\ncopy the values from one block of memory to another block of memory. In other words,\nyou can use this function to copy the values from one array into another array.\n\n[^cmemcpy]: \n\nWe are using this `@memcpy()` built-in function to copy the values that are currently stored\nin the underlying array of the stack object (`self.items`) into our new and bigger array that\nwe have allocated (`new_buf`). After we execute this function, the `new_buf` contains a copy\nof the values that are present at `self.items`.\n\nNow that we have secured a copy of our current values in the `new_buf` object, we\ncan now free the memory currently allocated at `self.items`. After that, we just need\nto assign our new and bigger array to `self.items`. This is the sequence\nof steps necessary to expand our array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn push(self: *Stack, val: u32) !void {\n if ((self.length + 1) > self.capacity) {\n var new_buf = try self.allocator.alloc(\n u32, self.capacity * 2\n );\n @memcpy(\n new_buf[0..self.capacity], self.items\n );\n self.allocator.free(self.items);\n self.items = new_buf;\n self.capacity = self.capacity * 2;\n }\n\n self.items[self.length] = val;\n self.length += 1;\n}\n```\n:::\n\n\n\n\nAfter we make sure that we have enough room to store this new value\nthat we are adding to the stack, all we have to do is to assign\nthis value to the top element in this stack, and, increase the\nvalue of the `length` attribute by one. We find the top element\nin the stack by using the `length` attribute.\n\n\n\n### Implementing the `pop` operation\n\nNow we can implement the pop operation of our stack object.\nThis is a much easier operation to implement, and the `pop()` method below summarises\nall the logic that is needed.\n\nWe just have to find the element in the underlying array that currently represents the top\nof the stack, and set this element to \"undefined\", to indicate that\nthis element is \"empty\". After that, we also need to decrease\nthe `length` attribute of the stack by one.\n\nIf the current length of the stack is zero, it means that there is\nno values being stored in the stack currently. So, in this case,\nwe could just return from the function and do nothing really.\nThis is what the if statement inside this function is checking for.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn pop(self: *Stack) void {\n if (self.length == 0) return;\n\n self.items[self.length - 1] = undefined;\n self.length -= 1;\n}\n```\n:::\n\n\n\n\n\n\n### Implementing the `deinit` method\n\nWe have implemented the methods responsible for the two main operations\nassociated with the stack data structure, which is `pop()` and `push()`,\nand we also have implemented the method responsible for instantiating\na new `Stack` object, which is the `init()` method.\n\nBut now, we need to implement also the method responsible for destroying\na `Stack` object. In Zig, this task is commonly associated with the method\nnamed `deinit()`. Most struct objects in Zig have such method, and it\nis commonly nicknamed \"the destructor method\".\n\nIn theory, all we have to do to destroy the `Stack` object is to make\nsure that we free the allocated memory for the underlying array, using\nthe allocator object that is stored inside the `Stack` object.\nThis is what the `deinit()` method below is doing.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn deinit(self: *Stack) void {\n self.allocator.free(self.items);\n}\n```\n:::\n\n\n\n\n\n\n\n## Making it generic\n\nNow that we have implemented the basic skeleton of our stack data structure,\nwe can now focus on discussing how we can make it generic. How can we make\nthis basic skeleton to work not only with `u32` values, but also with any other\ndata type we want?\nFor example, we might need to create a stack object to store `User` values\nin it. How can we make this possible? The answer lies in the use of generics\nand `comptime`.\n\nAs I described in @sec-generic-struct, the basic idea is to write a generic\nfunction that returns a struct definition as output.\nIn theory, we do not need much to transform our `Stack` struct into a generic\ndata structure. All that we need to do is to transform the underlying array\nof the stack into a generic array.\n\nIn other words, this underlying array needs to be a \"chameleon\". It needs to adapt,\nand transform it into an array of any data type that we want. For example, if we need to create\na stack that will store `u8` values, then this underlying array needs to be\na `u8` array (i.e., `[]u8`). But if we need to store `User` values instead, then,\nthis array needs to be a `User` array (i.e., `[]User`). Etc.\n\nWe do that by using a generic function. Because a generic function can receive a data type\nas input, and we can pass this data type to the struct definition of our `Stack` object.\nTherefore, we can use the generic function to create a `Stack` object that can store\nthe data type we want. If we want to create a stack structure that stores `User` values,\nwe pass the `User` data type to this generic function, and it will create for us\nthe struct definition that describes a `Stack` object that can store `User` values in it.\n\nLook at the code example below. I have omitted some parts of the `Stack` struct definition\nfor brevity. However, if a specific part of our `Stack` struct is not exposed here\nin this example, then it's because this part did not change from the previous example.\nIt remains the same.\n\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn Stack(comptime T: type) type {\n return struct {\n items: []T,\n capacity: usize,\n length: usize,\n allocator: Allocator,\n const Self = @This();\n\n pub fn init(allocator: Allocator,\n capacity: usize) !Stack(T) {\n var buf = try allocator.alloc(T, capacity);\n return .{\n .items = buf[0..],\n .capacity = capacity,\n .length = 0,\n .allocator = allocator,\n };\n }\n\n pub fn push(self: *Self, val: T) !void {\n // Truncate the rest of the struct\n };\n}\n```\n:::\n\n\n\n\nNotice that we have created a function in this example named `Stack()`. This function\ntakes a type as input, and passes this type to the struct definition of our\n`Stack` object. The data member `items` is now, an array of type `T`, which is the\ndata type that we have provided as input to the function. The function argument\n`val` in the `push()` function is now a value of type `T` too.\n\nWe can just provide a data type to this function, and it will create a definition of a\n`Stack` object that can store values of the data type that we have provided. In the example below, we are creating\nthe definition of a\n`Stack` object that can store `u8` values in it. This definition is stored at the `Stacku8` object.\nThis `Stacku8` object becomes our new struct, that we are going to use\nto create our `Stack` object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nconst Stacku8 = Stack(u8);\nvar stack = try Stacku8.init(allocator, 10);\ndefer stack.deinit();\ntry stack.push(1);\ntry stack.push(2);\ntry stack.push(3);\ntry stack.push(4);\ntry stack.push(5);\ntry stack.push(6);\n\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstd.debug.print(\"Stack capacity: {d}\\n\", .{stack.capacity});\n\nstack.pop();\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstack.pop();\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstd.debug.print(\n \"Stack state: {any}\\n\",\n .{stack.items[0..stack.length]}\n);\n```\n:::\n\n\n\n\n```\nStack len: 6\nStack capacity: 10\nStack len: 5\nStack len: 4\nStack state: { 1, 2, 3, 4, 0, 0, 0, 0, 0, 0 }\n```\n\nEvery generic data structure in the Zig Standard Library (`ArrayList`, `HashMap`, `SinlyLinkedList`, etc.)\nis implemented through this logic. They use a generic function to create the struct definition that can work\nwith the data type that you provided as input.\n\n\n\n\n## Conclusion\n\nThe full source code of the stack structure discussed in this chapter is freely available in the official\nrepository of this book. Just checkout the [`stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/stack.zig)[^zig-stack]\nfor the `u32` version of our stack,\nand the [`generic_stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/generic_stack.zig)[^zig-stack2]\nfor the generic version, available inside the `ZigExamples` folder of the repository.\n\n\n[^zig-stack]: \n[^zig-stack2]: \n", + "supporting": [ + "10-stack-project_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/12-file-op/execute-results/html.json b/_freeze/Chapters/12-file-op/execute-results/html.json index 4bb8d71f..f21b00fa 100644 --- a/_freeze/Chapters/12-file-op/execute-results/html.json +++ b/_freeze/Chapters/12-file-op/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "e7a97064b2b87b0c0d58e245144e133b", + "hash": "1e79228e1613c85b9e688833811e2fda", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n\n# Filesystem and Input/Output (IO) {#sec-filesystem}\n\nIn this chapter we are going to discuss how to use the cross-platform structs and functions\nfrom the Zig Standard Library that can execute filesystem operations. Most of these functions and structs\ncomes from the `std.fs` module.\n\nWe are also going to talk about Input/Output (also known as IO) operations in Zig. Most of\nthese operations are made by using the structs and functions from `std.io` module, which defines\nfile descriptors for the *standard channels* of your system (`stdout` and `stdin`), and also,\nfunctions to create and use I/O streams.\n\n\n## Input/Output basics {#sec-io-basics}\n\nIf you have some experience in a high-level language, you have certainly used\nthese input and output functionalities before in this language. In other words, you certainly have\nbeen in a situation where you needed to sent some output to the user, or, to receive an input\nfrom the user.\n\nFor example, in Python we can receive some input from the user by using the `input()` built-in\nfunction. But we can also print (or \"show\") some output to the user by using the `print()`\nbuilt-in function. So yes, if you have programmed before in Python, you certainly have\nused these functions once before.\n\nBut do you know how these functions relate back to your operating system (OS)? How exactly\nthey are interacting with the resources of your OS to receive or sent some input/output.\nIn essence, these input/output functions from high-level languages are just abstractions\nover the *standard output* and *standard input* channels of your operating system.\n\nThis means that we receive an input, or send some output, through the operating system.\nIt is the OS that makes the bridge between the user and your program. Your program\ndoes not have a direct access to the user. It is the OS that intermediates every\nmessage exchanged between your program and the user.\n\nThe *standard output* and *standard input* channels of your OS are commonly known as the\n`stdout` and `stdin` channels of your OS, respectively. In some contexts, they are also\ncalled the *standard output device* and the *standard input device*. As the name suggests,\nthe *standard output* is the channel through which output flows, while the *standard input*\nis the channel in which input flows.\n\nFurthermore, OS's also normally create a dedicated channel for exchanging error messages, which is known as the\n*standard error* channel, or, the `stderr` channel. This is the channel to which error and warning messages\nare usually sent to. These are the messages that are normally displayed in red-like or orange-like colors\ninto your terminal.\n\nNormally, every OS (e.g. Windows, macOS, Linux, etc.) creates a dedicated and separate set of\n*standard output*, *standard error* and *standard input* channels for every single program (or process) that runs in your computer.\nThis means that every program you write have a dedicated `stdin`, `stderr` and `stdout` that are separate\nfrom the `stdin`, `stderr` and `stdout` of other programs and processes that are currently running.\n\nThis is a behaviour from your OS. This does not come from the programming language that you are using.\nBecause as I sad earlier, input and output in programming languages, especially\nin high-level ones, are just a simple abstraction over the `stdin`, `stderr` and `stdout` from your current OS.\nThat is, your OS is the intermediary between every input/output operation made in your program,\nregardless of the programming language that you are using.\n\n\n### The writer and reader pattern {#sec-writer-reader}\n\nIn Zig, there is a pattern around input/output (IO). I (the author of this book) don't know if there\nis an official name for this pattern. But here, in this book, I will call it the \"writer and reader pattern\".\nIn essence, every IO operation in Zig is made through either a `GenericReader` or a `GenericWriter` object[^gen-zig].\n\nThese two data types come from the `std.io` module of the Zig Standard Library. As their names suggests, a\n`GenericReader` is an object that offers tools to read data from \"something\" (or \"somewhere\"), while a `GenericWriter`\noffers tools to write data into this \"something\". This \"something\" might be different things: like a\nfile that exists in your filesystem; or, it might be a network socket in your system[^sock]; or,\na continuous stream of data, like a standard input device from your system, that might be constantly\nreceiving new data from users, or, as another example, a live chat in a game that is constantly\nreceiving and displaying new messages from the players of the game.\n\n[^gen-zig]: Previously, these objects were known as the `Reader` and `Writer` objects.\n[^sock]: The socket objects that we have created at @sec-create-socket, are examples of network sockets.\n\nSo, if you want to **read** data from something, or somewhere, it means that you need to use a `GenericReader` object.\nBut if you need instead, to **write** data into this \"something\", then, you need to use a `GenericWriter` object instead.\nBoth of these objects are normally created from a file descriptor object. More specifically, through the `writer()` and `reader()`\nmethods of this file descriptor object. If you are not familiar with this type of object, go to the next section.\n\nEvery `GenericWriter` object have methods like `print()`, which allows you to write/send a formatted string\n(i.e. this formatted string is like a `f` string in Python, or, similar to the `printf()` C function)\ninto the \"something\" (file, socket, stream, etc.) that you are using. It also have a `writeAll()` method, which allows you to\nwrite a string, or, an array of bytes into the \"something\".\n\nLikewise, every `GenericReader` object have methods like `readAll()`, which allows you to read the\ndata from the \"something\" (file, socket, stream, etc.) until it fills a particular array (i.e. a \"buffer\") object.\nIn other words, if you provide an array object of 300 `u8` values to `readAll()`, then, this method attempts to read 300 bytes\nof data from the \"something\", and it stores them into the array object that you have provided.\n\nWe also have other methods, like the `readAtLeast()` method, which allows you to specify how\nmany bytes exactly you want to read from the \"something\". In more details, if you give the\nnumber $n$ as input to this method, then, it will attempt to read at least $n$ bytes of data\nfrom the \"something\". The \"something\" might have less than $n$ bytes of data available for you\nto read, so, it is not guaranteed that you will get precisely $n$ bytes as result.\n\nAnother useful method is `readUntilDelimiterOrEof()`. In this method, you specify a \"delimiter character\".\nThe idea is that this function will attempt to read as many bytes of data as possible from the \"something\",\nuntil it encounters the end of the stream, or, it encounters the \"delimiter character\" that you have specified.\n\nIf you don't know exactly how many bytes will come from the \"something\", you may find the `readAllAlloc()` method\nuseful. In essence, you provide an allocator object to this method, so that it can allocate more space if needed.\nAs consequence, this method will try to read all bytes of the \"something\", and, if it runs out of space at some point\nduring the \"reading process\", it uses the allocator object to allocate more space to continue reading the bytes.\nAs result, this method returns a slice to the array object containing all the bytes read.\n\nThis is just a quick description of the methods present in these types of objects. But I recommend you\nto read the official docs, both for\n[`GenericWriter`](https://ziglang.org/documentation/master/std/#std.io.GenericWriter)[^gen-write] and\n[`GenericReader`](https://ziglang.org/documentation/master/std/#std.io.GenericReader)[^gen-read].\nI also think it is a good idea to read the source code of the modules in the Zig Standard Library\nthat defines the methods present in these objects, which are the\n[`Reader.zig`](https://github.com/ziglang/zig/blob/master/lib/std/io/Reader.zig)[^mod-read]\nand [`Writer.zig`]()[^mod-write].\n\n[^gen-read]: .\n[^gen-write]: .\n[^mod-read]: .\n[^mod-write]: .\n\n\n\n### Introducing file descriptors {#sec-file-descriptor}\n\nA \"file descriptor\" object is a core component behind every IO operation that is made in any operating system (OS).\nSuch object is an identifier for a particular input/output (IO) resource from your OS [@wiki_file_descriptor].\nIt describes and identifies this particular resource. An IO resource might be:\n\n- an existing file in your filesystem.\n- an existing network socket.\n- other types of stream channels.\n- a pipeline (or just \"pipe\") in your terminal[^pipes].\n\n[^pipes]: A pipeline is a mechanism for inter-process communication, or, inter-process IO. You could also interpret a pipeline as a \"set of processes that are chained together, through the standard input/output devices of the system\". At Linux for example, a pipeline is created inside a terminal, by connecting two or more terminal commands with the \"pipe\" character (`|`).\n\nFrom the bullet points listed above, we know that although the term \"file\" is present,\na \"file descriptor\" might describe something more than just a file.\nThis concept of a \"file descriptor\" comes from the Portable Operating System Interface (POSIX) API,\nwhich is a set of standards that guide how operating systems across the world should be implemented,\nto maintain compatibility between them.\n\nA file descriptor not only identifies the input/output resource that you are using to receive or send some data,\nbut it also describes where this resource is, and also, which IO mode this resource is currently using.\nFor example, this IO resource might be using only the \"read\" IO mode, which means that this resource\nis open to \"read operations\", while \"write operations\" are not authorized.\nThese IO modes are essentially the modes that you provide to the argument `mode`\nfrom the `fopen()` C function, and also, from the `open()` Python built-in function.\n\nIn C, a \"file descriptor\" is a `FILE` pointer, but, in Zig, a file descriptor is a `File` object.\nThis data type (`File`) is described in the `std.fs` module of the Zig Standard Library.\nWe normally don't create a `File` object directly in our Zig code. Instead, we normally get such object as result when we\nopen an IO resource. In other words, we normally ask our OS to open a particular IO resource for us,\nand, if the OS do open successfully this IO resource, the OS normally handles back to us\na file descriptor to this particular IO resource.\n\nSo you usually get a `File` object by using functions and methods from the Zig Standard Library\nthat asks the OS to open some IO resource, like the `openFile()` method that opens a file in the\nfilesystem. The `net.Stream` object that we have created at @sec-create-socket is also a type of\nfile descriptor object.\n\n\n### The *standard output*\n\nYou already saw across this book, how can we access and use specifically the `stdout` in Zig\nto send some output to the user.\nFor that, we use the `getStdOut()` function from the `std.io` module. This function returns\na file descriptor that describes the `stdout` channel of your current OS. Through this file\ndescriptor object, we can read from or write stuff to the `stdout` of our program.\n\nAlthough we can read stuff recorded into the `stdout` channel, we normally only\nwrite to (or \"print\") stuff into this channel. The reason is very similar to what we discussed at\n@sec-read-http-message, when we were discussing what \"reading from\" versus \"writing to\" the connection\nobject from our small HTTP Server project would mean.\n\nWhen we write stuff into a channel, we are essentially sending data to the other end of this channel.\nIn contrast, when we read stuff from this channel, we are essentially reading the data that was sent\nthrough this channel. Since the `stdout` is a channel to send output to the user, the key verb here\nis **send**. We want to send something to someone, and, as consequence, we want to **write** something\ninto some channel.\n\nThat is why, when we use `getStdOut()`, most of the times, we also use the `writer()` method from the `stdout` file descriptor,\nto get access to a writer object that we can use to write stuff into this `stdout` channel.\nMore specifically, this `writer()` method returns a `GenericWriter` object. One of the\nmain methods of this `GenericWriter` object is the `print()` method that we have used\nbefore to write (or \"print\") a formatted string into the `stdout` channel.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n try stdout.writeAll(\n \"This message was written into stdout.\\n\"\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nThis message was written into stdout.\n```\n\n\n:::\n:::\n\n\n\n\n\n\nThis `GenericWriter` object is like any other generic writer object that you would normally get from a file descriptor object.\nSo, the same methods from a generic writer object that you would use while writing files to the filesystem for example, you could also\nuse them here, from the file descriptor object of `stdout`, and vice-versa.\n\n\n### The *standard input*\n\nYou can access the *standard input* (i.e. `stdin`) in Zig by using the `getStdIn()` function from the `std.io` module.\nLike its brother (`getStdOut()`), this function also returns a file descriptor object that describes the `stdin` channel\nof your OS.\n\nBecause we want to receive some input from the user, the key verb here becomes **receive**, and, as consequence,\nwe usually want to **read** data from the `stdin` channel, instead of writing data into it. So, we normally use\nthe `reader()` method of the file descriptor object returned by `getStdIn()`, to get access to a `GenericReader`\nobject that we can use to read data from `stdin`.\n\nIn the example below, we are creating a small buffer capable of holding 20 characters. Then, we try to read\nthe data from the `stdin` with the `readUntilDelimiterOrEof()` method, and save this data into the `buffer` object.\nAlso notice that we are reading the data from the `stdin` until we hit a new line character (`'\\n'`).\n\nIf you execute this program, you will notice that it stops the execution, ands start to wait indefinitely\nfor some input from the user. In other words, you need to type your name into the terminal, and then, you press Enter to\nsend your name to `stdin`. After you send your name to `stdin`, the program reads this input, and continues with the execution,\nby printing the given name to `stdout`. In the example below, I typed my name (Pedro) into the terminal, and then, pressed Enter.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst stdin = std.io.getStdIn().reader();\npub fn main() !void {\n try stdout.writeAll(\"Type your name\\n\");\n var buffer: [20]u8 = undefined;\n @memset(buffer[0..], 0);\n _ = try stdin.readUntilDelimiterOrEof(buffer[0..], '\\n');\n try stdout.print(\"Your name is: {s}\\n\", .{buffer});\n}\n```\n:::\n\n\n\n\n```\nType your name\nYour name is: Pedro\n\n```\n\n\n### The *standard error*\n\nThe *standard error* (a.k.a. the `stderr`) works exactly the same as `stdout` and `stdin`.\nYou just call the `getStdErr()` function from the `std.io` module, and you get the file descriptor to `stderr`.\nIdeally, you should write only error or warning messages to `stderr`, because this is\nthe purpose of this channel.\n\n\n\n\n\n## Buffered IO\n\nAs we described at @sec-io-basics, input/output (IO) operations are made directly by the operating system.\nIt is the OS that manages the IO resource that you want to use for your IO operations.\nThe consequence of this fact is that IO operations are heavily based on system calls (i.e. calling the operating system directly).\n\nJust to be clear, there is nothing particularly wrong with system calls. We use them all the time on\nany serious codebase written in any low-level programming language. However, system calls are\nalways orders of magnitude slower than many different types of operations.\n\nSo is perfectly fine to use a system call once in a while. But when these system calls are used often,\nyou can clearly notice most of the time the loss of performance in your application. So, the good rule of thumbs\nis to use a system call only when it is needed, and also, only in infrequent situations, to reduce\nthe number of system calls performed to a minimum.\n\n\n### Understanding how buffered IO works\n\nBuffered IO is a strategy to achieve better performance. It is used to reduce the number of system calls made by IO operations, and, as\nconsequence, achieve a much higher performance. At @fig-unbuffered-io and @fig-buffered-io you can find two different diagrams\nwhich presents the difference between read operations performed in an unbuffered IO environment versus a buffered IO environment.\n\nTo give a better context to these diagrams, let's suppose that we have a text file that contains the famous Lorem ipsum text[^lorem]\nin our filesystem. Let's also suppose that these diagrams at @fig-unbuffered-io and @fig-buffered-io\nare showing the read operations that we are performing to read the Lorem ipsum text from this text file.\nThe first thing you will notice when looking at these diagrams, is that in an unbuffered environment\nthe read operations leads to many system calls.\nMore precisely, in the diagram exposed at @fig-unbuffered-io we get one system call per each byte that we read from the text file.\nOn the other hand, at @fig-buffered-io we have only one system call at the very beginning.\n\nWhen we use a buffered IO system, at the first read operation we perform, instead of sending one single byte directly\nto our program, the OS first sends a chunk of bytes from the file to a buffer object (i.e. an array).\nThis chunk of bytes are cached/stored inside this buffer object.\n\nTherefore, from now on, for every new read operation that you perform, instead of making a new system call to ask\nfor the next byte in the file to the OS, this read operation is redirected to the buffer object, that have\nthis next byte already cached and ready to go.\n\n\n[^lorem]: .\n\n\n![Unbuffered IO](./../Figures/unbuffered-io.png){#fig-unbuffered-io width=60%}\n\n![Buffered IO](./../Figures/buffered-io.png){#fig-buffered-io}\n\n\n\nThis is the basic logic behind buffered IO systems. The size of the buffer object depends on multiple factors. But it is usually\nequal to the size of a full page of memory (4096 bytes). If we follow this logic, then, the OS reads the first 4096 bytes\nof the file and caches it into the buffer object. As long as your program does not consume all of these 4096 bytes from the buffer,\nyou will not create new system calls.\n\nHowever, as soon as you consume all of these 4096 bytes from the buffer, it means that there is no bytes left in the buffer.\nIn this situation, a new system call is made to ask the OS to send the next 4096 bytes in the file, and once again,\nthese bytes are cached into the buffer object, and the cycle starts once again.\n\n\n### Buffered IO across different languages\n\nIO operations made through a `FILE` pointer in C are buffered\nby default, so, at least in C, you don't need to worry about this subject. But in contrast, IO operations in both Rust and Zig are not\nbuffered depending on which functions from the standard libraries that you are using.\n\nFor example, in Rust, buffered IO is implemented through the `BufReader` and `BufWriter` structs, while in Zig, it is implemented\nthrough the `BufferedReader` and `BufferedWriter` structs.\nSo any IO operation that you perform through the `GenericWriter` and `GenericReader` objects\nthat I presented at @sec-writer-reader are not buffered, which means that these objects\nmight create a lot of system calls depending on the situation.\n\n\n### Using buffered IO in Zig\n\nUsing buffered IO in Zig is actually very easy. All you have to do is to just\ngive the `GenericWriter` object to the `bufferedWriter()` function, or, to give the `GenericReader`\nobject to the `bufferedReader()` function. These functions come from the `std.io` module,\nand they will construct the `BufferedWriter` or `BufferedReader` object for you.\n\nAfter you create this new `BufferedWriter` or `BufferedReader` object, you can call the `writer()`\nor `reader()` method of this new object, to get access to a new (and buffered) generic reader or\ngeneric writer.\n\nLet's describe the process once again. Every time that you have a file descriptor object, you first get the generic writer or generic reader\nobject from it, by calling the `writer()` or `reader()` methods of this file descriptor object.\nThen, you provide this generic writer or generic reader to the `bufferedWriter()` or `bufferedReader()`\nfunction, which creates a new `BufferedWriter` or `BufferedReader` object. Then, you call\nthe `writer()` or `reader()` methods of this buffered writer or buffered reader object,\nwhich gives you access to a generic writer or a generic reader object that is buffered.\n\nTake this program as an example. This program is demonstrating the process exposed at @fig-buffered-io.\nWe are simply opening a text file that contains the Lorem ipsum text, and then, we create a buffered IO reader object\nat `bufreader`, and we use this `bufreader` object to read the contents of this file into a buffer object, then,\nwe end the program by printing this buffer to `stdout`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar file = try std.fs.cwd().openFile(\n \"ZigExamples/file-io/lorem.txt\", .{}\n);\ndefer file.close();\nvar buffered = std.io.bufferedReader(file.reader());\nvar bufreader = buffered.reader();\n\nvar buffer: [1000]u8 = undefined;\n@memset(buffer[0..], 0);\n\n_ = try bufreader.readUntilDelimiterOrEof(\n buffer[0..], '\\n'\n);\ntry stdout.print(\"{s}\\n\", .{buffer});\n```\n:::\n\n\n\n\n```\nLorem ipsum dolor sit amet, consectetur\nadipiscing elit. Sed tincidunt erat sed nulla ornare, nec\naliquet ex laoreet. Ut nec rhoncus nunc. Integer magna metus,\nultrices eleifend porttitor ut, finibus ut tortor. Maecenas\nsapien justo, finibus tincidunt dictum ac, semper et lectus.\nVivamus molestie egestas orci ac viverra. Pellentesque nec\narcu facilisis, euismod eros eu, sodales nisl. Ut egestas\nsagittis arcu, in accumsan sapien rhoncus sit amet. Aenean\nneque lectus, imperdiet ac lobortis a, ullamcorper sed massa.\nNullam porttitor porttitor erat nec dapibus. Ut vel dui nec\nnulla vulputate molestie eget non nunc. Ut commodo luctus ipsum,\nin finibus libero feugiat eget. Etiam vel ante at urna tincidunt\nposuere sit amet ut felis. Maecenas finibus suscipit tristique.\nDonec viverra non sapien id suscipit.\n```\n\nDespite being a buffered IO reader, this `bufreader` object is similar to any other `GenericReader` object,\nand have the exact same methods. So, although these two types of objects perform very different IO operations,\nthey have the same interface, so you, the programmer, can interchangeably use them\nwithout the need to change anything in your source code.\nSo a buffered IO reader or a buffered IO writer objects have the same methods than its generic and unbuffered brothers,\ni.e. the generic reader and generic writer objects that I presented at @sec-writer-reader.\n\n::: {.callout-tip}\nIn general, you should always use a buffered IO reader or a buffered IO writer object to perform\nIO operations in Zig. Because they deliver better performance to your IO operations.\n:::\n\n\n## Filesystem basics\n\nNow that we have discussed the basics around Input/Output operations in Zig, we need to\ntalk about the basics around filesystems, which is another core part of any operating system.\nAlso, filesystems are related to input/output, because the files that we store and create in our\ncomputer are considered an IO resource, as we described at @sec-file-descriptor.\n\n\n### The concept of current working directory (CWD)\n\nThe working directory is the folder on your computer where you are currently rooted at.\nIn other words, it is the folder that your program is currently looking at.\nTherefore, whenever you are executing a program, this program is always working with\na specific folder on your computer. It is always in this folder that the program will initially\nlook for the files you require, and it is also in this folder that the program\nwill initially save all the files you ask it to save.\n\nThe working directory is determined by the folder from which you invoke your program\nin the terminal. In other words, if you are in the terminal of your OS, and you\nexecute a binary file (i.e. a program) from this terminal, the folder to which your terminal\nis pointing at is the current working directory of your program that is being executed.\n\nAt @fig-cwd we have an example of me executing a program from the terminal. We are executing\nthe program outputted by the `zig` compiler by compiling the Zig module named `hello.zig`.\nThe CWD in this case is the `zig-book` folder. In other words, while the `hello.zig` program\nis executing, it will be looking at the `zig-book` folder, and any file operation that we perform\ninside this program, will be using this `zig-book` folder as the \"starting point\", or, as the \"central focus\".\n\n![Executing a program from the terminal](./../Figures/cwd.png){#fig-cwd}\n\nJust because we are rooted inside a particular folder (in the case of @fig-cwd, the `zig-book` folder) of our computer,\nit doesn't mean that we cannot access or write resources in other locations of our computer.\nThe current working directory (CWD) mechanism just defines where your program will look first\nfor the files you ask for. This does not prevent you from accessing files that are located\nelsewhere on your computer. However, to access any file that is in a folder other than your\ncurrent working directory, you must provide a path to that file or folder.\n\n\n### The concept of paths\n\nA path is essentially a location. It points to a location in your filesystem. We use\npaths to describe the location of files and folders in our computer.\nOne important aspect about paths is that they are always written inside strings,\ni.e. they are always provided as text values.\n\nThere are two types of paths that you can provide to any program in any OS: a relative path, or an absolute path.\nAbsolute paths are paths that start at the root of your filesystem, and go all the way to the file name or the specific folder\nthat you are referring to. This type of path is called absolute, because it points to an unique and absolute location on your computer.\nThat is, there is no other existing location on your computer that corresponds to this path. It is an unique identifier.\n\nIn Windows, an absolute path is a path that starts with a hard disk identifier (e.g. `C:/Users/pedro`).\nOn the other hand, absolute paths in Linux and macOS, are paths that start with a forward slash character (e.g. `/usr/local/bin`).\nNotice that a path is composed by \"segments\". Each segment is connected to each other by a slash character (`\\` or `/`).\nOn Windows, the backward slash (`\\`) is normally used to connect the path segments. While on Linux and macOS, the forward\nslash (`/`) is the character used to connect path segments.\n\nA relative path is a path that start at the CWD. In other words, a relative path is\n\"relative to the CWD\". The path used to access the `hello.zig` file at @fig-cwd is an example of a relative path. This path\nis reproduced below. This path begins at the CWD, which in the context of @fig-cwd, is the `zig-book` folder,\nthen, it goes to the `ZigExamples` folder, then, into `zig-basics`, then, to the `hello.zig` file.\n\n```\nZigExamples/zig-basics/hello_world.zig\n```\n\n\n### Path wildcards\n\nWhen providing paths, especially relative paths, you have the option of using a *wildcard*.\nThere are two commonly used *wildcards* in paths, which are \"one period\" (.) and \"two periods\" (..).\nIn other words, these two specific characters have special meanings when used in paths,\nand can be used on any operating system (Mac, Windows, Linux, etc.). That is, they\nare \"cross platform\".\n\nThe \"one period\" represents an alias for the current directory.\nThis means that the relative paths `\"./Course/Data/covid.csv\"` and `\"Course/Data/covid.csv\"` are equivalent.\nOn the other hand, the \"two periods\" refers to the previous directory.\nFor example, the path `\"Course/..\"` is equivalent to the path `\".\"`, that is, the current working directory.\n\nTherefore, the path `\"Course/..\"` refers to the folder before the `Course` folder.\nAs another example, the path `\"src/writexml/../xml.cpp\"` refers to the file `xml.cpp`\nthat is inside the folder before the `writexml` folder, which in this example is the `src` folder.\nTherefore, this path is equivalent to `\"src/xml.cpp\"`.\n\n\n\n\n## The CWD handler\n\nIn Zig, filesystem operations are usually made through a directory handler object.\nA directory handler in Zig is an object of type `Dir`, which is an object that describes\na particular folder in the filesystem of our computer.\nYou normally create a `Dir` object, by calling the `std.fs.cwd()` function.\nThis function returns a `Dir` object that points to (or, that describes) the\ncurrent working directory (CWD).\n\nThrough this `Dir` object, you can create new files, or modify, or read existing ones that are\ninside your CWD. In other words, a `Dir` object is the main entrypoint in Zig to perform\nmultiple types of filesystem operations.\nIn the example below, we are creating this `Dir` object, and storing it\ninside the `cwd` object. Although we are not using this object at this code example,\nwe are going to use it a lot over the next examples.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\n_ = cwd;\n```\n:::\n\n\n\n\n\n\n\n\n\n\n\n## File operations\n\n### Creating files {#sec-creating-files}\n\nWe create new files by using the `createFile()` method from the `Dir` object.\nJust provide the name of the file that you want to create, and this function will\ndo the necessary steps to create such file. You can also provide a relative path to this function,\nand it will create the file by following this path, which is relative to the CWD.\n\nThis function might return an error, so, you should use `try`, `catch`, or any of the other methods presented\nat @sec-error-handling to handle the possible error. But if everything goes well,\nthis `createFile()` method returns a file descriptor object (i.e. a `File` object) as result,\nthrough which you can add content to the file with the IO operations that I presented before.\n\nTake this code example below. In this example, we are creating a new text file\nnamed `foo.txt`. If the function `createFile()` succeeds, the object named `file` will contain a file descriptor\nobject, which we can use to write (or add) new content to the file, like we do in this example, by using\na buffered writer object to write a new line of text to the file.\n\nNow, a quick note, when we create a file descriptor object in C, by using a C function like `fopen()`, we must always close the file\nat the end of our program, or, as soon as we complete all operations that we wanted to perform\non the file. In Zig, this is no different. So everytime we create a new file, this file remains\n\"open\", waiting for some operation to be performed. As soon as we are done with it, we always have\nto close this file, to free the resources associated with it.\nIn Zig, we do this by calling the method `close()` from the file descriptor object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.createFile(\"foo.txt\", .{});\n// Don't forget to close the file at the end.\ndefer file.close();\n// Do things with the file ...\nvar fw = file.writer();\n_ = try fw.writeAll(\n \"Writing this line to the file\\n\"\n);\n```\n:::\n\n\n\n\n\nSo, in this example we not only have created a file into the filesystem,\nbut we also wrote some data into this file, using the file descriptor object\nreturned by `createFile()`. If the file that you are trying to create\nalready exists in your filesystem, this `createFile()` call will\noverwrite the contents of the file, or, in other words, it will\nin erase all the contents of the existing file.\n\nIf you don't want this to happen, meaning, that you don't want to overwrite\nthe contents of the existing file, but you want to write data to this file anyway\n(i.e. you want to append data to the file), you should use the `openFile()`\nmethod from the `Dir` object.\n\nAnother important aspect about `createFile()` is that this method creates a file\nthat is not open to read operations by default. It means that you cannot read this file.\nYou are not allowed to.\nSo for example, you might want to write some stuff into this file at the beginning of the execution\nof your program. Then, at a future point in your program you might need to read what you\nwrote in this file. If you try to read data from this file, you will likely\nget a `NotOpenForReading` error as result.\n\n\nBut how can you overcome this barrier? How can you create a file that is open\nto read operations? All you have to do, is to set the `read` flag to true\nin the second argument of `createFile()`. When you set this flag to true,\nthen the file get's create with \"read permissions\", and, as consequence,\na program like this one below becomes valid:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.createFile(\n \"foo.txt\",\n .{ .read = true }\n);\ndefer file.close();\n\nvar fw = file.writer();\n_ = try fw.writeAll(\"We are going to read this line\\n\");\n\nvar buffer: [300]u8 = undefined;\n@memset(buffer[0..], 0);\ntry file.seekTo(0);\nvar fr = file.reader();\n_ = try fr.readAll(buffer[0..]);\ntry stdout.print(\"{s}\\n\", .{buffer});\n```\n:::\n\n\n\n\n\n```\nWe are going to read this line\n```\n\n\nIf you are not familiar with position indicators, you might not recognize the method\n`seekTo()`. If that is your case, do not worry,\nwe are going to talk more about this method at @sec-indicators. But essentially\nthis method is moving the position indicator back to the beginning of the file,\nso that we can read the contents of the file from the beginning.\n\n\n### Opening files and appending data to it\n\nOpening files is easy. Just use the `openFile()` method instead of `createFile()`.\nIn the first argument of `openFile()` you provide the path to the file that\nyou want to open. Then, on the second argument you provide the flags (or, the options)\nthat dictates how the file is opened.\n\nYou can see the full list of options for `openFile()` by visiting the documentation for\n[`OpenFlags`](https://ziglang.org/documentation/master/std/#std.fs.File.OpenFlags)[^oflags].\nBut the main flag that you will most certainly use is the `mode` flag.\nThis flag specifies the IO mode that the file will be using when it get's opened.\nThere are three IO modes, or, three values that you can provide to this flag, which are:\n\n- `read_only`, allows only read operations on the file. All write operations are blocked.\n- `write_only`, allows only write operations on the file. All read operations are blocked. \n- `read_write`, allows both write and read operations on the file.\n\n[^oflags]: \n\nThese modes are similar to the modes that you provide to the `mode` argument of the\n`open()` Python built-in function[^py-open], or, the `mode` argument of the\n`fopen()` C function[^c-open].\nIn the code example below, we are opening the `foo.txt` text file with a `write_only` mode,\nand appending a new line of text to the end of the file. We use `seekFromEnd()` this time\nto guarantee that we are going to append the text to the end of the file. Once again, methods\nsuch as `seekFromEnd()` are described in more depth at @sec-indicators.\n\n[^py-open]: \n[^c-open]: \n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.openFile(\n \"foo.txt\", .{ .mode = .write_only }\n);\ndefer file.close();\ntry file.seekFromEnd(0);\nvar fw = file.writer();\n_ = try fw.writeAll(\"Some random text to write\\n\");\n```\n:::\n\n\n\n\n\n### Deleting files\n\nSometimes, we just need to delete/remove the files that we have.\nTo do that, we use the `deleteFile()` method. You just provide the path of the\nfile that you want to delete, and this method will try to delete the file located\nat this path.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.deleteFile(\"foo.txt\");\n```\n:::\n\n\n\n\n### Copying files\n\nTo copy existing files, we use the `copyFile()` method. The first argument in this method\nis the path to the file that you want to copy. The second argument is a `Dir` object, i.e. a directory handler,\nmore specifically, a `Dir` object that points to the folder in your computer where you want to\ncopy the file to. The third argument is the new path of the file, or, in other words, the new location\nof the file. The fourth argument is the options (or flags) to be used in the copy operation.\n\nThe `Dir` object that you provide as input to this method will be used to copy the file to\nthe new location. You may create this `Dir` object before calling the `copyFile()` method.\nMaybe you are planning to copy the file to a completely different location in your computer,\nso it might be worth to create a directory handler to that location. But if you are copying the\nfile to a subfolder of your CWD, then, you can just simply pass the CWD handler to this argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.copyFile(\n \"foo.txt\",\n cwd,\n \"ZigExamples/file-io/foo.txt\",\n .{}\n);\n```\n:::\n\n\n\n\n\n### Read the docs!\n\nThere are some other useful methods for file operations available at `Dir` objects,\nsuch as the `writeFile()` method, but I recommend you to read the docs for the\n[`Dir` type](https://ziglang.org/documentation/master/std/#std.fs.Dir)[^zig-dir]\nto explore the other available methods, since I already talked too much about them.\n\n\n[^zig-dir]: \n\n\n\n\n## Position indicators {#sec-indicators}\n\nA position indicator is like a type of cursor, or, an index. This \"index\" identifies the current\nlocation in the file (or, in the data stream) that the file descriptor object that you have\nis currently looking at.\nWhen you create a file descriptor, the position indicator starts at the beginning of the file,\nor, at the beginning of the stream. When you read from or write into the file (or socket, or data stream, etc.)\ndescribed by this file descriptor object, you end up moving the position indicator.\n\nIn other words, any IO operation have a common side effect, which is to move the position indicator.\nFor example, suppose that we have a file of 300 bytes total in size. If you\nread 100 bytes from the file, then, the position indicator moves 100 bytes forward. If you try\nto write 50 bytes into this same file, these 50 bytes will be written from the current\nposition indicated by the position indicator. Since the indicator is at a 100 bytes forward from\nthe beginning of the file, these 50 bytes would be written in the middle of the file.\n\nThis is why we have used the `seekTo()` method at the last code example presented at @sec-creating-files.\nWe have used this method to move the position indicator back to the beginning of the file, which\nwould make sure that we would write the text that we wanted to write from the beginning of the file,\ninstead of writing it from the middle of the file. Because before the write operation, we had\nperformed a read operation, which means that the position indicator was moved in this read operation.\n\nThe position indicators of a file descriptor object can be changed (or altered) by using the\n\"seek\" methods from this file descriptor, which are: `seekTo()`, `seekFromEnd()` and `seekBy()`.\nThese methods have the same effect, or, the same responsibility that the\n[`fseek()`](https://en.cppreference.com/w/c/io/fseek)[^c-fseek] C function.\n\n[^c-fseek]: \n\n\nConsidering that `offset` refers to the index that you provide as input to these \"seek\" methods,\nthe bullet points below summarises what is the effect of each of these methods.\nAs a quick note, in the case of `seekFromEnd()` and `seekBy()`, the `offset` provided can be either a\npositive or a negative index.\n\n- `seekTo()` will move the position indicator to the location that is `offset` bytes from the beginning of the file.\n- `seekFromEnd()` will move the position indicator to the location that is `offset` bytes from the end of the file.\n- `seekBy()` will move the position indicator to the location that is `offset` bytes from the current position in the file.\n\n\n\n\n\n\n\n## Directory operations\n\n### Iterating through the files in a directory\n\nOne of the most classic tasks related to filesystem is to be able\nto iterate through the existing files in a directory. To iterate over the\nfiles in a directory, we need to create an iterator object.\n\nYou can produce such iterator object by using either the `iterate()` or `walk()` methods\nof a `Dir` object. Both methods return an iterator object as output, which you can advance by using the\n`next()` method. The difference between these methods, is that `iterate()` returns a non-recursive iterator,\nwhile `walk()` does. It means that the iterator returned by `walk()` will not only iterate through\nthe files available in the current directory, but also, through the files from any subdirectory found\ninside the current directory.\n\nIn the example below, we are displaying the names of the files stored inside the\ndirectory `ZigExamples/file-io`. Notice that we had to open this directory through\nthe `openDir()` function. Also notice that we provided the flag `iterate` in the\nsecond argument of `openDir()`. This flag is important, because without this flag,\nwe would not be allowed to iterate through the files in this directory.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst dir = try cwd.openDir(\n \"ZigExamples/file-io/\",\n .{ .iterate = true }\n);\nvar it = dir.iterate();\nwhile (try it.next()) |entry| {\n try stdout.print(\n \"File name: {s}\\n\",\n .{entry.name}\n );\n}\n```\n:::\n\n\n\n\n```\nFile name: create_file_and_write_toit.zig\nFile name: create_file.zig\nFile name: lorem.txt\nFile name: iterate.zig\nFile name: delete_file.zig\nFile name: append_to_file.zig\nFile name: user_input.zig\nFile name: foo.txt\nFile name: create_file_and_read.zig\nFile name: buff_io.zig\nFile name: copy_file.zig\n```\n\n\n### Creating new directories\n\nThere are two methods that are important when it comes to\ncreating directories, which are `makeDir()` and `makePath()`.\nThe difference between these two methods is that `makeDir()` can\nonly create one single directory in the current directory in each call,\nwhile `makePath()` is capable of recursively create subdirectories in the same call.\n\n\nThis is why the name of this method is \"make path\". It will create as many\nsubdirectories as necessary to create the path that you provided as input.\nSo, if you provide the path `\"sub1/sub2/sub3\"` as input to this method,\nit will create three different subdirectories, `sub1`, `sub2` and `sub3`,\nwithin the same function call. In contrast, if you provided such path\nas input to `makeDir()`, you would likely get an error as result, since\nthis method can only create a single subdirectory.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.makeDir(\"src\");\ntry cwd.makePath(\"src/decoders/jpg/\");\n```\n:::\n\n\n\n\n### Deleting directories\n\nTo delete a directory, just provide the path to the directory that you want to delete\nas input to the `deleteDir()` method from a `Dir` object. In the example below,\nwe are deleting the `src` directory that we have just created in the previous example.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.deleteDir(\"src\");\n```\n:::\n\n\n\n\n\n## Conclusion\n\nIn this chapter, I have described how to perform in Zig the most common filesystem and IO operations.\nBut you might feel the lack of some other, less common, operation in this chapter, such as: how to rename files,\nor how to open a directory, or how to create symbolic links, or how to use `access()` to test if a particular\npath exists in your computer. But for all of these less common tasks, I recommend you to read\nthe documentation of the [`Dir` type](https://ziglang.org/documentation/master/std/#std.fs.Dir)[^zig-dir]\n, since you can find a good description of these cases there.\n\n\n\n\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n\n# Filesystem and Input/Output (IO) {#sec-filesystem}\n\nIn this chapter we are going to discuss how to use the cross-platform structs and functions\nfrom the Zig Standard Library that can execute filesystem operations. Most of these functions and structs\ncomes from the `std.fs` module.\n\nWe are also going to talk about Input/Output (also known as IO) operations in Zig. Most of\nthese operations are made by using the structs and functions from `std.io` module, which defines\nfile descriptors for the *standard channels* of your system (`stdout` and `stdin`), and also,\nfunctions to create and use I/O streams.\n\n\n## Input/Output basics {#sec-io-basics}\n\nIf you have some experience in a high-level language, you have certainly used\nthese input and output functionalities before in this language. In other words, you certainly have\nbeen in a situation where you needed to sent some output to the user, or, to receive an input\nfrom the user.\n\nFor example, in Python we can receive some input from the user by using the `input()` built-in\nfunction. But we can also print (or \"show\") some output to the user by using the `print()`\nbuilt-in function. So yes, if you have programmed before in Python, you certainly have\nused these functions once before.\n\nBut do you know how these functions relate back to your operating system (OS)? How exactly\nthey are interacting with the resources of your OS to receive or sent some input/output.\nIn essence, these input/output functions from high-level languages are just abstractions\nover the *standard output* and *standard input* channels of your operating system.\n\nThis means that we receive an input, or send some output, through the operating system.\nIt's the OS that makes the bridge between the user and your program. Your program\ndoes not have a direct access to the user. It's the OS that intermediates every\nmessage exchanged between your program and the user.\n\nThe *standard output* and *standard input* channels of your OS are commonly known as the\n`stdout` and `stdin` channels of your OS, respectively. In some contexts, they are also\ncalled the *standard output device* and the *standard input device*. As the name suggests,\nthe *standard output* is the channel through which output flows, while the *standard input*\nis the channel in which input flows.\n\nFurthermore, OS's also normally create a dedicated channel for exchanging error messages, which is known as the\n*standard error* channel, or, the `stderr` channel. This is the channel to which error and warning messages\nare usually sent to. These are the messages that are normally displayed in red-like or orange-like colors\ninto your terminal.\n\nNormally, every OS (e.g. Windows, macOS, Linux, etc.) creates a dedicated and separate set of\n*standard output*, *standard error* and *standard input* channels for every single program (or process) that runs in your computer.\nThis means that every program you write have a dedicated `stdin`, `stderr` and `stdout` that are separate\nfrom the `stdin`, `stderr` and `stdout` of other programs and processes that are currently running.\n\nThis is a behaviour from your OS. This does not come from the programming language that you are using.\nBecause as I sad earlier, input and output in programming languages, especially\nin high-level ones, are just a simple abstraction over the `stdin`, `stderr` and `stdout` from your current OS.\nThat is, your OS is the intermediary between every input/output operation made in your program,\nregardless of the programming language that you are using.\n\n\n### The writer and reader pattern {#sec-writer-reader}\n\nIn Zig, there is a pattern around input/output (IO). I (the author of this book) don't know if there\nis an official name for this pattern. But here, in this book, I will call it the \"writer and reader pattern\".\nIn essence, every IO operation in Zig is made through either a `GenericReader` or a `GenericWriter` object[^gen-zig].\n\nThese two data types come from the `std.io` module of the Zig Standard Library. As their names suggests, a\n`GenericReader` is an object that offers tools to read data from \"something\" (or \"somewhere\"), while a `GenericWriter`\noffers tools to write data into this \"something\". This \"something\" might be different things: like a\nfile that exists in your filesystem; or, it might be a network socket in your system[^sock]; or,\na continuous stream of data, like a standard input device from your system, that might be constantly\nreceiving new data from users, or, as another example, a live chat in a game that is constantly\nreceiving and displaying new messages from the players of the game.\n\n[^gen-zig]: Previously, these objects were known as the `Reader` and `Writer` objects.\n[^sock]: The socket objects that we have created in @sec-create-socket, are examples of network sockets.\n\nSo, if you want to **read** data from something, or somewhere, it means that you need to use a `GenericReader` object.\nBut if you need instead, to **write** data into this \"something\", then, you need to use a `GenericWriter` object instead.\nBoth of these objects are normally created from a file descriptor object. More specifically, through the `writer()` and `reader()`\nmethods of this file descriptor object. If you are not familiar with this type of object, go to the next section.\n\nEvery `GenericWriter` object have methods like `print()`, which allows you to write/send a formatted string\n(i.e., this formatted string is like a `f` string in Python, or, similar to the `printf()` C function)\ninto the \"something\" (file, socket, stream, etc.) that you are using. It also have a `writeAll()` method, which allows you to\nwrite a string, or, an array of bytes into the \"something\".\n\nLikewise, every `GenericReader` object have methods like `readAll()`, which allows you to read the\ndata from the \"something\" (file, socket, stream, etc.) until it fills a particular array (i.e., a \"buffer\") object.\nIn other words, if you provide an array object of 300 `u8` values to `readAll()`, then, this method attempts to read 300 bytes\nof data from the \"something\", and it stores them into the array object that you have provided.\n\nWe also have other methods, like the `readAtLeast()` method, which allows you to specify how\nmany bytes exactly you want to read from the \"something\". In more details, if you give the\nnumber $n$ as input to this method, then, it will attempt to read at least $n$ bytes of data\nfrom the \"something\". The \"something\" might have less than $n$ bytes of data available for you\nto read, so, it's not guaranteed that you will get precisely $n$ bytes as result.\n\nAnother useful method is `readUntilDelimiterOrEof()`. In this method, you specify a \"delimiter character\".\nThe idea is that this function will attempt to read as many bytes of data as possible from the \"something\",\nuntil it encounters the end of the stream, or, it encounters the \"delimiter character\" that you have specified.\n\nIf you don't know exactly how many bytes will come from the \"something\", you may find the `readAllAlloc()` method\nuseful. In essence, you provide an allocator object to this method, so that it can allocate more space if needed.\nAs consequence, this method will try to read all bytes of the \"something\", and, if it runs out of space at some point\nduring the \"reading process\", it uses the allocator object to allocate more space to continue reading the bytes.\nAs result, this method returns a slice to the array object containing all the bytes read.\n\nThis is just a quick description of the methods present in these types of objects. But I recommend you\nto read the official docs, both for\n[`GenericWriter`](https://ziglang.org/documentation/master/std/#std.io.GenericWriter)[^gen-write] and\n[`GenericReader`](https://ziglang.org/documentation/master/std/#std.io.GenericReader)[^gen-read].\nI also think it's a good idea to read the source code of the modules in the Zig Standard Library\nthat defines the methods present in these objects, which are the\n[`Reader.zig`](https://github.com/ziglang/zig/blob/master/lib/std/io/Reader.zig)[^mod-read]\nand [`Writer.zig`]()[^mod-write].\n\n[^gen-read]: .\n[^gen-write]: .\n[^mod-read]: .\n[^mod-write]: .\n\n\n\n### Introducing file descriptors {#sec-file-descriptor}\n\nA \"file descriptor\" object is a core component behind every IO operation that is made in any operating system (OS).\nSuch object is an identifier for a particular input/output (IO) resource from your OS [@wiki_file_descriptor].\nIt describes and identifies this particular resource. An IO resource might be:\n\n- an existing file in your filesystem.\n- an existing network socket.\n- other types of stream channels.\n- a pipeline (or just \"pipe\") in your terminal[^pipes].\n\n[^pipes]: A pipeline is a mechanism for inter-process communication, or, inter-process IO. You could also interpret a pipeline as a \"set of processes that are chained together, through the standard input/output devices of the system\". At Linux for example, a pipeline is created inside a terminal, by connecting two or more terminal commands with the \"pipe\" character (`|`).\n\nFrom the bullet points listed above, we know that although the term \"file\" is present,\na \"file descriptor\" might describe something more than just a file.\nThis concept of a \"file descriptor\" comes from the Portable Operating System Interface (POSIX) API,\nwhich is a set of standards that guide how operating systems across the world should be implemented,\nto maintain compatibility between them.\n\nA file descriptor not only identifies the input/output resource that you are using to receive or send some data,\nbut it also describes where this resource is, and also, which IO mode this resource is currently using.\nFor example, this IO resource might be using only the \"read\" IO mode, which means that this resource\nis open to \"read operations\", while \"write operations\" are not authorized.\nThese IO modes are essentially the modes that you provide to the argument `mode`\nfrom the `fopen()` C function, and also, from the `open()` Python built-in function.\n\nIn C, a \"file descriptor\" is a `FILE` pointer, but, in Zig, a file descriptor is a `File` object.\nThis data type (`File`) is described in the `std.fs` module of the Zig Standard Library.\nWe normally don't create a `File` object directly in our Zig code. Instead, we normally get such object as result when we\nopen an IO resource. In other words, we normally ask our OS to open a particular IO resource for us,\nand, if the OS do open successfully this IO resource, the OS normally handles back to us\na file descriptor to this particular IO resource.\n\nSo you usually get a `File` object by using functions and methods from the Zig Standard Library\nthat asks the OS to open some IO resource, like the `openFile()` method that opens a file in the\nfilesystem. The `net.Stream` object that we have created in @sec-create-socket is also a type of\nfile descriptor object.\n\n\n### The *standard output*\n\nYou already saw across this book, how can we access and use specifically the `stdout` in Zig\nto send some output to the user.\nFor that, we use the `getStdOut()` function from the `std.io` module. This function returns\na file descriptor that describes the `stdout` channel of your current OS. Through this file\ndescriptor object, we can read from or write stuff to the `stdout` of our program.\n\nAlthough we can read stuff recorded into the `stdout` channel, we normally only\nwrite to (or \"print\") stuff into this channel. The reason is very similar to what we discussed at\n@sec-read-http-message, when we were discussing what \"reading from\" versus \"writing to\" the connection\nobject from our small HTTP Server project would mean.\n\nWhen we write stuff into a channel, we are essentially sending data to the other end of this channel.\nIn contrast, when we read stuff from this channel, we are essentially reading the data that was sent\nthrough this channel. Since the `stdout` is a channel to send output to the user, the key verb here\nis **send**. We want to send something to someone, and, as consequence, we want to **write** something\ninto some channel.\n\nThat is why, when we use `getStdOut()`, most of the times, we also use the `writer()` method from the `stdout` file descriptor,\nto get access to a writer object that we can use to write stuff into this `stdout` channel.\nMore specifically, this `writer()` method returns a `GenericWriter` object. One of the\nmain methods of this `GenericWriter` object is the `print()` method that we have used\nbefore to write (or \"print\") a formatted string into the `stdout` channel.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n try stdout.writeAll(\n \"This message was written into stdout.\\n\"\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nThis message was written into stdout.\n```\n\n\n:::\n:::\n\n\n\n\n\n\nThis `GenericWriter` object is like any other generic writer object that you would normally get from a file descriptor object.\nSo, the same methods from a generic writer object that you would use while writing files to the filesystem for example, you could also\nuse them here, from the file descriptor object of `stdout`, and vice-versa.\n\n\n### The *standard input*\n\nYou can access the *standard input* (i.e., `stdin`) in Zig by using the `getStdIn()` function from the `std.io` module.\nLike its brother (`getStdOut()`), this function also returns a file descriptor object that describes the `stdin` channel\nof your OS.\n\nBecause we want to receive some input from the user, the key verb here becomes **receive**, and, as consequence,\nwe usually want to **read** data from the `stdin` channel, instead of writing data into it. So, we normally use\nthe `reader()` method of the file descriptor object returned by `getStdIn()`, to get access to a `GenericReader`\nobject that we can use to read data from `stdin`.\n\nIn the example below, we are creating a small buffer capable of holding 20 characters. Then, we try to read\nthe data from the `stdin` with the `readUntilDelimiterOrEof()` method, and save this data into the `buffer` object.\nAlso notice that we are reading the data from the `stdin` until we hit a new line character (`'\\n'`).\n\nIf you execute this program, you will notice that it stops the execution, ands start to wait indefinitely\nfor some input from the user. In other words, you need to type your name into the terminal, and then, you press Enter to\nsend your name to `stdin`. After you send your name to `stdin`, the program reads this input, and continues with the execution,\nby printing the given name to `stdout`. In the example below, I typed my name (Pedro) into the terminal, and then, pressed Enter.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst stdin = std.io.getStdIn().reader();\npub fn main() !void {\n try stdout.writeAll(\"Type your name\\n\");\n var buffer: [20]u8 = undefined;\n @memset(buffer[0..], 0);\n _ = try stdin.readUntilDelimiterOrEof(buffer[0..], '\\n');\n try stdout.print(\"Your name is: {s}\\n\", .{buffer});\n}\n```\n:::\n\n\n\n\n```\nType your name\nYour name is: Pedro\n\n```\n\n\n### The *standard error*\n\nThe *standard error* (a.k.a. the `stderr`) works exactly the same as `stdout` and `stdin`.\nYou just call the `getStdErr()` function from the `std.io` module, and you get the file descriptor to `stderr`.\nIdeally, you should write only error or warning messages to `stderr`, because this is\nthe purpose of this channel.\n\n\n\n\n\n## Buffered IO\n\nAs we described in @sec-io-basics, input/output (IO) operations are made directly by the operating system.\nIt's the OS that manages the IO resource that you want to use for your IO operations.\nThe consequence of this fact is that IO operations are heavily based on system calls (i.e., calling the operating system directly).\n\nJust to be clear, there is nothing particularly wrong with system calls. We use them all the time on\nany serious codebase written in any low-level programming language. However, system calls are\nalways orders of magnitude slower than many different types of operations.\n\nSo is perfectly fine to use a system call once in a while. But when these system calls are used often,\nyou can clearly notice most of the time the loss of performance in your application. So, the good rule of thumb\nis to use a system call only when it's needed, and also, only in infrequent situations, to reduce\nthe number of system calls performed to a minimum.\n\n\n### Understanding how buffered IO works\n\nBuffered IO is a strategy to achieve better performance. It's used to reduce the number of system calls made by IO operations, and, as\nconsequence, achieve a much higher performance. In @fig-unbuffered-io and @fig-buffered-io you can find two different diagrams\nwhich presents the difference between read operations performed in an unbuffered IO environment versus a buffered IO environment.\n\nTo give a better context to these diagrams, let's suppose that we have a text file that contains the famous Lorem ipsum text[^lorem]\nin our filesystem. Let's also suppose that these diagrams in @fig-unbuffered-io and @fig-buffered-io\nare showing the read operations that we are performing to read the Lorem ipsum text from this text file.\nThe first thing you will notice when looking at these diagrams, is that in an unbuffered environment\nthe read operations leads to many system calls.\nMore precisely, in the diagram exposed in @fig-unbuffered-io we get one system call per each byte that we read from the text file.\nOn the other hand, in @fig-buffered-io we have only one system call at the very beginning.\n\nWhen we use a buffered IO system, at the first read operation we perform, instead of sending one single byte directly\nto our program, the OS first sends a chunk of bytes from the file to a buffer object (i.e., an array).\nThis chunk of bytes are cached/stored inside this buffer object.\n\nTherefore, from now on, for every new read operation that you perform, instead of making a new system call to ask\nfor the next byte in the file to the OS, this read operation is redirected to the buffer object, that have\nthis next byte already cached and ready to go.\n\n\n[^lorem]: .\n\n\n![Unbuffered IO](./../Figures/unbuffered-io.png){#fig-unbuffered-io width=60%}\n\n![Buffered IO](./../Figures/buffered-io.png){#fig-buffered-io}\n\n\n\nThis is the basic logic behind buffered IO systems. The size of the buffer object depends on multiple factors. But it's usually\nequal to the size of a full page of memory (4096 bytes). If we follow this logic, then, the OS reads the first 4096 bytes\nof the file and caches it into the buffer object. As long as your program does not consume all of these 4096 bytes from the buffer,\nyou will not create new system calls.\n\nHowever, as soon as you consume all of these 4096 bytes from the buffer, it means that there is no bytes left in the buffer.\nIn this situation, a new system call is made to ask the OS to send the next 4096 bytes in the file, and once again,\nthese bytes are cached into the buffer object, and the cycle starts once again.\n\n\n### Buffered IO across different languages\n\nIO operations made through a `FILE` pointer in C are buffered\nby default, so, at least in C, you don't need to worry about this subject. But in contrast, IO operations in both Rust and Zig are not\nbuffered depending on which functions from the standard libraries that you are using.\n\nFor example, in Rust, buffered IO is implemented through the `BufReader` and `BufWriter` structs, while in Zig, it's implemented\nthrough the `BufferedReader` and `BufferedWriter` structs.\nSo any IO operation that you perform through the `GenericWriter` and `GenericReader` objects\nthat I presented in @sec-writer-reader are not buffered, which means that these objects\nmight create a lot of system calls depending on the situation.\n\n\n### Using buffered IO in Zig\n\nUsing buffered IO in Zig is actually very easy. All you have to do is to just\ngive the `GenericWriter` object to the `bufferedWriter()` function, or, to give the `GenericReader`\nobject to the `bufferedReader()` function. These functions come from the `std.io` module,\nand they will construct the `BufferedWriter` or `BufferedReader` object for you.\n\nAfter you create this new `BufferedWriter` or `BufferedReader` object, you can call the `writer()`\nor `reader()` method of this new object, to get access to a new (and buffered) generic reader or\ngeneric writer.\n\nLet's describe the process once again. Every time that you have a file descriptor object, you first get the generic writer or generic reader\nobject from it, by calling the `writer()` or `reader()` methods of this file descriptor object.\nThen, you provide this generic writer or generic reader to the `bufferedWriter()` or `bufferedReader()`\nfunction, which creates a new `BufferedWriter` or `BufferedReader` object. Then, you call\nthe `writer()` or `reader()` methods of this buffered writer or buffered reader object,\nwhich gives you access to a generic writer or a generic reader object that is buffered.\n\nTake this program as an example. This program is demonstrating the process exposed in @fig-buffered-io.\nWe are simply opening a text file that contains the Lorem ipsum text, and then, we create a buffered IO reader object\nat `bufreader`, and we use this `bufreader` object to read the contents of this file into a buffer object, then,\nwe end the program by printing this buffer to `stdout`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar file = try std.fs.cwd().openFile(\n \"ZigExamples/file-io/lorem.txt\", .{}\n);\ndefer file.close();\nvar buffered = std.io.bufferedReader(file.reader());\nvar bufreader = buffered.reader();\n\nvar buffer: [1000]u8 = undefined;\n@memset(buffer[0..], 0);\n\n_ = try bufreader.readUntilDelimiterOrEof(\n buffer[0..], '\\n'\n);\ntry stdout.print(\"{s}\\n\", .{buffer});\n```\n:::\n\n\n\n\n```\nLorem ipsum dolor sit amet, consectetur\nadipiscing elit. Sed tincidunt erat sed nulla ornare, nec\naliquet ex laoreet. Ut nec rhoncus nunc. Integer magna metus,\nultrices eleifend porttitor ut, finibus ut tortor. Maecenas\nsapien justo, finibus tincidunt dictum ac, semper et lectus.\nVivamus molestie egestas orci ac viverra. Pellentesque nec\narcu facilisis, euismod eros eu, sodales nisl. Ut egestas\nsagittis arcu, in accumsan sapien rhoncus sit amet. Aenean\nneque lectus, imperdiet ac lobortis a, ullamcorper sed massa.\nNullam porttitor porttitor erat nec dapibus. Ut vel dui nec\nnulla vulputate molestie eget non nunc. Ut commodo luctus ipsum,\nin finibus libero feugiat eget. Etiam vel ante at urna tincidunt\nposuere sit amet ut felis. Maecenas finibus suscipit tristique.\nDonec viverra non sapien id suscipit.\n```\n\nDespite being a buffered IO reader, this `bufreader` object is similar to any other `GenericReader` object,\nand have the exact same methods. So, although these two types of objects perform very different IO operations,\nthey have the same interface, so you, the programmer, can interchangeably use them\nwithout the need to change anything in your source code.\nSo a buffered IO reader or a buffered IO writer objects have the same methods than its generic and unbuffered brothers,\ni.e., the generic reader and generic writer objects that I presented in @sec-writer-reader.\n\n::: {.callout-tip}\nIn general, you should always use a buffered IO reader or a buffered IO writer object to perform\nIO operations in Zig. Because they deliver better performance to your IO operations.\n:::\n\n\n## Filesystem basics\n\nNow that we have discussed the basics around Input/Output operations in Zig, we need to\ntalk about the basics around filesystems, which is another core part of any operating system.\nAlso, filesystems are related to input/output, because the files that we store and create in our\ncomputer are considered an IO resource, as we described in @sec-file-descriptor.\n\n\n### The concept of current working directory (CWD)\n\nThe working directory is the folder on your computer where you are currently rooted at.\nIn other words, it's the folder that your program is currently looking at.\nTherefore, whenever you are executing a program, this program is always working with\na specific folder on your computer. It's always in this folder that the program will initially\nlook for the files you require, and it's also in this folder that the program\nwill initially save all the files you ask it to save.\n\nThe working directory is determined by the folder from which you invoke your program\nin the terminal. In other words, if you are in the terminal of your OS, and you\nexecute a binary file (i.e., a program) from this terminal, the folder to which your terminal\nis pointing at is the current working directory of your program that is being executed.\n\nIn @fig-cwd we have an example of me executing a program from the terminal. We are executing\nthe program outputted by the `zig` compiler by compiling the Zig module named `hello.zig`.\nThe CWD in this case is the `zig-book` folder. In other words, while the `hello.zig` program\nis executing, it will be looking at the `zig-book` folder, and any file operation that we perform\ninside this program, will be using this `zig-book` folder as the \"starting point\", or, as the \"central focus\".\n\n![Executing a program from the terminal](./../Figures/cwd.png){#fig-cwd}\n\nJust because we are rooted inside a particular folder (in the case of @fig-cwd, the `zig-book` folder) of our computer,\nit doesn't mean that we cannot access or write resources in other locations of our computer.\nThe current working directory (CWD) mechanism just defines where your program will look first\nfor the files you ask for. This does not prevent you from accessing files that are located\nelsewhere on your computer. However, to access any file that is in a folder other than your\ncurrent working directory, you must provide a path to that file or folder.\n\n\n### The concept of paths\n\nA path is essentially a location. It points to a location in your filesystem. We use\npaths to describe the location of files and folders in our computer.\nOne important aspect about paths is that they are always written inside strings,\ni.e., they are always provided as text values.\n\nThere are two types of paths that you can provide to any program in any OS: a relative path, or an absolute path.\nAbsolute paths are paths that start at the root of your filesystem, and go all the way to the file name or the specific folder\nthat you are referring to. This type of path is called absolute, because it points to an unique and absolute location on your computer.\nThat is, there is no other existing location on your computer that corresponds to this path. It's an unique identifier.\n\nIn Windows, an absolute path is a path that starts with a hard disk identifier (e.g. `C:/Users/pedro`).\nOn the other hand, absolute paths in Linux and macOS, are paths that start with a forward slash character (e.g. `/usr/local/bin`).\nNotice that a path is composed by \"segments\". Each segment is connected to each other by a slash character (`\\` or `/`).\nOn Windows, the backward slash (`\\`) is normally used to connect the path segments. While on Linux and macOS, the forward\nslash (`/`) is the character used to connect path segments.\n\nA relative path is a path that start at the CWD. In other words, a relative path is\n\"relative to the CWD\". The path used to access the `hello.zig` file in @fig-cwd is an example of a relative path. This path\nis reproduced below. This path begins at the CWD, which in the context of @fig-cwd, is the `zig-book` folder,\nthen, it goes to the `ZigExamples` folder, then, into `zig-basics`, then, to the `hello.zig` file.\n\n```\nZigExamples/zig-basics/hello_world.zig\n```\n\n\n### Path wildcards\n\nWhen providing paths, especially relative paths, you have the option of using a *wildcard*.\nThere are two commonly used *wildcards* in paths, which are \"one period\" (.) and \"two periods\" (..).\nIn other words, these two specific characters have special meanings when used in paths,\nand can be used on any operating system (Mac, Windows, Linux, etc.). That is, they\nare \"cross platform\".\n\nThe \"one period\" represents an alias for the current directory.\nThis means that the relative paths `\"./Course/Data/covid.csv\"` and `\"Course/Data/covid.csv\"` are equivalent.\nOn the other hand, the \"two periods\" refers to the previous directory.\nFor example, the path `\"Course/..\"` is equivalent to the path `\".\"`, that is, the current working directory.\n\nTherefore, the path `\"Course/..\"` refers to the folder before the `Course` folder.\nAs another example, the path `\"src/writexml/../xml.cpp\"` refers to the file `xml.cpp`\nthat is inside the folder before the `writexml` folder, which in this example is the `src` folder.\nTherefore, this path is equivalent to `\"src/xml.cpp\"`.\n\n\n\n\n## The CWD handler\n\nIn Zig, filesystem operations are usually made through a directory handler object.\nA directory handler in Zig is an object of type `Dir`, which is an object that describes\na particular folder in the filesystem of our computer.\nYou normally create a `Dir` object, by calling the `std.fs.cwd()` function.\nThis function returns a `Dir` object that points to (or, that describes) the\ncurrent working directory (CWD).\n\nThrough this `Dir` object, you can create new files, or modify, or read existing ones that are\ninside your CWD. In other words, a `Dir` object is the main entrypoint in Zig to perform\nmultiple types of filesystem operations.\nIn the example below, we are creating this `Dir` object, and storing it\ninside the `cwd` object. Although we are not using this object at this code example,\nwe are going to use it a lot over the next examples.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\n_ = cwd;\n```\n:::\n\n\n\n\n\n\n\n\n\n\n\n## File operations\n\n### Creating files {#sec-creating-files}\n\nWe create new files by using the `createFile()` method from the `Dir` object.\nJust provide the name of the file that you want to create, and this function will\ndo the necessary steps to create such file. You can also provide a relative path to this function,\nand it will create the file by following this path, which is relative to the CWD.\n\nThis function might return an error, so, you should use `try`, `catch`, or any of the other methods presented\nin @sec-error-handling to handle the possible error. But if everything goes well,\nthis `createFile()` method returns a file descriptor object (i.e., a `File` object) as result,\nthrough which you can add content to the file with the IO operations that I presented before.\n\nTake this code example below. In this example, we are creating a new text file\nnamed `foo.txt`. If the function `createFile()` succeeds, the object named `file` will contain a file descriptor\nobject, which we can use to write (or add) new content to the file, like we do in this example, by using\na buffered writer object to write a new line of text to the file.\n\nNow, a quick note, when we create a file descriptor object in C, by using a C function like `fopen()`, we must always close the file\nat the end of our program, or, as soon as we complete all operations that we wanted to perform\non the file. In Zig, this is no different. So everytime we create a new file, this file remains\n\"open\", waiting for some operation to be performed. As soon as we are done with it, we always have\nto close this file, to free the resources associated with it.\nIn Zig, we do this by calling the method `close()` from the file descriptor object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.createFile(\"foo.txt\", .{});\n// Don't forget to close the file at the end.\ndefer file.close();\n// Do things with the file ...\nvar fw = file.writer();\n_ = try fw.writeAll(\n \"Writing this line to the file\\n\"\n);\n```\n:::\n\n\n\n\n\nSo, in this example we not only have created a file into the filesystem,\nbut we also wrote some data into this file, using the file descriptor object\nreturned by `createFile()`. If the file that you are trying to create\nalready exists in your filesystem, this `createFile()` call will\noverwrite the contents of the file, or, in other words, it will\nin erase all the contents of the existing file.\n\nIf you don't want this to happen, meaning, that you don't want to overwrite\nthe contents of the existing file, but you want to write data to this file anyway\n(i.e., you want to append data to the file), you should use the `openFile()`\nmethod from the `Dir` object.\n\nAnother important aspect about `createFile()` is that this method creates a file\nthat is not open to read operations by default. It means that you cannot read this file.\nYou are not allowed to.\nSo for example, you might want to write some stuff into this file at the beginning of the execution\nof your program. Then, at a future point in your program you might need to read what you\nwrote in this file. If you try to read data from this file, you will likely\nget a `NotOpenForReading` error as result.\n\n\nBut how can you overcome this barrier? How can you create a file that is open\nto read operations? All you have to do, is to set the `read` flag to true\nin the second argument of `createFile()`. When you set this flag to true,\nthen the file gets create with \"read permissions\", and, as consequence,\na program like this one below becomes valid:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.createFile(\n \"foo.txt\",\n .{ .read = true }\n);\ndefer file.close();\n\nvar fw = file.writer();\n_ = try fw.writeAll(\"We are going to read this line\\n\");\n\nvar buffer: [300]u8 = undefined;\n@memset(buffer[0..], 0);\ntry file.seekTo(0);\nvar fr = file.reader();\n_ = try fr.readAll(buffer[0..]);\ntry stdout.print(\"{s}\\n\", .{buffer});\n```\n:::\n\n\n\n\n\n```\nWe are going to read this line\n```\n\n\nIf you are not familiar with position indicators, you might not recognize the method\n`seekTo()`. If that is your case, do not worry,\nwe are going to talk more about this method in @sec-indicators. But essentially\nthis method is moving the position indicator back to the beginning of the file,\nso that we can read the contents of the file from the beginning.\n\n\n### Opening files and appending data to it\n\nOpening files is easy. Just use the `openFile()` method instead of `createFile()`.\nIn the first argument of `openFile()` you provide the path to the file that\nyou want to open. Then, on the second argument you provide the flags (or, the options)\nthat dictates how the file is opened.\n\nYou can see the full list of options for `openFile()` by visiting the documentation for\n[`OpenFlags`](https://ziglang.org/documentation/master/std/#std.fs.File.OpenFlags)[^oflags].\nBut the main flag that you will most certainly use is the `mode` flag.\nThis flag specifies the IO mode that the file will be using when it gets opened.\nThere are three IO modes, or, three values that you can provide to this flag, which are:\n\n- `read_only`, allows only read operations on the file. All write operations are blocked.\n- `write_only`, allows only write operations on the file. All read operations are blocked.\n- `read_write`, allows both write and read operations on the file.\n\n[^oflags]: \n\nThese modes are similar to the modes that you provide to the `mode` argument of the\n`open()` Python built-in function[^py-open], or, the `mode` argument of the\n`fopen()` C function[^c-open].\nIn the code example below, we are opening the `foo.txt` text file with a `write_only` mode,\nand appending a new line of text to the end of the file. We use `seekFromEnd()` this time\nto guarantee that we are going to append the text to the end of the file. Once again, methods\nsuch as `seekFromEnd()` are described in more depth in @sec-indicators.\n\n[^py-open]: \n[^c-open]: \n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.openFile(\n \"foo.txt\", .{ .mode = .write_only }\n);\ndefer file.close();\ntry file.seekFromEnd(0);\nvar fw = file.writer();\n_ = try fw.writeAll(\"Some random text to write\\n\");\n```\n:::\n\n\n\n\n\n### Deleting files\n\nSometimes, we just need to delete/remove the files that we have.\nTo do that, we use the `deleteFile()` method. You just provide the path of the\nfile that you want to delete, and this method will try to delete the file located\nat this path.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.deleteFile(\"foo.txt\");\n```\n:::\n\n\n\n\n### Copying files\n\nTo copy existing files, we use the `copyFile()` method. The first argument in this method\nis the path to the file that you want to copy. The second argument is a `Dir` object, i.e., a directory handler,\nmore specifically, a `Dir` object that points to the folder in your computer where you want to\ncopy the file to. The third argument is the new path of the file, or, in other words, the new location\nof the file. The fourth argument is the options (or flags) to be used in the copy operation.\n\nThe `Dir` object that you provide as input to this method will be used to copy the file to\nthe new location. You may create this `Dir` object before calling the `copyFile()` method.\nMaybe you are planning to copy the file to a completely different location in your computer,\nso it might be worth to create a directory handler to that location. But if you are copying the\nfile to a subfolder of your CWD, then, you can just simply pass the CWD handler to this argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.copyFile(\n \"foo.txt\",\n cwd,\n \"ZigExamples/file-io/foo.txt\",\n .{}\n);\n```\n:::\n\n\n\n\n\n### Read the docs!\n\nThere are some other useful methods for file operations available at `Dir` objects,\nsuch as the `writeFile()` method, but I recommend you to read the docs for the\n[`Dir` type](https://ziglang.org/documentation/master/std/#std.fs.Dir)[^zig-dir]\nto explore the other available methods, since I already talked too much about them.\n\n\n[^zig-dir]: \n\n\n\n\n## Position indicators {#sec-indicators}\n\nA position indicator is like a type of cursor, or, an index. This \"index\" identifies the current\nlocation in the file (or, in the data stream) that the file descriptor object that you have\nis currently looking at.\nWhen you create a file descriptor, the position indicator starts at the beginning of the file,\nor, at the beginning of the stream. When you read from or write into the file (or socket, or data stream, etc.)\ndescribed by this file descriptor object, you end up moving the position indicator.\n\nIn other words, any IO operation have a common side effect, which is to move the position indicator.\nFor example, suppose that we have a file of 300 bytes total in size. If you\nread 100 bytes from the file, then, the position indicator moves 100 bytes forward. If you try\nto write 50 bytes into this same file, these 50 bytes will be written from the current\nposition indicated by the position indicator. Since the indicator is at a 100 bytes forward from\nthe beginning of the file, these 50 bytes would be written in the middle of the file.\n\nThis is why we have used the `seekTo()` method at the last code example presented in @sec-creating-files.\nWe have used this method to move the position indicator back to the beginning of the file, which\nwould make sure that we would write the text that we wanted to write from the beginning of the file,\ninstead of writing it from the middle of the file. Because before the write operation, we had\nperformed a read operation, which means that the position indicator was moved in this read operation.\n\nThe position indicators of a file descriptor object can be changed (or altered) by using the\n\"seek\" methods from this file descriptor, which are: `seekTo()`, `seekFromEnd()` and `seekBy()`.\nThese methods have the same effect, or, the same responsibility that the\n[`fseek()`](https://en.cppreference.com/w/c/io/fseek)[^c-fseek] C function.\n\n[^c-fseek]: \n\n\nConsidering that `offset` refers to the index that you provide as input to these \"seek\" methods,\nthe bullet points below summarises what is the effect of each of these methods.\nAs a quick note, in the case of `seekFromEnd()` and `seekBy()`, the `offset` provided can be either a\npositive or a negative index.\n\n- `seekTo()` will move the position indicator to the location that is `offset` bytes from the beginning of the file.\n- `seekFromEnd()` will move the position indicator to the location that is `offset` bytes from the end of the file.\n- `seekBy()` will move the position indicator to the location that is `offset` bytes from the current position in the file.\n\n\n\n\n\n\n\n## Directory operations\n\n### Iterating through the files in a directory\n\nOne of the most classic tasks related to filesystem is to be able\nto iterate through the existing files in a directory. To iterate over the\nfiles in a directory, we need to create an iterator object.\n\nYou can produce such iterator object by using either the `iterate()` or `walk()` methods\nof a `Dir` object. Both methods return an iterator object as output, which you can advance by using the\n`next()` method. The difference between these methods, is that `iterate()` returns a non-recursive iterator,\nwhile `walk()` does. It means that the iterator returned by `walk()` will not only iterate through\nthe files available in the current directory, but also, through the files from any subdirectory found\ninside the current directory.\n\nIn the example below, we are displaying the names of the files stored inside the\ndirectory `ZigExamples/file-io`. Notice that we had to open this directory through\nthe `openDir()` function. Also notice that we provided the flag `iterate` in the\nsecond argument of `openDir()`. This flag is important, because without this flag,\nwe would not be allowed to iterate through the files in this directory.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst dir = try cwd.openDir(\n \"ZigExamples/file-io/\",\n .{ .iterate = true }\n);\nvar it = dir.iterate();\nwhile (try it.next()) |entry| {\n try stdout.print(\n \"File name: {s}\\n\",\n .{entry.name}\n );\n}\n```\n:::\n\n\n\n\n```\nFile name: create_file_and_write_toit.zig\nFile name: create_file.zig\nFile name: lorem.txt\nFile name: iterate.zig\nFile name: delete_file.zig\nFile name: append_to_file.zig\nFile name: user_input.zig\nFile name: foo.txt\nFile name: create_file_and_read.zig\nFile name: buff_io.zig\nFile name: copy_file.zig\n```\n\n\n### Creating new directories\n\nThere are two methods that are important when it comes to\ncreating directories, which are `makeDir()` and `makePath()`.\nThe difference between these two methods is that `makeDir()` can\nonly create one single directory in the current directory in each call,\nwhile `makePath()` is capable of recursively create subdirectories in the same call.\n\n\nThis is why the name of this method is \"make path\". It will create as many\nsubdirectories as necessary to create the path that you provided as input.\nSo, if you provide the path `\"sub1/sub2/sub3\"` as input to this method,\nit will create three different subdirectories, `sub1`, `sub2` and `sub3`,\nwithin the same function call. In contrast, if you provided such path\nas input to `makeDir()`, you would likely get an error as result, since\nthis method can only create a single subdirectory.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.makeDir(\"src\");\ntry cwd.makePath(\"src/decoders/jpg/\");\n```\n:::\n\n\n\n\n### Deleting directories\n\nTo delete a directory, just provide the path to the directory that you want to delete\nas input to the `deleteDir()` method from a `Dir` object. In the example below,\nwe are deleting the `src` directory that we have just created in the previous example.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.deleteDir(\"src\");\n```\n:::\n\n\n\n\n\n## Conclusion\n\nIn this chapter, I have described how to perform in Zig the most common filesystem and IO operations.\nBut you might feel the lack of some other, less common, operation in this chapter, such as: how to rename files,\nor how to open a directory, or how to create symbolic links, or how to use `access()` to test if a particular\npath exists in your computer. But for all of these less common tasks, I recommend you to read\nthe documentation of the [`Dir` type](https://ziglang.org/documentation/master/std/#std.fs.Dir)[^zig-dir]\n, since you can find a good description of these cases there.\n", + "supporting": [ + "12-file-op_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/13-image-filter/execute-results/html.json b/_freeze/Chapters/13-image-filter/execute-results/html.json index 94161bf3..5564dfd4 100644 --- a/_freeze/Chapters/13-image-filter/execute-results/html.json +++ b/_freeze/Chapters/13-image-filter/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "913ef6c1f2a988d49f8b7ce026c813b6", + "hash": "99b3cf5d4ae363f25838f780686e3234", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 4 - Developing an image filter\n\nIn this chapter we are going to build a new project. The objective of\nthis project is to write a program that applies a filter over an image.\nMore specifically, a \"grayscale filter\", which transforms\nany color image into a grayscale image.\n\nWe are going to use the image displayed at @fig-pascal in this project.\nIn other words, we want to transform this colored image into a grayscale image,\nby using our \"image filter program\" written in Zig.\n\n![A photo of the chilean-american actor Pedro Pascal. Source: Google Images.](../ZigExamples/image_filter/pedro_pascal.png){#fig-pascal}\n\nWe don't need to write a lot of code to build such \"image filter program\". However, we first need\nto understand how digital images work. That is why we begin this chapter\nby explaining the theory behind digital images and how colors are represented in modern computers.\nWe also give a brief explanation about the PNG (Portable Network Graphics) file format, which is the format used\nin the example images.\n\nAt the end of this chapter, we should have a full example of a program that takes the PNG image displayed at @fig-pascal\nas input, and writes a new image to the current working directory that is the grayscale version of this input image.\nThis grayscale version of @fig-pascal is exposed at @fig-pascal-gray.\nYou can find the full source code of this small project at the `ZigExamples/image_filter`\n[folder at the official repository of this book](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/image_filter)[^img-filter-folder].\n\n\n![The grayscale version of the photo.](../ZigExamples/image_filter/pedro_pascal_filter.png){#fig-pascal-gray}\n\n\n## How we see things? {#sec-eyes}\n\nIn this section, I want to briefly describe to you how we (humans) actually see things with our own eyes.\nI mean, how our eyes work? If you do have a very basic understanding of how our eyes work, you will understand\nmore easily how digital images are made. Because the techniques behind digital images\nwere developed by taking a lot of inspiration from how our human eyes work.\n\nYou can interpret a human eye as a light sensor, or, a light receptor. The eye receives some amount of light as input,\nand it interprets the colors that are present in this \"amount of light\".\nIf no amount of light hits the eye, then, the eye cannot extract color from it, and as result,\nwe end up seeing nothing, or, more precisely, we see complete blackness.\n\nTherefore, everything depends on light. What we actually see are the colors (blue, red, orange, green, purple, yellow, etc.) that\nare being reflected from the light that is hitting our eyes. **Light is the source of all colors!**\nThis is what Isaac Newton discovered on his famous prism experiment[^newton] in the 1660s.\n\n[^newton]: \n\nInside our eyes, we have a specific type of cell called the \"cone cell\".\nOur eye have three different types, or, three different versions of these \"cone cells\".\nEach type of cone cell is very sensitive to a specific spectrum of the light. More specifically,\nto the spectrums that define the colors red, green and blue.\nSo, in summary, our eyes have specific types of cells that\nare highly sensitive to these three colors (red, green and blue).\n\nThese are the cells responsible for perceiving the color present in the light that hits our eyes.\nAs a result, our eyes perceives color as a mixture of these three colors (red, green and blue). By having an amount\nof each one of these three colors, and mixing them together, we can get any other visible color\nthat we want. So every color that we see is perceived as a specific mixture of blues, greens and reds,\nlike 30% of red, plus 20% of green, plus 50% of blue.\n\nWhen these cone cells perceive (or, detect) the colors that are found in the\nlight that is hitting our eyes, these cells produce electrical signals, which are sent to the brain.\nOur brain interprets these electrical signals, and use them to form the image that we are seeing\ninside our head.\n\nBased on what we have discussed here, the bullet points exposed below describes the sequence of events that\ncomposes this very simplified version of how our human eyes work:\n\n1. Light hits our eyes.\n1. The cone cells perceive the colors that are present in this light.\n1. Cone cells produce electrical signals that describes the colors that were perceived in the light.\n1. The electrical signals are sent to the brain.\n1. Brain interprets these signals, and form the image based on the colors identified by these electrical signals.\n\n\n## How digital images work? {#sec-digital-img}\n\nA digital image is a \"digital representation\" of an image that we see with our eyes.\nIn other words, a digital image is a \"digital representation\" of the colors that we see\nand perceive through the light.\nIn the digital world, we have two types of images, which are: vector images and raster images.\nVector images are not described here. So just remember that the content discussed here\n**is related solely to raster images**, and not vector images.\n\nA raster image is a type of digital image that is represented as a 2D (two dimensional) matrix\nof pixels. In other words, every raster image is basically a rectangle of pixels, and each pixel have a particular color.\nSo, a raster image is just a rectangle of pixels, and each of these pixels are displayed in the screen of your computer (or the screen\nof any other device, e.g. laptop, tablet, smartphone, etc.) as a color.\n\n@fig-raster demonstrates this idea. If you take any raster image, and you zoom into it very hard,\nyou will see the actual pixels of the image. JPEG, TIFF and PNG are file formats that are commonly\nused to store raster images.\n\n![Zooming over a raster image to see the pixels. Source: Google Images.](../Figures/imagem-raster.png){#fig-raster}\n\nThe more pixels the image has, the more information and detail we can include in the image.\nThe more accurate, sharp and pretty the image will look. This is why photographic cameras\nusually produce big raster images, with several megapixels of resolution, to include as much detail as possible into the final image.\nAs an example, a digital image with dimensions of 1920 pixels wide and 1080 pixels high, would be a image that\ncontains $1920 \\times 1080 = 2073600$ pixels in total. You could also say that the \"total area\" of the image is\nof 2073600 pixels, although the concept of \"area\" is not really used here in computer graphics.\n\nMost digital images we see in our modern world uses the RGB color model. RGB stands for (red, green and blue).\nSo the color of each pixel in these raster images are usually represented as a mixture of red, green and blue,\njust like in our eyes. That is, the color of each pixel is identified by a set of\nthree different integer values. Each integer value identifies the \"amount\" of each color (red, green and blue).\nFor example, the set `(199, 78, 70)` identifies a color that is more close to red. We have 199 of red, 78 of green,\nand 70 of blue. In contrast, the set `(129, 77, 250)` describes a color that is more close to purple. Et cetera.\n\n\n\n### Images are displayed from top to bottom\n\nThis is not a rule written in stone, but the big majority of digital images are displayed from top\nto bottom and left to right. Most computers screens also follow this pattern. So, the first pixels\nin the image are the ones that are at the top and left corner of the image. You can find a visual representation\nof this logic at @fig-img-display.\n\nAlso notice in @fig-img-display that, because a raster image is essentially a 2D matrix of pixels,\nthe image is organized into rows and columns of pixels. The columns are defined by the horizontal x axis,\nwhile the rows are defined by the vertical y axis.\n\nEach pixel (i.e. the gray rectangles) exposed at @fig-img-display contains a number inside of it.\nThese numbers are the indexes of the pixels. You can notice that the first pixels are in the top and left\ncorner, and also, that the indexes of these pixels \"grow to the sides\", or, in other words, they grow in the direction of the horizontal x axis.\nMost raster images are organized as rows of pixels. Thus, when these digital images are\ndisplayed, the screen display the first row of pixels, then, the second row, then, the third row, etc.\n\n![How the pixels of raster images are displayed.](./../Figures/image-display.png){#fig-img-display}\n\n\n\n\n\n\n### Representing the matrix of pixels in code {#sec-pixel-repr}\n\nOk, we know already that raster images are represented as 2D matrices of pixels.\nBut we do not have a notion of a 2D matrix in Zig. Actually, most low-level languages in general\n(Zig, C, Rust, etc.) do not have such notion.\nSo how can we represent such matrix of pixels in Zig, or any other low-level language?\nThe strategy that most programmers choose in this situation is to just use a normal 1D array to store the values of\nthis 2D matrix. In other words, you just create an normal 1D array, and store all values from both dimensions into this 1D array.\n\nAs an example, suppose we have a very small image of dimensions 4x3.\nSince a raster image is represented as a 2D matrix of pixels, and each pixel\nis represented by 3 \"unsigned 8-bit\" integer values, we have 12 pixels in\ntotal in this image, which are represented by $3 \\times 12 = 36$ integer values.\nTherefore, we need to create an array of 36 `u8` values to store this small image.\n\nThe reason why unsigned 8-bit integer (`u8`) values are used to represent the amounts of each color,\ninstead of any other integer type, is because they take the minimum amount of space as possible, or,\nthe minimum amount of bits as possible. Which helps to reduces the binary size of the image, i.e. the 2D matrix.\nAlso, they convey a good amount of precision and detail about the colors, even though they can represent\na relatively small range (from 0 to 255) of \"color amounts\".\n\nComing back to our initial example of a 4x3 image,\nthe `matrix` object exposed below could be an example of an 1D array that stores\nthe data that represents this 4x3 image.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst matrix = [_]u8{\n 201, 10, 25, 185, 65, 70,\n 65, 120, 110, 65, 120, 117,\n 98, 95, 12, 213, 26, 88,\n 143, 112, 65, 97, 99, 205,\n 234, 105, 56, 43, 44, 216,\n 45, 59, 243, 211, 209, 54,\n};\n```\n:::\n\n\n\n\nThe first three integer values in this array are the color amounts of the first pixel in the image.\nThe next three integers are the colors amounts for the second pixel.\nAnd the sequence goes on in this pattern. Having that in mind, the size of the array that stores\na raster image is usually a multiple of 3. In this case, the array have a size of 36.\n\nI mean, the size of the array is **usually** a multiple of 3, because in specific circumstances,\nit can also be a multiple of 4. This happens when a transparency amount is\nalso included into the raster image. In other words, there are some types of raster images\nthat uses a different color model, which is the RGBA (red, green, blue and alpha)\ncolor model. The \"alpha\" corresponds to an amount of transparency in the pixel.\nSo every pixel in a RGBA image is represented by a red, green, blue and alpha values.\n\nMost raster images uses the standard RGB model, so, for the most part, you will\nsee arrays sizes that are multiples of 3. But some images, especially the ones\nthat are stored in PNG files, might be using the RGBA model, and, therefore, are\nrepresented by an array whose size is a multiple of 4.\n\nIn our case here, the example image of our project (@fig-pascal) is a raster image\nstored in a PNG file, and this specific image is using the RGBA color model. Therefore,\neach pixel in the image is represented by 4 different integer values, and, as consequence,\nto store this image in our Zig code, we need to create an array whose size is a multiple of 4.\n\n\n## The PNG library that we are going to use\n\nLet's begin our project by focusing on writing the necessary Zig code to\nread the data from the PNG file. In other words, we want to read the PNG file exposed\nat @fig-pascal, and parse its data to extract the 2D matrix of pixels that represents the image.\n\nAs we have discussed at @sec-pixel-repr, the image that we are using as example here\nis a PNG file that uses the RGBA color model, and, therefore, each pixel of the image\nis represented by 4 integer values. You can download this image by visiting the `ZigExamples/image_filter`\n[folder at the official repository of this book](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/image_filter)[^img-filter-folder].\nYou can also find in this folder the complete source code of this small project that we\nare developing here.\n\n[^img-filter-folder]: \n\nThere are some C libraries available that we can use to read and parse PNG files.\nThe most famous and used of all is `libpng`, which is the \"official library\" for reading and writing\nPNG files. Although this library is available on most operating system, it is well known\nfor being complex and hard to use.\n\nThat is why, I'm going to use a more modern alternative here in this project, which is the `libspng` library.\nI choose to use this C library here, because it is much, much simpler to use than `libpng`,\nand it also offers very good performance for all operations. You can checkout the\n[official website of the library](https://libspng.org/)[^libspng]\nto know more about it. You will also find there some documentation that might help you to understand and\nfollow the code examples exposed here.\n\n[^libspng]: \n\n\nFirst of all, remember to build and install this `libspng` into your system. Because\nif you don't do this step, the `zig` compiler will not be able to find the files and resources of\nthis library in your computer, and link them with the Zig source code that we are writing together here.\nThere is good information about how to build and install the library at the\n[build section of the library documentation](https://libspng.org/docs/build/)[^lib-build].\n\n[^lib-build]: \n\n\n\n\n## Reading the PNG file\n\nIn order to extract the pixel data from the PNG file, we need to read and decode the file.\nA PNG file is just a binary file written in the \"PNG format\". Luckily, the `libspng` library offers\na function called `spng_decode_image()` that does all this heavy work for us.\n\nNow, since `libspng` is a C library, most of the file and I/O operations in this library are made by using\na `FILE` C pointer. Because of that, is probably a better idea to use the `fopen()` C function\nto open our PNG file, instead of using the `openFile()` method that I introduced at @sec-filesystem.\nThat is why I'm importing the `stdio.h` C header in this project, and using the `fopen()` C function to open the file.\n\nIf you look at the snippet below, you can see that we are:\n\n1. opening the PNG file with `fopen()`.\n1. creating the `libspng` context with `spng_ctx_new()`.\n1. using `spng_set_png_file()` to specify the `FILE` object that reads the PNG file that we are going to use.\n\nEvery operation in `libspng` is made through a \"context object\". In our snippet below, this object is `ctx`.\nAlso, to perform an operation over a PNG file, we need to specify which exact PNG file we are referring to.\nThis is the job of `spng_set_png_file()`. We are using this function to specify the file descriptor\nobject that reads the PNG file that we want to use.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cDefine(\"_NO_CRT_STDIO_INLINE\", \"1\");\n @cInclude(\"stdio.h\");\n @cInclude(\"spng.h\");\n});\n\nconst path = \"pedro_pascal.png\";\nconst file_descriptor = c.fopen(path, \"rb\");\nif (file_descriptor == null) {\n @panic(\"Could not open file!\");\n}\nconst ctx = c.spng_ctx_new(0) orelse unreachable;\n_ = c.spng_set_png_file(\n ctx, @ptrCast(file_descriptor)\n);\n```\n:::\n\n\n\n\nBefore we continue, is important to emphasize the following: since we have opened the file with `fopen()`,\nwe have to remember to close the file at the end of the program, with `fclose()`.\nIn other words, after we have done everything that we wanted to do with the PNG file\n`pedro_pascal.png`, we need to close this file, by applying `fclose()` over the file descriptor object.\nWe could use also the `defer` keyword to help us in this task, if we want to.\nThis code snippet below demonstrates this step:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (c.fclose(file_descriptor) != 0) {\n return error.CouldNotCloseFileDescriptor;\n}\n```\n:::\n\n\n\n\n\n\n\n### Reading the image header section\n\nNow, the context object `ctx` is aware of our PNG file `pedro_pascal.png`, because it has access to\na file descriptor object to this file. The first thing that we are going to do is to read the\n\"image header section\" of the PNG file. This \"image header section\" is the section\nof the file that contains some basic information about the PNG file, like, the bit depth of the pixel data\nof the image, the color model used in the file, the dimensions of the image (height and width in number of pixels),\netc.\n\nTo make things easier, I will encapsulate this \"read image header\" operation into a\nnice and small function called `get_image_header()`. All that this function needs to do\nis to call the `spng_get_ihdr()` function. This function from `libspng` is responsible\nfor reading the image header data, and storing it into a C struct named `spng_ihdr`.\nThus, an object of type `spng_ihdr` is a C struct that contains the data from the\nimage header section of the PNG file.\n\nSince this Zig function is receiving a C object (the `libspng` context object) as input, I marked\nthe function argument `ctx` as \"a pointer to the context object\" (`*c.spng_ctx`), following the recommendations\nthat we have discussed at @sec-pass-c-structs.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn get_image_header(ctx: *c.spng_ctx) !c.spng_ihdr {\n var image_header: c.spng_ihdr = undefined;\n if (c.spng_get_ihdr(ctx, &image_header) != 0) {\n return error.CouldNotGetImageHeader;\n }\n\n return image_header;\n}\n\nvar image_header = try get_image_header(ctx);\n```\n:::\n\n\n\n\nAlso notice in this function, that I'm checking if the `spng_get_ihdr()` function call have\nreturned or not an integer value that is different than zero. Most functions from the\n`libspng` library return a code status as result, and the code status \"zero\" means\n\"success\". So any code status that is different than zero means that an error\noccurred while running `spng_get_ihdr()`. This is why I'm returning an error value from\nthe function in case the code status returned by the function is different than zero.\n\n\n### Allocating space for the pixel data\n\nBefore we read the pixel data from the PNG file, we need to allocate enough space to hold this data.\nBut in order to allocate such space, we first need to know how much space we need to allocate.\nThe dimensions of the image are obviously needed to calculate the size of this space. But there are\nother elements that also affect this number, such as the color model used in the image, the bit depth, and others.\n\nAnyway, all of this means that calculating the size of the space that we need, is not a simple task.\nThat is why the `libspng` library offers an utility function named\n`spng_decoded_image_size()` to calculate this size for us. Once again, I'm going\nto encapsulate the logic around this C function into a nice and small Zig function\nnamed `calc_output_size()`. You can see below that this function returns a nice\ninteger value as result, informing the size of the space that we need to allocate.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn calc_output_size(ctx: *c.spng_ctx) !u64 {\n var output_size: u64 = 0;\n const status = c.spng_decoded_image_size(\n ctx, c.SPNG_FMT_RGBA8, &output_size\n );\n if (status != 0) {\n return error.CouldNotCalcOutputSize;\n }\n return output_size;\n}\n```\n:::\n\n\n\n\n\n\nYou might quest yourself what the value `SPNG_FMT_RGBA8` means. This value is actually an enum\nvalue defined in the `spng.h` C header file. This enum is used to identify a \"PNG format\".\nMore precisely, it identifies a PNG file that uses the RGBA color model and 8 bit depth.\nSo, by providing this enum value as input to the `spng_decoded_image_size()` function,\nwe are saying to this function to calculate the size of the decoded pixel data, by considering\na PNG file that follows this \"RGBA color model with 8 bit depth\" format.\n\nHaving this function, we can use it in conjunction with an allocator object, to allocate an\narray of bytes (`u8` values) that is big enough to store the decoded pixel data of the image.\nNotice that I'm using `@memset()` to initialize the entire array to zero.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst output_size = try calc_output_size(ctx);\nvar buffer = try allocator.alloc(u8, output_size);\n@memset(buffer[0..], 0);\n```\n:::\n\n\n\n\n\n### Decoding the image data\n\nNow that we have the necessary space to store the decoded pixel data of the image,\nwe can start to actually decode and extract this pixel data from the image,\nby using the `spng_decode_image()` C function.\n\nThe `read_data_to_buffer()` Zig function exposed below summarises the necessary\nsteps to read this decoded pixel data, and store it into an input buffer.\nNotice that this function is encapsulating the logic around the `spng_decode_image()` function.\nAlso, we are using the `SPNG_FMT_RGBA8` enum value once again to inform the corresponding function,\nthat the PNG image being decoded, uses the RGBA color model and 8 bit depth.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn read_data_to_buffer(ctx: *c.spng_ctx, buffer: []u8) !void {\n const status = c.spng_decode_image(\n ctx,\n buffer.ptr,\n buffer.len,\n c.SPNG_FMT_RGBA8,\n 0\n );\n\n if (status != 0) {\n return error.CouldNotDecodeImage;\n }\n}\n```\n:::\n\n\n\n\nHaving this function at hand, we can apply it over our context object, and also, over\nthe buffer object that we have allocated in the previous section to hold the decoded pixel data\nof the image:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry read_data_to_buffer(ctx, buffer[0..]);\n```\n:::\n\n\n\n\n\n### Looking at the pixel data\n\nNow that we have the pixel data stored in our \"buffer object\", we can take\na quick look at the bytes. In the example below, we are looking at the first\n12 bytes in the decoded pixel data.\n\nIf you take a close look at these values, you might notice that every 4 bytes\nin the sequence is 255. Which, coincidentally is the maximum possible integer value\nto be represented by a `u8` value. So, if the range from 0 to 255, which is the range\nof integer values that can be represented by an `u8` value, can be represented as a scale from 0% to 100%,\nthese 255 values are essentially 100% in that scale.\n\nIf you recall from @sec-pixel-repr, I have\ndescribed in that section that our `pedro_pascal.png` PNG file uses the RGBA color model,\nwhich adds an alpha (or transparency) byte to each pixel in the image.\nAs consequence, each pixel in the image is represented by 4 bytes. Since we are looking\nhere are the first 12 bytes in the image, it means that we are looking at the data from\nthe first $12 / 4 = 3$ pixels in the image.\n\nSo, based on how these first 12 bytes (or these 3 pixels) look, with these 255 values at every 4 bytes, we can say that is likely\nthat every pixel in the image have alpha (or transparency) setted to 100%. This might not be true,\nbut, is the most likely possibility. Also, if we look at the image itself, which if your recall is\nexposed at @fig-pascal, we can see that the transparency does not change across the image,\nwhich enforces this theory.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry stdout.print(\"{any}\\n\", .{buffer[0..12]});\n```\n:::\n\n\n\n\n```\n{\n 200, 194, 216, 255, 203, 197,\n 219, 255, 206, 200, 223, 255\n}\n```\n\n\nWe can see in the above result that the first pixel in this image have 200 of red, 194 of green, and 216 of blue.\nHow do I know the order in which the colors appears in the sequence? If you have not guessed that yet,\nis because of the acronym RGB. First RED, then GREEN, then BLUE. If we scale these integer values\naccording to our scale of 0% to 100% (0 to 255), we get 78% of red, 76% of green and 85% of blue.\n\n\n\n## Applying the image filter\n\nNow that we have the data of each pixel in the image, we can focus on applying our image\nfilter over these pixels. Remember, our objective here is to apply a grayscale filter over\nthe image. A grayscale filter is a filter that transforms a colored image into a grayscale image.\n\nThere are different formulas and strategies to transform a colored image into a grayscale image.\nBut all of these different strategies normally involve applying some math over the colors of each pixel.\nIn this project, we are going to use the most general formula, which is exposed below.\nThis formula considers $r$ as the red of the pixel, $g$ as the green, $b$ as the blue, and $p'$ as the\nlinear luminance of the pixel.\n\n$$\n p' = (0.2126 \\times r) + (0.7152 \\times g) + (0.0722 \\times b)\n$${#eq-grayscale}\n\nThis @eq-grayscale is the formula to calculate the linear luminance of a pixel. Is worth noting that this formula\nworks only for images whose pixels are using the sRGB color space, which is the standard color space\nfor the web. Thus, ideally, all images on the web should use this color space. Luckily,\nthis is our case here, i.e. the `pedro_pascal.png` image is using this sRGB color space, and, as consequence,\nwe can use the @eq-grayscale. You can read more about this formula at the Wikipedia page for grayscale [@wiki_grayscale].\n\nThe `apply_image_filter()` function exposed below summarises the necessary steps to\napply @eq-grayscale over the pixels in the image. We just apply this function\nover our buffer object that contains our pixel data, and, as result, the pixel\ndata stored in this buffer object should now represent the grayscale version of our image.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn apply_image_filter(buffer:[]u8) !void {\n const len = buffer.len;\n const red_factor: f16 = 0.2126;\n const green_factor: f16 = 0.7152;\n const blue_factor: f16 = 0.0722;\n var index: u64 = 0;\n while (index < len) : (index += 4) {\n const rf: f16 = @floatFromInt(buffer[index]);\n const gf: f16 = @floatFromInt(buffer[index + 1]);\n const bf: f16 = @floatFromInt(buffer[index + 2]);\n const y_linear: f16 = (\n (rf * red_factor) + (gf * green_factor)\n + (bf * blue_factor)\n );\n buffer[index] = @intFromFloat(y_linear);\n buffer[index + 1] = @intFromFloat(y_linear);\n buffer[index + 2] = @intFromFloat(y_linear);\n }\n}\n\ntry apply_image_filter(buffer[0..]);\n```\n:::\n\n\n\n\n\n\n## Saving the grayscale version of the image\n\nSince we have now the grayscale version of our image stored in our buffer object,\nwe need to encode this buffer object back into the \"PNG format\", and save the encoded data into\na new PNG file in our filesystem, so that we can access and see the grayscale version of our image\nthat was produced by our small program.\n\nTo do that, the `libspng` library help us once again by offering an \"encode data to PNG\" type of function,\nwhich is the `spng_encode_image()` function. But in order to \"encode data to PNG\" with `libspng`, we need\nto create a new context object. This new context object must use an \"encoder context\", which\nis identified by the enum value `SPNG_CTX_ENCODER`.\n\nThe `save_png()` function exposed below, summarises all the necessary steps to save the\ngrayscale version of our image into a new PNG file in the filesystem. By default, this\nfunction will save the grayscale image into a file named `pedro_pascal_filter.png` in the CWD.\n\nNotice in this code example that we are using the same image header object (`image_header`) that we have\ncollected previously with the `get_image_header()` function. Remember, this image header object\nis a C struct (`spng_ihdr`) that contains basic information about our PNG file, such as\nthe dimensions of the image, the color model used, etc.\n\nIf we wanted to save a very different image in this new PNG file, e.g. an image\nwith different dimensions, or, an image that uses a different color model, a different bit depth, etc.\nwe would have to create a new image header (`spng_ihdr`) object that describes the properties\nof this new image.\n\nBut we are essentially saving the same image that we have begin with here (the dimensions of\nthe image, the color model, etc. are all still the same). The only difference\nbetween the two images are the colors of the pixels, which are now \"shades of gray\".\nAs consequence, we can safely use the exact same image header data in this new PNG file.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn save_png(image_header: *c.spng_ihdr, buffer: []u8) !void {\n const path = \"pedro_pascal_filter.png\";\n const file_descriptor = c.fopen(path.ptr, \"wb\");\n if (file_descriptor == null) {\n return error.CouldNotOpenFile;\n }\n const ctx = (\n c.spng_ctx_new(c.SPNG_CTX_ENCODER)\n orelse unreachable\n );\n defer c.spng_ctx_free(ctx);\n _ = c.spng_set_png_file(ctx, @ptrCast(file_descriptor));\n _ = c.spng_set_ihdr(ctx, image_header);\n\n const encode_status = c.spng_encode_image(\n ctx,\n buffer.ptr,\n buffer.len,\n c.SPNG_FMT_PNG,\n c.SPNG_ENCODE_FINALIZE\n );\n if (encode_status != 0) {\n return error.CouldNotEncodeImage;\n }\n if (c.fclose(file_descriptor) != 0) {\n return error.CouldNotCloseFileDescriptor;\n }\n}\n\ntry save_png(&image_header, buffer[0..]);\n```\n:::\n\n\n\n\nAfter we execute this `save_png()` function, we should have a new PNG file\ninside our CWD, named `pedro_pascal_filter.png`. If we open this PNG file,\nwe will see the same image exposed at @fig-pascal-gray.\n\n\n## Building our project\n\nNow that we have written the code, let's discuss how can we build/compile this project.\nTo do that, I'm going to create a `build.zig` file in the root directory of our project,\nand start writing the necessary code to compile the project, using the knowledge\nthat we have acquired from @sec-build-system.\n\n\nWe first create the build target for our executable file, that executes our\nZig code. Let's suppose that all of our Zig code was written into a Zig module\nnamed `image_filter.zig`. The `exe` object exposed in the build script below\ndescribes the build target for our executable file.\n\nSince we have used some C code from the `libspng` library in our Zig code,\nwe need to link our Zig code (which is in the `exe` build target) to both\nthe C Standard Library, and, to the `libspng` library. We do that, by calling\nthe `linkLibC()` and `linkSystemLibrary()` methods from our `exe` build target.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const target = b.standardTargetOptions(.{});\n const optimize = b.standardOptimizeOption(.{});\n const exe = b.addExecutable(.{\n .name = \"image_filter\",\n .root_source_file = b.path(\"src/image_filter.zig\"),\n .target = target,\n .optimize = optimize,\n });\n exe.linkLibC();\n // Link to libspng library:\n exe.linkSystemLibrary(\"spng\");\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n\nSince we are using the `linkSystemLibrary()` method, it means that the library\nfiles for `libspng` are searched in your system to be linked with the `exe` build target.\nIf you have not yet built and installed the `libspng` library into your system, this\nlinkage step will likely not work. Because it will not find the library files in your system.\n\nSo, just remember to install `libspng` in your system, if you want to build this project.\nHaving this build script above written, we can finally build our project by\nrunning the `zig build` command in the terminal.\n\n```bash\nzig build\n```\n\n\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 4 - Developing an image filter\n\nIn this chapter we are going to build a new project. The objective of\nthis project is to write a program that applies a filter over an image.\nMore specifically, a \"grayscale filter\", which transforms\nany color image into a grayscale image.\n\nWe are going to use the image displayed in @fig-pascal in this project.\nIn other words, we want to transform this colored image into a grayscale image,\nby using our \"image filter program\" written in Zig.\n\n![A photo of the chilean-american actor Pedro Pascal. Source: Google Images.](../ZigExamples/image_filter/pedro_pascal.png){#fig-pascal}\n\nWe don't need to write a lot of code to build such \"image filter program\". However, we first need\nto understand how digital images work. That is why we begin this chapter\nby explaining the theory behind digital images and how colors are represented in modern computers.\nWe also give a brief explanation about the PNG (Portable Network Graphics) file format, which is the format used\nin the example images.\n\nAt the end of this chapter, we should have a full example of a program that takes the PNG image displayed in @fig-pascal\nas input, and writes a new image to the current working directory that is the grayscale version of this input image.\nThis grayscale version of @fig-pascal is exposed in @fig-pascal-gray.\nYou can find the full source code of this small project at the `ZigExamples/image_filter`\n[folder at the official repository of this book](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/image_filter)[^img-filter-folder].\n\n\n![The grayscale version of the photo.](../ZigExamples/image_filter/pedro_pascal_filter.png){#fig-pascal-gray}\n\n\n## How we see things? {#sec-eyes}\n\nIn this section, I want to briefly describe to you how we (humans) actually see things with our own eyes.\nI mean, how our eyes work? If you do have a very basic understanding of how our eyes work, you will understand\nmore easily how digital images are made. Because the techniques behind digital images\nwere developed by taking a lot of inspiration from how our human eyes work.\n\nYou can interpret a human eye as a light sensor, or, a light receptor. The eye receives some amount of light as input,\nand it interprets the colors that are present in this \"amount of light\".\nIf no amount of light hits the eye, then, the eye cannot extract color from it, and as result,\nwe end up seeing nothing, or, more precisely, we see complete blackness.\n\nTherefore, everything depends on light. What we actually see are the colors (blue, red, orange, green, purple, yellow, etc.) that\nare being reflected from the light that is hitting our eyes. **Light is the source of all colors!**\nThis is what Isaac Newton discovered on his famous prism experiment[^newton] in the 1660s.\n\n[^newton]: \n\nInside our eyes, we have a specific type of cell called the \"cone cell\".\nOur eye have three different types, or, three different versions of these \"cone cells\".\nEach type of cone cell is very sensitive to a specific spectrum of the light. More specifically,\nto the spectrums that define the colors red, green and blue.\nSo, in summary, our eyes have specific types of cells that\nare highly sensitive to these three colors (red, green and blue).\n\nThese are the cells responsible for perceiving the color present in the light that hits our eyes.\nAs a result, our eyes perceives color as a mixture of these three colors (red, green and blue). By having an amount\nof each one of these three colors, and mixing them together, we can get any other visible color\nthat we want. So every color that we see is perceived as a specific mixture of blues, greens and reds,\nlike 30% of red, plus 20% of green, plus 50% of blue.\n\nWhen these cone cells perceive (or, detect) the colors that are found in the\nlight that is hitting our eyes, these cells produce electrical signals, which are sent to the brain.\nOur brain interprets these electrical signals, and use them to form the image that we are seeing\ninside our head.\n\nBased on what we have discussed here, the bullet points exposed below describes the sequence of events that\ncomposes this very simplified version of how our human eyes work:\n\n1. Light hits our eyes.\n1. The cone cells perceive the colors that are present in this light.\n1. Cone cells produce electrical signals that describes the colors that were perceived in the light.\n1. The electrical signals are sent to the brain.\n1. Brain interprets these signals, and form the image based on the colors identified by these electrical signals.\n\n\n## How digital images work? {#sec-digital-img}\n\nA digital image is a \"digital representation\" of an image that we see with our eyes.\nIn other words, a digital image is a \"digital representation\" of the colors that we see\nand perceive through the light.\nIn the digital world, we have two types of images, which are: vector images and raster images.\nVector images are not described here. So just remember that the content discussed here\n**is related solely to raster images**, and not vector images.\n\nA raster image is a type of digital image that is represented as a 2D (two dimensional) matrix\nof pixels. In other words, every raster image is basically a rectangle of pixels, and each pixel have a particular color.\nSo, a raster image is just a rectangle of pixels, and each of these pixels are displayed in the screen of your computer (or the screen\nof any other device, e.g. laptop, tablet, smartphone, etc.) as a color.\n\n@fig-raster demonstrates this idea. If you take any raster image, and you zoom into it very hard,\nyou will see the actual pixels of the image. JPEG, TIFF and PNG are file formats that are commonly\nused to store raster images.\n\n![Zooming over a raster image to see the pixels. Source: Google Images.](../Figures/imagem-raster.png){#fig-raster}\n\nThe more pixels the image has, the more information and detail we can include in the image.\nThe more accurate, sharp and pretty the image will look. This is why photographic cameras\nusually produce big raster images, with several megapixels of resolution, to include as much detail as possible into the final image.\nAs an example, a digital image with dimensions of 1920 pixels wide and 1080 pixels high, would be a image that\ncontains $1920 \\times 1080 = 2073600$ pixels in total. You could also say that the \"total area\" of the image is\nof 2073600 pixels, although the concept of \"area\" is not really used here in computer graphics.\n\nMost digital images we see in our modern world uses the RGB color model. RGB stands for (red, green and blue).\nSo the color of each pixel in these raster images are usually represented as a mixture of red, green and blue,\njust like in our eyes. That is, the color of each pixel is identified by a set of\nthree different integer values. Each integer value identifies the \"amount\" of each color (red, green and blue).\nFor example, the set `(199, 78, 70)` identifies a color that is more close to red. We have 199 of red, 78 of green,\nand 70 of blue. In contrast, the set `(129, 77, 250)` describes a color that is more close to purple. Et cetera.\n\n\n\n### Images are displayed from top to bottom\n\nThis is not a rule written in stone, but the big majority of digital images are displayed from top\nto bottom and left to right. Most computers screens also follow this pattern. So, the first pixels\nin the image are the ones that are at the top and left corner of the image. You can find a visual representation\nof this logic in @fig-img-display.\n\nAlso notice in @fig-img-display that, because a raster image is essentially a 2D matrix of pixels,\nthe image is organized into rows and columns of pixels. The columns are defined by the horizontal x axis,\nwhile the rows are defined by the vertical y axis.\n\nEach pixel (i.e., the gray rectangles) exposed in @fig-img-display contains a number inside of it.\nThese numbers are the indexes of the pixels. You can notice that the first pixels are in the top and left\ncorner, and also, that the indexes of these pixels \"grow to the sides\", or, in other words, they grow in the direction of the horizontal x axis.\nMost raster images are organized as rows of pixels. Thus, when these digital images are\ndisplayed, the screen display the first row of pixels, then, the second row, then, the third row, etc.\n\n![How the pixels of raster images are displayed.](./../Figures/image-display.png){#fig-img-display}\n\n\n\n\n\n\n### Representing the matrix of pixels in code {#sec-pixel-repr}\n\nOk, we know already that raster images are represented as 2D matrices of pixels.\nBut we do not have a notion of a 2D matrix in Zig. Actually, most low-level languages in general\n(Zig, C, Rust, etc.) do not have such notion.\nSo how can we represent such matrix of pixels in Zig, or any other low-level language?\nThe strategy that most programmers choose in this situation is to just use a normal 1D array to store the values of\nthis 2D matrix. In other words, you just create an normal 1D array, and store all values from both dimensions into this 1D array.\n\nAs an example, suppose we have a very small image of dimensions 4x3.\nSince a raster image is represented as a 2D matrix of pixels, and each pixel\nis represented by 3 \"unsigned 8-bit\" integer values, we have 12 pixels in\ntotal in this image, which are represented by $3 \\times 12 = 36$ integer values.\nTherefore, we need to create an array of 36 `u8` values to store this small image.\n\nThe reason why unsigned 8-bit integer (`u8`) values are used to represent the amounts of each color,\ninstead of any other integer type, is because they take the minimum amount of space as possible, or,\nthe minimum amount of bits as possible. Which helps to reduces the binary size of the image, i.e., the 2D matrix.\nAlso, they convey a good amount of precision and detail about the colors, even though they can represent\na relatively small range (from 0 to 255) of \"color amounts\".\n\nComing back to our initial example of a 4x3 image,\nthe `matrix` object exposed below could be an example of an 1D array that stores\nthe data that represents this 4x3 image.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst matrix = [_]u8{\n 201, 10, 25, 185, 65, 70,\n 65, 120, 110, 65, 120, 117,\n 98, 95, 12, 213, 26, 88,\n 143, 112, 65, 97, 99, 205,\n 234, 105, 56, 43, 44, 216,\n 45, 59, 243, 211, 209, 54,\n};\n```\n:::\n\n\n\n\nThe first three integer values in this array are the color amounts of the first pixel in the image.\nThe next three integers are the colors amounts for the second pixel.\nAnd the sequence goes on in this pattern. Having that in mind, the size of the array that stores\na raster image is usually a multiple of 3. In this case, the array have a size of 36.\n\nI mean, the size of the array is **usually** a multiple of 3, because in specific circumstances,\nit can also be a multiple of 4. This happens when a transparency amount is\nalso included into the raster image. In other words, there are some types of raster images\nthat uses a different color model, which is the RGBA (red, green, blue and alpha)\ncolor model. The \"alpha\" corresponds to an amount of transparency in the pixel.\nSo every pixel in a RGBA image is represented by a red, green, blue and alpha values.\n\nMost raster images uses the standard RGB model, so, for the most part, you will\nsee arrays sizes that are multiples of 3. But some images, especially the ones\nthat are stored in PNG files, might be using the RGBA model, and, therefore, are\nrepresented by an array whose size is a multiple of 4.\n\nIn our case here, the example image of our project (@fig-pascal) is a raster image\nstored in a PNG file, and this specific image is using the RGBA color model. Therefore,\neach pixel in the image is represented by 4 different integer values, and, as consequence,\nto store this image in our Zig code, we need to create an array whose size is a multiple of 4.\n\n\n## The PNG library that we are going to use\n\nLet's begin our project by focusing on writing the necessary Zig code to\nread the data from the PNG file. In other words, we want to read the PNG file exposed\nin @fig-pascal, and parse its data to extract the 2D matrix of pixels that represents the image.\n\nAs we have discussed in @sec-pixel-repr, the image that we are using as example here\nis a PNG file that uses the RGBA color model, and, therefore, each pixel of the image\nis represented by 4 integer values. You can download this image by visiting the `ZigExamples/image_filter`\n[folder at the official repository of this book](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/image_filter)[^img-filter-folder].\nYou can also find in this folder the complete source code of this small project that we\nare developing here.\n\n[^img-filter-folder]: \n\nThere are some C libraries available that we can use to read and parse PNG files.\nThe most famous and used of all is `libpng`, which is the \"official library\" for reading and writing\nPNG files. Although this library is available on most operating system, it's well known\nfor being complex and hard to use.\n\nThat is why, I'm going to use a more modern alternative here in this project, which is the `libspng` library.\nI choose to use this C library here, because it's much, much simpler to use than `libpng`,\nand it also offers very good performance for all operations. You can checkout the\n[official website of the library](https://libspng.org/)[^libspng]\nto know more about it. You will also find there some documentation that might help you to understand and\nfollow the code examples exposed here.\n\n[^libspng]: \n\n\nFirst of all, remember to build and install this `libspng` into your system. Because\nif you don't do this step, the `zig` compiler will not be able to find the files and resources of\nthis library in your computer, and link them with the Zig source code that we are writing together here.\nThere is good information about how to build and install the library at the\n[build section of the library documentation](https://libspng.org/docs/build/)[^lib-build].\n\n[^lib-build]: \n\n\n\n\n## Reading the PNG file\n\nIn order to extract the pixel data from the PNG file, we need to read and decode the file.\nA PNG file is just a binary file written in the \"PNG format\". Luckily, the `libspng` library offers\na function called `spng_decode_image()` that does all this heavy work for us.\n\nNow, since `libspng` is a C library, most of the file and I/O operations in this library are made by using\na `FILE` C pointer. Because of that, is probably a better idea to use the `fopen()` C function\nto open our PNG file, instead of using the `openFile()` method that I introduced in @sec-filesystem.\nThat is why I'm importing the `stdio.h` C header in this project, and using the `fopen()` C function to open the file.\n\nIf you look at the snippet below, you can see that we are:\n\n1. opening the PNG file with `fopen()`.\n1. creating the `libspng` context with `spng_ctx_new()`.\n1. using `spng_set_png_file()` to specify the `FILE` object that reads the PNG file that we are going to use.\n\nEvery operation in `libspng` is made through a \"context object\". In our snippet below, this object is `ctx`.\nAlso, to perform an operation over a PNG file, we need to specify which exact PNG file we are referring to.\nThis is the job of `spng_set_png_file()`. We are using this function to specify the file descriptor\nobject that reads the PNG file that we want to use.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cDefine(\"_NO_CRT_STDIO_INLINE\", \"1\");\n @cInclude(\"stdio.h\");\n @cInclude(\"spng.h\");\n});\n\nconst path = \"pedro_pascal.png\";\nconst file_descriptor = c.fopen(path, \"rb\");\nif (file_descriptor == null) {\n @panic(\"Could not open file!\");\n}\nconst ctx = c.spng_ctx_new(0) orelse unreachable;\n_ = c.spng_set_png_file(\n ctx, @ptrCast(file_descriptor)\n);\n```\n:::\n\n\n\n\nBefore we continue, is important to emphasize the following: since we have opened the file with `fopen()`,\nwe have to remember to close the file at the end of the program, with `fclose()`.\nIn other words, after we have done everything that we wanted to do with the PNG file\n`pedro_pascal.png`, we need to close this file, by applying `fclose()` over the file descriptor object.\nWe could use also the `defer` keyword to help us in this task, if we want to.\nThis code snippet below demonstrates this step:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (c.fclose(file_descriptor) != 0) {\n return error.CouldNotCloseFileDescriptor;\n}\n```\n:::\n\n\n\n\n\n\n\n### Reading the image header section\n\nNow, the context object `ctx` is aware of our PNG file `pedro_pascal.png`, because it has access to\na file descriptor object to this file. The first thing that we are going to do is to read the\n\"image header section\" of the PNG file. This \"image header section\" is the section\nof the file that contains some basic information about the PNG file, like, the bit depth of the pixel data\nof the image, the color model used in the file, the dimensions of the image (height and width in number of pixels),\netc.\n\nTo make things easier, I will encapsulate this \"read image header\" operation into a\nnice and small function called `get_image_header()`. All that this function needs to do\nis to call the `spng_get_ihdr()` function. This function from `libspng` is responsible\nfor reading the image header data, and storing it into a C struct named `spng_ihdr`.\nThus, an object of type `spng_ihdr` is a C struct that contains the data from the\nimage header section of the PNG file.\n\nSince this Zig function is receiving a C object (the `libspng` context object) as input, I marked\nthe function argument `ctx` as \"a pointer to the context object\" (`*c.spng_ctx`), following the recommendations\nthat we have discussed in @sec-pass-c-structs.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn get_image_header(ctx: *c.spng_ctx) !c.spng_ihdr {\n var image_header: c.spng_ihdr = undefined;\n if (c.spng_get_ihdr(ctx, &image_header) != 0) {\n return error.CouldNotGetImageHeader;\n }\n\n return image_header;\n}\n\nvar image_header = try get_image_header(ctx);\n```\n:::\n\n\n\n\nAlso notice in this function, that I'm checking if the `spng_get_ihdr()` function call have\nreturned or not an integer value that is different than zero. Most functions from the\n`libspng` library return a code status as result, and the code status \"zero\" means\n\"success\". So any code status that is different than zero means that an error\noccurred while running `spng_get_ihdr()`. This is why I'm returning an error value from\nthe function in case the code status returned by the function is different than zero.\n\n\n### Allocating space for the pixel data\n\nBefore we read the pixel data from the PNG file, we need to allocate enough space to hold this data.\nBut in order to allocate such space, we first need to know how much space we need to allocate.\nThe dimensions of the image are obviously needed to calculate the size of this space. But there are\nother elements that also affect this number, such as the color model used in the image, the bit depth, and others.\n\nAnyway, all of this means that calculating the size of the space that we need, is not a simple task.\nThat is why the `libspng` library offers an utility function named\n`spng_decoded_image_size()` to calculate this size for us. Once again, I'm going\nto encapsulate the logic around this C function into a nice and small Zig function\nnamed `calc_output_size()`. You can see below that this function returns a nice\ninteger value as result, informing the size of the space that we need to allocate.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn calc_output_size(ctx: *c.spng_ctx) !u64 {\n var output_size: u64 = 0;\n const status = c.spng_decoded_image_size(\n ctx, c.SPNG_FMT_RGBA8, &output_size\n );\n if (status != 0) {\n return error.CouldNotCalcOutputSize;\n }\n return output_size;\n}\n```\n:::\n\n\n\n\n\n\nYou might quest yourself what the value `SPNG_FMT_RGBA8` means. This value is actually an enum\nvalue defined in the `spng.h` C header file. This enum is used to identify a \"PNG format\".\nMore precisely, it identifies a PNG file that uses the RGBA color model and 8 bit depth.\nSo, by providing this enum value as input to the `spng_decoded_image_size()` function,\nwe are saying to this function to calculate the size of the decoded pixel data, by considering\na PNG file that follows this \"RGBA color model with 8 bit depth\" format.\n\nHaving this function, we can use it in conjunction with an allocator object, to allocate an\narray of bytes (`u8` values) that is big enough to store the decoded pixel data of the image.\nNotice that I'm using `@memset()` to initialize the entire array to zero.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst output_size = try calc_output_size(ctx);\nvar buffer = try allocator.alloc(u8, output_size);\n@memset(buffer[0..], 0);\n```\n:::\n\n\n\n\n\n### Decoding the image data\n\nNow that we have the necessary space to store the decoded pixel data of the image,\nwe can start to actually decode and extract this pixel data from the image,\nby using the `spng_decode_image()` C function.\n\nThe `read_data_to_buffer()` Zig function exposed below summarises the necessary\nsteps to read this decoded pixel data, and store it into an input buffer.\nNotice that this function is encapsulating the logic around the `spng_decode_image()` function.\nAlso, we are using the `SPNG_FMT_RGBA8` enum value once again to inform the corresponding function,\nthat the PNG image being decoded, uses the RGBA color model and 8 bit depth.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn read_data_to_buffer(ctx: *c.spng_ctx, buffer: []u8) !void {\n const status = c.spng_decode_image(\n ctx,\n buffer.ptr,\n buffer.len,\n c.SPNG_FMT_RGBA8,\n 0\n );\n\n if (status != 0) {\n return error.CouldNotDecodeImage;\n }\n}\n```\n:::\n\n\n\n\nHaving this function at hand, we can apply it over our context object, and also, over\nthe buffer object that we have allocated in the previous section to hold the decoded pixel data\nof the image:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry read_data_to_buffer(ctx, buffer[0..]);\n```\n:::\n\n\n\n\n\n### Looking at the pixel data\n\nNow that we have the pixel data stored in our \"buffer object\", we can take\na quick look at the bytes. In the example below, we are looking at the first\n12 bytes in the decoded pixel data.\n\nIf you take a close look at these values, you might notice that every 4 bytes\nin the sequence is 255. Which, coincidentally is the maximum possible integer value\nto be represented by a `u8` value. So, if the range from 0 to 255, which is the range\nof integer values that can be represented by an `u8` value, can be represented as a scale from 0% to 100%,\nthese 255 values are essentially 100% in that scale.\n\nIf you recall from @sec-pixel-repr, I have\ndescribed in that section that our `pedro_pascal.png` PNG file uses the RGBA color model,\nwhich adds an alpha (or transparency) byte to each pixel in the image.\nAs consequence, each pixel in the image is represented by 4 bytes. Since we are looking\nhere are the first 12 bytes in the image, it means that we are looking at the data from\nthe first $12 / 4 = 3$ pixels in the image.\n\nSo, based on how these first 12 bytes (or these 3 pixels) look, with these 255 values at every 4 bytes, we can say that is likely\nthat every pixel in the image have alpha (or transparency) setted to 100%. This might not be true,\nbut, is the most likely possibility. Also, if we look at the image itself, which if your recall is\nexposed in @fig-pascal, we can see that the transparency does not change across the image,\nwhich enforces this theory.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry stdout.print(\"{any}\\n\", .{buffer[0..12]});\n```\n:::\n\n\n\n\n```\n{\n 200, 194, 216, 255, 203, 197,\n 219, 255, 206, 200, 223, 255\n}\n```\n\n\nWe can see in the above result that the first pixel in this image have 200 of red, 194 of green, and 216 of blue.\nHow do I know the order in which the colors appears in the sequence? If you have not guessed that yet,\nis because of the acronym RGB. First RED, then GREEN, then BLUE. If we scale these integer values\naccording to our scale of 0% to 100% (0 to 255), we get 78% of red, 76% of green and 85% of blue.\n\n\n\n## Applying the image filter\n\nNow that we have the data of each pixel in the image, we can focus on applying our image\nfilter over these pixels. Remember, our objective here is to apply a grayscale filter over\nthe image. A grayscale filter is a filter that transforms a colored image into a grayscale image.\n\nThere are different formulas and strategies to transform a colored image into a grayscale image.\nBut all of these different strategies normally involve applying some math over the colors of each pixel.\nIn this project, we are going to use the most general formula, which is exposed below.\nThis formula considers $r$ as the red of the pixel, $g$ as the green, $b$ as the blue, and $p'$ as the\nlinear luminance of the pixel.\n\n$$\n p' = (0.2126 \\times r) + (0.7152 \\times g) + (0.0722 \\times b)\n$${#eq-grayscale}\n\nThis @eq-grayscale is the formula to calculate the linear luminance of a pixel. It's worth noting that this formula\nworks only for images whose pixels are using the sRGB color space, which is the standard color space\nfor the web. Thus, ideally, all images on the web should use this color space. Luckily,\nthis is our case here, i.e., the `pedro_pascal.png` image is using this sRGB color space, and, as consequence,\nwe can use the @eq-grayscale. You can read more about this formula at the Wikipedia page for grayscale [@wiki_grayscale].\n\nThe `apply_image_filter()` function exposed below summarises the necessary steps to\napply @eq-grayscale over the pixels in the image. We just apply this function\nover our buffer object that contains our pixel data, and, as result, the pixel\ndata stored in this buffer object should now represent the grayscale version of our image.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn apply_image_filter(buffer:[]u8) !void {\n const len = buffer.len;\n const red_factor: f16 = 0.2126;\n const green_factor: f16 = 0.7152;\n const blue_factor: f16 = 0.0722;\n var index: u64 = 0;\n while (index < len) : (index += 4) {\n const rf: f16 = @floatFromInt(buffer[index]);\n const gf: f16 = @floatFromInt(buffer[index + 1]);\n const bf: f16 = @floatFromInt(buffer[index + 2]);\n const y_linear: f16 = (\n (rf * red_factor) + (gf * green_factor)\n + (bf * blue_factor)\n );\n buffer[index] = @intFromFloat(y_linear);\n buffer[index + 1] = @intFromFloat(y_linear);\n buffer[index + 2] = @intFromFloat(y_linear);\n }\n}\n\ntry apply_image_filter(buffer[0..]);\n```\n:::\n\n\n\n\n\n\n## Saving the grayscale version of the image\n\nSince we have now the grayscale version of our image stored in our buffer object,\nwe need to encode this buffer object back into the \"PNG format\", and save the encoded data into\na new PNG file in our filesystem, so that we can access and see the grayscale version of our image\nthat was produced by our small program.\n\nTo do that, the `libspng` library help us once again by offering an \"encode data to PNG\" type of function,\nwhich is the `spng_encode_image()` function. But in order to \"encode data to PNG\" with `libspng`, we need\nto create a new context object. This new context object must use an \"encoder context\", which\nis identified by the enum value `SPNG_CTX_ENCODER`.\n\nThe `save_png()` function exposed below, summarises all the necessary steps to save the\ngrayscale version of our image into a new PNG file in the filesystem. By default, this\nfunction will save the grayscale image into a file named `pedro_pascal_filter.png` in the CWD.\n\nNotice in this code example that we are using the same image header object (`image_header`) that we have\ncollected previously with the `get_image_header()` function. Remember, this image header object\nis a C struct (`spng_ihdr`) that contains basic information about our PNG file, such as\nthe dimensions of the image, the color model used, etc.\n\nIf we wanted to save a very different image in this new PNG file, e.g. an image\nwith different dimensions, or, an image that uses a different color model, a different bit depth, etc.\nwe would have to create a new image header (`spng_ihdr`) object that describes the properties\nof this new image.\n\nBut we are essentially saving the same image that we have begin with here (the dimensions of\nthe image, the color model, etc. are all still the same). The only difference\nbetween the two images are the colors of the pixels, which are now \"shades of gray\".\nAs consequence, we can safely use the exact same image header data in this new PNG file.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn save_png(image_header: *c.spng_ihdr, buffer: []u8) !void {\n const path = \"pedro_pascal_filter.png\";\n const file_descriptor = c.fopen(path.ptr, \"wb\");\n if (file_descriptor == null) {\n return error.CouldNotOpenFile;\n }\n const ctx = (\n c.spng_ctx_new(c.SPNG_CTX_ENCODER)\n orelse unreachable\n );\n defer c.spng_ctx_free(ctx);\n _ = c.spng_set_png_file(ctx, @ptrCast(file_descriptor));\n _ = c.spng_set_ihdr(ctx, image_header);\n\n const encode_status = c.spng_encode_image(\n ctx,\n buffer.ptr,\n buffer.len,\n c.SPNG_FMT_PNG,\n c.SPNG_ENCODE_FINALIZE\n );\n if (encode_status != 0) {\n return error.CouldNotEncodeImage;\n }\n if (c.fclose(file_descriptor) != 0) {\n return error.CouldNotCloseFileDescriptor;\n }\n}\n\ntry save_png(&image_header, buffer[0..]);\n```\n:::\n\n\n\n\nAfter we execute this `save_png()` function, we should have a new PNG file\ninside our CWD, named `pedro_pascal_filter.png`. If we open this PNG file,\nwe will see the same image exposed in @fig-pascal-gray.\n\n\n## Building our project\n\nNow that we have written the code, let's discuss how can we build/compile this project.\nTo do that, I'm going to create a `build.zig` file in the root directory of our project,\nand start writing the necessary code to compile the project, using the knowledge\nthat we have acquired from @sec-build-system.\n\n\nWe first create the build target for our executable file, that executes our\nZig code. Let's suppose that all of our Zig code was written into a Zig module\nnamed `image_filter.zig`. The `exe` object exposed in the build script below\ndescribes the build target for our executable file.\n\nSince we have used some C code from the `libspng` library in our Zig code,\nwe need to link our Zig code (which is in the `exe` build target) to both\nthe C Standard Library, and, to the `libspng` library. We do that, by calling\nthe `linkLibC()` and `linkSystemLibrary()` methods from our `exe` build target.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const target = b.standardTargetOptions(.{});\n const optimize = b.standardOptimizeOption(.{});\n const exe = b.addExecutable(.{\n .name = \"image_filter\",\n .root_source_file = b.path(\"src/image_filter.zig\"),\n .target = target,\n .optimize = optimize,\n });\n exe.linkLibC();\n // Link to libspng library:\n exe.linkSystemLibrary(\"spng\");\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n\nSince we are using the `linkSystemLibrary()` method, it means that the library\nfiles for `libspng` are searched in your system to be linked with the `exe` build target.\nIf you have not yet built and installed the `libspng` library into your system, this\nlinkage step will likely not work. Because it will not find the library files in your system.\n\nSo, just remember to install `libspng` in your system, if you want to build this project.\nHaving this build script above written, we can finally build our project by\nrunning the `zig build` command in the terminal.\n\n```bash\nzig build\n```\n", + "supporting": [ + "13-image-filter_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/14-threads/execute-results/html.json b/_freeze/Chapters/14-threads/execute-results/html.json index 391ecd93..e68da4ad 100644 --- a/_freeze/Chapters/14-threads/execute-results/html.json +++ b/_freeze/Chapters/14-threads/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "043ca4f316462852f28e8b4d4fe3047b", + "hash": "5330e6bae2255d3ad46893b0641f0683", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Introducing threads and parallelism in Zig {#sec-thread}\n\nThreads are available in Zig through the `Thread` struct from the Zig Standard Library.\nThis struct represents a kernel thread, and it follows a POSIX Thread pattern,\nmeaning that, it works similarly to a thread from the `pthread` C library, which is usually available on any distribution\nof the GNU C Compiler (`gcc`). If you are not familiar with threads, I will give you some theory behind it first, shall we?\n\n\n## What are threads? {#sec-what-thread}\n\nA thread is basically a separate context of execution.\nWe use threads to introduce parallelism into our program,\nwhich in most cases, makes the program run faster, because we have multiple tasks\nbeing performed at the same time, parallel to each other.\n\nPrograms are normally single-threaded by default. Which means that each program\nusually runs on a single thread, or, a single context of execution. When we have only one thread running, we have no\nparallelism. And when we don't have parallelism, the commands are executed sequentially, that is,\nonly one command is executed at a time, one after another. By creating multiple threads inside our program,\nwe start to execute multiple commands at the same time.\n\nPrograms that create multiple threads are very common on the wild. Because many different types\nof applications are well suited for parallelism. Good examples are video and photo-editing applications\n(e.g. Adobe Photoshop or DaVinci Resolve), games (e.g. The Witcher 3), and also web browsers\n(e.g. Google Chrome, Firefox, Microsoft Edge, etc).\nFor example, in web browsers, threads are normally used to implement tabs.\nThe tabs in a web browsers usually run as separate threads in the main process of\nthe web browser. That is, each new tab that you open in your web browser,\nusually runs on a separate thread of execution.\n\nBy running each tab in a separate thread, we allow all open tabs in the browser to run at the same time,\nand independently from each other. For example, you might have YouTube, or Spotify, currently opened in\na tab, and you are listening to some podcast in that tab, while, at the same time,\nyou are working in another tab, writing an essay on Google Docs. Even if you are not looking\ninto the YouTube tab, you can still hear the podcast only because this YouTube tab is running in parallel\nwith the other tab where Google Docs is running.\n\nWithout threads, the other alternative would be to run each tab as a completely separate\nprocess in your computer. But that would be a bad choice, because just a few tabs would already consume\ntoo much power and resources from your computer. In other words, is very expensive to create a completely new process,\ncompared to creating a new thread of execution. Also, the chances of you experiencing lag and overhead\nwhile using the browser would be significant. Threads are faster to create, and they also consume\nmuch, much less resources from the computer, especially because they share some resources\nwith the main process.\n\nTherefore, is the use of threads in modern web browsers that allows you to hear the podcast\nat the same time while you are writing something on Google Docs.\nWithout threads, a web browser would probably be limited to just one single tab.\n\nThreads are also well-suited for anything that involves serving requests or orders.\nBecause serving a request takes time, and usually involves a lot of \"waiting time\".\nIn other words, we spend a lot of time in idle, waiting for something to complete.\nFor example, consider a restaurant. Serving orders in a restaurant usually involves\nthe following steps:\n\n1. receive order from the client.\n1. pass the order to the kitchen, and wait for the food to be cooked.\n1. start cooking the food in the kitchen.\n1. when the food is fully cooked deliver this food to the client.\n\nIf you think about the bullet points above, you will notice that one big moment of waiting time\nis present in this whole process, which is while the food is being cooked\ninside the kitchen. While the food is being prepped, both the waiter and the client\nitself are waiting for the food to be ready and delivered.\n\nIf we write a program to represent this restaurant, more specifically, a single-threaded program, then,\nthis program would be very inefficient. Because the program would stay in idle, waiting for a considerable amount\nof time on the \"check if food is ready\" step. Consider the code snippet exposed below that could\npotentially represent such program.\n\nThe problem with this program is the while loop. This program will spend a lot of time\nwaiting on the while loop, doing nothing more than just checking if the food is ready.\nThis is a waste of time. Instead of waiting for something to happen, the waiter\ncould just send the order to the kitchen, and just move on, and continue with receiving\nmore orders from other clients, and sending more orders to the kitchen, instead\nof doing nothing and waiting for the food to be ready.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst order = Order.init(\"Pizza Margherita\", n = 1);\nconst waiter = Waiter.init();\nwaiter.receive_order(order);\nwaiter.ask_kitchen_to_cook();\nvar food_not_ready = true;\nwhile (food_not_ready) {\n food_not_ready = waiter.is_food_ready();\n}\nconst food = waiter.get_food_from_kitchen();\nwaiter.send_food_to_client(food);\n```\n:::\n\n\n\n\nThis is why threads would be a great fit for this program. We could use threads\nto free the waiters from their \"waiting duties\", so they can go on with their\nother tasks, and receive more orders. Take a look at the next example, where I have re-written the above\nprogram into a different program that uses threads to cook and deliver the orders.\n\nYou can see in this program that when a waiter receives a new order\nfrom a client, this waiter executes the `send_order()` function.\nThe only thing that this function does is to create a new thread\nand detaches it. Since creating a thread is a very fast operation,\nthis `send_order()` function returns almost immediately,\nso the waiter spends almost no time worrying about the order, and just\nmove on and tries to get the next order from the clients.\n\nInside the new thread created, the order get's cooked by a chef, and when the\nfood is ready, it is delivered to the client's table.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn cook_and_deliver_order(order: *Order) void {\n const chef = Chef.init();\n const food = chef.cook(order.*);\n chef.deliver_food(food);\n}\nfn send_order(order: Order) void {\n const cook_thread = Thread.spawn(\n .{}, cook_and_deliver_order, .{&order}\n );\n cook_thread.detach();\n}\n\nconst waiter = Waiter.init();\nwhile (true) {\n const order = waiter.get_new_order();\n if (order) {\n send_order(order);\n }\n}\n```\n:::\n\n\n\n\n\n\n## Threads versus processes\n\nWhen we run a program, this program is executed as a *process* in the operating system.\nThis is a one to one relationship, each program or application that you execute\nis a separate process in the operating system. But each program, or each process,\ncan create and contain multiple threads inside of it. Therefore,\nprocesses and threads have a one to many relationship.\n\nThis also means that every thread that we create is always associated with a particular process in our computer.\nIn other words, a thread is always a subset (or a children) of an existing process.\nAll threads share some of the resources associated with the process from which they were created.\nAnd because threads share resources with the process, they are very good for making communication\nbetween tasks easier.\n\nFor example, suppose that you were developing a big and complex application\nthat would be much simpler if you could split it in two, and make these two separate pieces talk\nwith each other. Some programmers opt to effectively write these two pieces of the codebase as two\ncompletely separate programs, and then, they use IPC (*inter-process communication*) to make these\ntwo separate programs/processes talk to each other, and make them work together.\n\nHowever, some programmers find IPC hard to deal with, and, as consequence,\nthey prefer to write one piece of the codebase as the \"main part of the program\",\nor, as the part of the code that runs as the process in the operating system,\nwhile the other piece of the codebase is written as a task to be executed in\na new thread. A process and a thread can easily comunicate with each other\nthrough both control flow, and also, through data, because they share and have\naccess to the same standard file descriptors (`stdout`, `stdin`, `stderr`), and also to the\nsame memory space on the heap and global data section.\n\n\nIn more details, each thread that you create have a separate stack frame reserved just for that thread,\nwhich essentially means that each local object that you create inside this thread, is local to that\nthread, i.e. the other threads cannot see this local object. Unless this object that you have created\nis an object that lives on the heap. In other words, if the memory associated with this object\nis on the heap, then, the other threads can potentially access this object.\n\nTherefore, objects that are stored in the stack are local to the thread where they were created.\nBut objects that are stored on the heap are potentially accessible to other threads. All of this means that,\neach thread have its own separate stack frame, but, at the same time, all threads share\nthe same heap, the same standard file descriptors (which means that they share the same `stdout`, `stdin`, `stderr`),\nand the same global data section in the program.\n\n\n\n## Creating a thread\n\nWe create new threads in Zig, by first, importing the `Thread` struct into\nour current Zig module, and then, calling the `spawn()` method of this struct,\nwhich creates (or, \"spawns\") a new thread of execution from our current process.\nThis method have three arguments, which are, respectively:\n\n1. a `SpawnConfig` object, which contains configurations for the spawn process.\n1. the name of the function that is going to be executed (or, that is going to be \"called\") inside this new thread.\n1. a list of arguments (or inputs) to be passed to the function provided in the second argument.\n\nWith these three arguments, you can control how the thread get's created, and also, specify which\nwork (or \"tasks\") will be performed inside this new thread. A thread is just a separate context of execution,\nand we usually create new threads in our code, because we want to perform some work inside this\nnew context of execution. And we specify which exact work, or, which exact steps that are going to be\nperformed inside this context, by providing the name of a function on the second argument of the `spawn()` method.\n\nThus, when this new thread get's created, this function that you provided as input to the `spawn()`\nmethod get's called, or, get's executed inside this new thread. You can control the\narguments, or, the inputs that are passed to this function when it get's called, by providing\na list of arguments (or a list of inputs) on the third argument of the `spawn()` method.\nThese arguments are passed to the function in the same order that they are\nprovided to `spawn()`.\n\nFurthermore, the `SpawnConfig` is a struct object with only two possible fields, or, two possible members, that you\ncan set to tailor the spawn behaviour. These fields are:\n\n- `stack_size`: you can provide an `usize` value to specify the size (in bytes) of the thread's stack frame. By default, this value is: $16 \\times 1024 \\times 1024$.\n- `allocator`: you can provide an allocator object to be used when allocating memory for the thread.\n\nTo use one of these two fields (or, \"configs\") you just have to create a new object of type `SpawnConfig`,\nand provide this object as input to the `spawn()` method. But, if you are not interested in using\none of these configs, and you are ok with using just the defaults, you can just provide an anonymous\nstruct literal (`.{}`) in the place of this `SpawnConfig` argument.\n\nAs our first, and very simple example, consider the code exposed below.\nInside the same program, you can create multiple threads of execution if you want to.\nBut, in this first example, we are creating just a single thread of execution, because\nwe call `spawn()` only once.\n\nAlso, notice in this example that we are executing the function `do_some_work()`\ninside the new thread. Since this function receives no inputs, because it has\nno arguments, we have passed an empty list in this instance, or, more precisely,\nan empty and anonymous struct (`.{}`) in the third argument of `spawn()`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Thread = std.Thread;\nfn do_some_work() !void {\n _ = try stdout.write(\"Starting the work.\\n\");\n std.time.sleep(100 * std.time.ns_per_ms);\n _ = try stdout.write(\"Finishing the work.\\n\");\n}\n\npub fn main() !void {\n const thread = try Thread.spawn(.{}, do_some_work, .{});\n thread.join();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nStarting the work.Finishing the work.\n```\n\n\n:::\n:::\n\n\n\n\nNotice the use of `try` when calling the `spawn()` method. This means\nthat this method can return an error in some circumstances. One circumstance\nin particular is when you attempt to create a new thread, when you have already\ncreated too much (i.e. you have exceeded the quota of concurrent threads in your system).\n\nBut, if the new thread is successfully created, the `spawn()` method returns a handler\nobject (which is just an object of type `Thread`) to this new thread. You can use\nthis handler object to effectively control all aspects of the thread.\n\nWhen the thread get's created, the function that you provided as input to `spawn()`\nget's invoked (i.e. get's called) to start the execution on this new thread.\nIn other words, everytime you call `spawn()`, not only a new thread get's created,\nbut also, the \"start work button\" of this thread get's automatically pressed.\nSo the work being performed in this thread starts at the moment that the thread is created.\nThis is similar to how `pthread_create()` from the `pthreads` library in C works,\nwhich also starts the execution at the moment that the thread get's created.\n\n\n## Returning from a thread\n\nWe have learned on the previous section that the execution of the thread starts at the moment\nthat the thread get's created. Now, we will learn how to \"join\" or \"detach\" a thread in Zig.\n\"Join\" and \"detach\" are operations that control how the thread returns to\nthe main thread, or, to the main process in our program.\n\nWe perform these operations by using the methods `join()` and `detach()` from the thread handler object.\nEvery thread that you create can be marked as either *joinable* or *detached* [@linux_pthread_create].\nYou can turn a thread into a *detached* thread by calling the `detach()` method\nfrom the thread handler object. But if you call the `join()` method instead, then, this thread\nbecomes a *joinable* thread.\n\nA thread cannot be both *joinable* and *detached*. Which in general means\nthat you cannot call both `join()` and `detach()` on the same thread.\nBut a thread must be one of the two, meaning that, you should always call\neither `join()` or `detach()` over a thread. If you don't call\none of these two methods over your thread, you introduce undefined behaviour into your program,\nwhich is described at @sec-not-call-join-detach.\n\nNow, let's describe what each of these two methods do to your thread.\n\n\n### Joining a thread\n\nWhen you join a thread, you are essentially saying: \"Hey! Could you please wait for the thread to finish,\nbefore you continue with your execution?\". For example, if we comeback to our first and simpliest example\nof a thread in Zig, in that example we have created a single thread inside the `main()` function of our program,\nand just called `join()` over this thread at the end. This section of the code example is reproduced below.\n\nBecause we are joining this new thread inside the `main()`'s scope, it means that the\nexecution of the `main()` function is temporarily stopped, to wait for the execution of the thread\nto finish. That is, the execution of `main()` stops temporarily at the line where `join()` get's called,\nand it will continue only after the thread has finished its tasks.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn main() !void {\n const thread = try Thread.spawn(.{}, do_some_work, .{});\n thread.join();\n}\n```\n:::\n\n\n\n\nBecause we have joined this new thread inside the `main()` scope, we have a\nguarantee that this new thread will finish before the end of the execution of `main()`.\nBecause it is guaranteed that `main()` will wait for the thread to finish its tasks.\n\nIn the example above, there are no more expressions after the `join()` call. We just have the end\nof the `main()`'s scope, and, therefore, the execution of our program just ends after the thread finishes its tasks,\nsince there is nothing more to do. But what if we had more stuff to do after the join call?\n\nTo demonstrate this other possibility, consider the next example exposed\nbelow. Here, we create a `print_id()` function, that just receives an id\nas input, and prints it to `stdout`. In this example, we are creating two\nnew threads, one after another. Then, we join the first thread, then,\nwe wait for two whole seconds, then, at last, we join the second thread.\n\nThe idea behind this example is that the last `join()` call is executed\nonly after the first thread finishes its task (i.e. the first `join()` call),\nand also, after the two seconds of delay. If you compile and run this\nexample, you will notice that most messages are quickly printed to `stdout`,\ni.e. they appear almost instantly on your screen.\nHowever, the last message (\"Joining thread 2\") takes around 2 seconds to appear\nin the screen.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_id(id: *const u8) !void {\n try stdout.print(\"Thread ID: {d}\\n\", .{id.*});\n}\n\npub fn main() !void {\n const id1: u8 = 1;\n const id2: u8 = 2;\n const thread1 = try Thread.spawn(.{}, print_id, .{&id1});\n const thread2 = try Thread.spawn(.{}, print_id, .{&id2});\n\n _ = try stdout.write(\"Joining thread 1\\n\");\n thread1.join();\n std.time.sleep(2 * std.time.ns_per_s);\n _ = try stdout.write(\"Joining thread 2\\n\");\n thread2.join();\n}\n```\n:::\n\n\n\n\n```\nThread ID: Joining thread 1\n1\nThread ID: 2\nJoining thread 2\n```\n\nThis demonstrates that both threads finish their work (i.e. printing the IDs)\nvery fast, before the two seconds of delay end. Because of that, the last `join()` call\nreturns pretty much instantly. Because when this last `join()` call happens, the second\nthread have already finished its task.\n\nNow, if you compile and run this example, you will also notice that, in some cases,\nthe messages intertwine with each other. In other words, you might see\nthe message \"Joining thread 1\" inserted in the middle of the message \"Thread 1\",\nor vice-versa. This happens because:\n\n- the threads are executing basically at the same time as the main process of the program (i.e. the `main()` function).\n- the threads share the same `stdout` from the main process of the program, which means that the messages that the threads produce are sent to exact same place as the messages produced by the main process.\n\nBoth of these points were described previously at @sec-what-thread.\nSo the messages might get intertwined because they are being produced and\nsent to the same `stdout` roughly at the same time.\nAnyway, when you call `join()` over a thread, the current process will wait\nfor the thread to finish before it continues, and, when the thread does finishes its\ntask, the resources associated with this thread are automatically freed, and,\nthe current process continues with its execution.\n\n\n### Detaching a thread\n\nWhen you detach a thread, the resources associated with this thread are automatically\nreleased back to the system, without the need for another thread to join with this terminated thread.\n\nIn other words, when you call `detach()` over a thread it's like when your children becomes adults,\ni.e. they become independent from you. A detached thread frees itself, and when this thread finishes its\ntasks, it does not report the results back to you. Thus, you normally mark a thread as *detached*\nwhen you don't need to use the return value of the thread, or, when you don't care about\nwhen exactly the thread finishes its job, i.e. the thread solves everything by itself.\n\nTake the code example below. We create a new thread, detach it, and then, we just\nprint a final message before we end our program. We use the same `print_id()`\nfunction that we have used over the previous examples.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_id(id: *const u8) !void {\n try stdout.print(\"Thread ID: {d}\\n\", .{id.*});\n}\n\npub fn main() !void {\n const id1: u8 = 1;\n const thread1 = try Thread.spawn(.{}, print_id, .{&id1});\n thread1.detach();\n _ = try stdout.write(\"Finish main\\n\");\n}\n```\n:::\n\n\n\n\n```\nFinish main\n```\n\nNow, if you look closely at the output of this code example, you will notice\nthat only the final message in main was printed to the console. The message\nthat was supposed to be printed by `print_id()` did not appear in the console.\nWhy? Is because the main process of our program has finished first,\nbefore the thread was able to say anything.\n\nAnd that is perfectly ok behaviour, because the thread was detached, so, it was\nable to free itself, without the need to wait for the main process.\nIf you ask main to sleep (or \"wait\") for some extra nanoseconds, before it ends, you will likely\nsee the message printed by `print_id()`, because you give enough time for the thread to\nfinish before the main process ends.\n\n\n## Thread pools\n\nThread pools is a very popular programming pattern, which is used especially on servers and daemons processes.\nA thread pool is just a set of threads, or, a \"pool\" of threads. Many programmers like to use this pattern, because it makes\neasier to manage and use multiple threads in your program, instead of manually creating the threads when you need them.\n\nAlso, using thread pools might increase performance as well in your program,\nespecially if your program is constantly creating threads to perform short-lived tasks.\nIn such instance, a thread pool might cause an increase in performance because you do not have be constantly\ncreating and destroying threads all the time, so you don't face a lot of the overhead involved\nin this constant process of creating and destroying threads.\n\nThe main idea behind a thread pool is to have a set of threads already created and ready to perform\ntasks at all times. You create a set of threads at the moment that your program starts, and keep\nthese threads alive while your program runs. Each of these threads will be either performing a task, or,\nwaiting for a task to be assigned.\nEvery time a new task emerges in your program, this task is added to a \"queue of tasks\",\nand the moment that a thread becomes available and ready to perform a new task,\nthis thread takes the next task from the \"queue of tasks\", and it simply performs the task.\n\nThe Zig Standard Library offers a thread pool implementation on the `std.Thread.Pool` struct.\nYou create a new instance of a `Pool` object by providing a `Pool.Options` object\nas input to the `init()` method of this struct. A `Pool.Options` object, is a struct object that contains\nconfigurations for the pool of threads. The most important settings in this struct object are\nthe members `n_jobs` and `allocator`. As the name suggests, the member `allocator` should receive an allocator object,\nwhile the member `n_jobs` specifies the number of threads to be created and maintained in this pool.\n\nConsider the example exposed below, that demonstrates how can we create a new thread pool object.\nHere, we create a `Pool.Options` object that contains\na general purpose allocator object, and also, the `n_jobs` member was set to 4, which\nmeans that the thread pool will create and use 4 threads.\n\nAlso notice that the `pool` object was initially set to `undefined`. This allow us\nto initially declare the thread pool object, but not properly instantiate the\nunderlying memory of the object. You have to initially declare your thread pool object\nby using `undefined` like this, because the `init()` method of `Pool` needs\nto have an initial pointer to properly instantiate the object.\n\nSo, just remember to create your thread pool object by using `undefined`, and then,\nafter that, you call the `init()` method over the object.\nYou should also not forget to call the `deinit()` method over the thread pool\nobject, once you are done with it, to release the resources allocated for the thread pool. Otherwise, you will\nhave a memory leak in your program.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Pool = std.Thread.Pool;\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const opt = Pool.Options{\n .n_jobs = 4,\n .allocator = allocator,\n };\n var pool: Pool = undefined;\n _ = try pool.init(opt);\n defer pool.deinit();\n}\n```\n:::\n\n\n\n\nNow that we know how to create `Pool` objects, we have\nto understand how to assign tasks to be executed by the threads in this pool object.\nTo assign a task to be performed by a thread, we need to call the `spawn()` method\nfrom the thread pool object.\n\nThis `spawn()` method works identical to the `spawn()` method from the\n`Thread` object. The method have almost the same arguments as the previous one,\nmore precisely, we don't have to provide a `SpawnConfig` object in this case.\nBut instead of creating a new thread, this `spawn()` method from\nthe thread pool object just register a new task in the internal \"queue of tasks\" to be performed,\nand any available thread in the pool will get this task, and it will simply perform the task.\n\nIn the example below, we are using our previous `print_id()` function once again.\nBut you may notice that the `print_id()` function is a little different this time,\nbecause now we are using `catch` instead of `try` in the `print()` call.\nCurrently, the `Pool` struct only supports functions that don't return errors\nas tasks. Thus, when assigning tasks to threads in a thread pool, is essential to use functions\nthat don't return errors. That is why we are using `catch` here, so that the\n`print_id()` function don't return an error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_id(id: *const u8) void {\n _ = stdout.print(\"Thread ID: {d}\\n\", .{id.*})\n catch void;\n}\nconst id1: u8 = 1;\nconst id2: u8 = 2;\ntry pool.spawn(print_id, .{&id1});\ntry pool.spawn(print_id, .{&id2});\n```\n:::\n\n\n\n\nThis limitation should probably not exist, and, in fact, it is already on the radar of the\nZig team to fix this issue, and it is being tracked on an [open issue](https://github.com/ziglang/zig/issues/18810)[^issue].\nSo, if you do need to provide a function that might return an error as the task\nto be performed by the threads in the thread pool, then, you are either limited to:\n\n- implementing your own thread pool that does not have this limitation.\n- wait for the Zig team to actually fix this issue.\n\n[^issue]: \n\n\n\n\n## Mutexes\n\nMutexes are a classic component of every thread library. In essence, a mutex is a *Mutually Exclusive Flag*, and this flag\nacts like a type of \"lock\", or as a gate keeper to a particular section of your code. Mutexes are related to thread synchronization,\nmore specifically, they prevent you from having some classic race conditions in your program,\nand, therefore, major bugs and undefined behaviour that are usually difficult to track and understand.\n\nThe main idea behind a mutex is to help us to control the execution of a particular section of the code, and to\nprevent two or more threads from executing this particular section of the code at the same time.\nMany programmers like to compare a mutex to a bathroom door (which usually have a lock).\nWhen a thread locks its own mutex object, it is like if the bathroom door was locked,\nand, therefore, the other people (in this case, the other threads) that wants to use the same bathroom at the same time\nhave to be patient, and simply wait for the other person (or the other thread) to unlock the door and get out of the bathroom.\n\nSome other programmers also like to explain mutexes by using the analogy of \"each person will have their turn to speak\".\nThis is the analogy used on the [*Multithreading Code* video from the Computerphile project](https://www.youtube.com/watch?v=7ENFeb-J75k&ab_channel=Computerphile)[^computerphile].\nImagine if you are in a conversation circle. There is a moderator in this circle, which is the person that decides who\nhave the right to speak at that particular moment. The moderator gives a green card (or some sort of an authorization card) to the person that\nis going to speak, and, as a result, everyone else must be silent and hear this person that has the green card.\nWhen the person finishes talking, it gives the green card back to the moderator, and the moderator decides\nwho is going to talk next, and delivers the green card to that person. And the cycle goes on like this.\n\n[^computerphile]: \n\n\nA mutex acts like the moderator in this conversation circle. The mutex authorizes one single thread to execute a specific section of the code,\nand it also blocks the other threads from executing this same section of the code. If these other threads want to execute this same\npiece of the code, they are forced to wait for the the authorized thread to finish first.\nWhen the authorized thread finishes executing this code, the mutex authorizes the next thread to execute this code,\nand the other threads are still blocked. Therefore, a mutex is like a moderator that does a \"each\nthread will have their turn to execute this section of the code\" type of control.\n\n\nMutexes are especially used to prevent data race problems from happening. A data race problem happens when two or more threads\nare trying to read from or write to the same shared object at the same time.\nSo, when you have an object that is shared will all threads, and, you want to avoid two or more threads from\naccessing this same object at the same time, you can use a mutex to lock the part of the code that access this specific object.\nWhen a thread tries to run this code that is locked by a mutex, this thread stops its execution,\nand patiently waits for this section of the codebase to be unlocked to continue.\n\nNotice that mutexes are normally used to lock areas of the codebase that access/modify data that is **shared** with all threads,\ni.e. objects that are either stored in the global data section, or, in the heap space of your program.\nSo mutexes are not normally used on areas of the codebase that access/modify objects that are local to the thread.\n\n\n\n### Critical section {#sec-critical-section}\n\nCritical section is a concept commonly associated with mutexes and thread synchronization.\nIn essence, a critical section is the section of the program that a thread access/modify a shared resource\n(i.e. an object, a file descriptor, something that all threads have access to). In other words,\na critical section is the section of the program where race conditions might happen, and, therefore,\nwhere undefined behaviour can be introduced into the program.\n\nWhen we use mutexes in our program, the critical section defines the area of the codebase that we want to lock.\nSo we normally lock the mutex object at the beginning of the critical section,\nand then, we unlock it at the end of the critical section.\nThe two bullet points exposed below comes from the \"Critical Section\" article from GeekFromGeeks,\nand they summarise well the role that a critical section plays in the thread synchronization problem [@geeks_critical_section].\n\n\n1. The critical section must be executed as an atomic operation, which means that once one thread or process has entered the critical section, all other threads or processes must wait until the executing thread or process exits the critical section. The purpose of synchronization mechanisms is to ensure that only one thread or process can execute the critical section at a time.\n1. The concept of a critical section is central to synchronization in computer systems, as it is necessary to ensure that multiple threads or processes can execute concurrently without interfering with each other. Various synchronization mechanisms such as semaphores, mutexes, monitors, and condition variables are used to implement critical sections and ensure that shared resources are accessed in a mutually exclusive manner.\n\n\n### Atomic operations {#sec-atomic-operation}\n\nYou will also see the term \"atomic operation\" a lot when reading about threads, race conditions and mutexes.\nIn summary, an operation is categorized as \"atomic\", when there is no way to happen a context switch in\nthe middle of this operation. In other words, this operation is always done from beginning to end, without interruptions\nof another process or operation in the middle of its execution phase.\n\nNot many operations today are atomic. But why atomic operations matters here? Is because data races\n(which is a type of a race condition) cannot happen on operations that are atomic.\nSo if a particular line in your code performs an atomic operation, then, this line will never\nsuffer from a data race problem. Therefore, programmers sometimes use an atomic operation\nto protect themselves from data race problems in their code.\n\nWhen you have an operation that is compiled into just one single assembly instruction, this operation might be atomic,\nbecause it is just one assembly instruction. But this is not guaranteed. This is usually true for old CPU architectures\n(such as `x86`). But nowadays, most assembly instructions in modern CPU architectures turn into multiple micro-tasks,\nwhich inherently makes the operation not atomic anymore, even though it has just one single assembly instruction.\n\nThe Zig Standard Library offers some atomic functionality at the `std.atomic` module.\nIn this module, you will find a public and generic function called `Value()`. With this function we create an \"atomic object\", which is\na value that contains some native atomic operations, most notably, a `load()` and a `fetchAdd()` operation.\nIf you have experience with multithreading in C++, you probably have recognized this pattern. So yes, this generic\n\"atomic object\" in Zig is essentially identical to the template struct `std::atomic` from the C++ Standard Library.\nIs important to emphasize that only primitive data types (i.e. the types presented at @sec-primitive-data-types)\nare supported by these atomic operations in Zig.\n\n\n\n\n\n### Data races and race conditions\n\nTo understand why mutexes are used, we need to understand better the problem that they seek\nto solve, which can be summarized into data races problems. A data race problem is a type of a race condition,\nwhich happens when one thread is accessing a particular memory location (i.e. a particular shared object) at the same\ntime that another thread is trying to write/save new data into this same memory location (i.e. the same shared object).\n\nWe can simply define a race condition as any type of bug in your program that is based\non a \"who get's there first\" problem. A data race problem is a type of a race condition, because it occurs when two or more parties\nare trying to read and write into the same memory location at the same time, and, therefore, the end result of this operation\ndepends completely on who get's to this memory location first.\nAs consequence, a program that have a data race problem will likely produce a different result each time that we execute it.\n\nThus, race conditions produce undefined behaviour and unpredictability because the program produces\na different answer in each time that a different person get's to the target location first than the others.\nAnd we have no easy way to either predict or control who is getting to this target location first.\nIn other words, in each execution of your program, you get a different answer, because a different person,\nor, a different function, or, a different part of the code is finishing its tasks first than the others.\n\nAs an example, consider the code snippet exposed below. In this example, we create a global counter\nvariable, and we also create an `increment()` function, whose job is to just increment this global counter\nvariable in a for loop.\n\nSince the for loop iterates 1 hundred thousand times, and, we create two separate threads\nin this code example, what number do you expect to see in the final message printed to `stdout`?\nThe answer should be 2 hundred thousand. Right? Well, in theory, this program was supposed\nto print 2 hundred thousand at the end, but in practice, every time that I execute this program\nI get a different answer.\n\nIn the example exposed below, you can see that this time the end\nresult was 117254, instead of the expected 200000. The second time I have executed this program,\nI got the number 108592 as result. So the end result of this program is varying, but it never gets\nto the expected 200000 that we want.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// Global counter variable\nvar counter: usize = 0;\n// Function to increment the counter\nfn increment() void {\n for (0..100000) |_| {\n counter += 1;\n }\n}\n\npub fn main() !void {\n const thr1 = try Thread.spawn(.{}, increment, .{});\n const thr2 = try Thread.spawn(.{}, increment, .{});\n thr1.join();\n thr2.join();\n try stdout.print(\"Couter value: {d}\\n\", .{counter});\n}\n```\n:::\n\n\n\n\n```\nCouter value: 117254\n```\n\n\nWhy this is happening? The answer is: because this program contains a data race problem.\nThis program would print the correct number 200000, if, and only if the first thread finishes\nits tasks before the second thread starts to execute. But that is very unlikely to happen.\nBecause the process of creating the thread is too fast, and therefore, both threads starts to execute roughly\nat the same time. If you change this code to add some nanoseconds of sleep between the first and the second calls to `spawn()`,\nyou will increase the chances of the program producing the \"correct result\".\n\nSo the data race problem happens, because both threads are reading and writing to the same\nmemory location at roughly the same time. In this example, each thread is essentially performing\nthree basic operations at each iteration of the for loop, which are:\n\n1. reading the current value of `count`.\n1. incrementing this value by 1.\n1. writing the result back into `count`.\n\nIdeally, a thread B should read the value of `count`, only after the other thread A has finished\nwriting the incremented value back into the `count` object. Therefore, in the ideal scenario, which is demonstrated\nat @tbl-data-race-ideal, the threads should work in sync with each other. But the reality is that these\nthreads are out of sync, and because of that, they suffer from a data race problem, which is demonstrated\nat @tbl-data-race-not.\n\nNotice that, in the data race scenario (@tbl-data-race-not), the read performed by a thread B happens\nbefore the write operation of thread A, and that ultimately leads to wrong results at the end of the program.\nBecause when the thread B reads the value from the `count` variable, the thread A is still processing\nthe initial value from `count`, and it did not write the new and incremented value into `count` yet. So what\nhappens is that thread B ends up reading the same initial value (the \"old\" value) from `count`, instead of\nreading the new and incremented version of this value that would be calculated by thread A.\n\n\n::: {#tbl-data-race-ideal}\n\n| Thread 1 | Thread 2 | Integer value |\n|-------------|-------------|---------------|\n| read value | | 0 |\n| increment | | 1 |\n| write value | | 1 |\n| | read value | 1 |\n| | increment | 2 |\n| | write value | 2 |\n\n: An ideal scenario for two threads incrementing the same integer value\n:::\n\n::: {#tbl-data-race-not}\n\n| Thread 1 | Thread 2 | Integer value |\n|-------------|-------------|---------------|\n| read value | | 0 |\n| | read value | 0 |\n| increment | | 1 |\n| | increment | 1 |\n| write value | | 1 |\n| | write value | 1 |\n\n: A data race scenario when two threads are incrementing the same integer value\n:::\n\n\nIf you think about these diagrams exposed in form of tables, you will notice that they relate back to our discussion of atomic operations\nat @sec-atomic-operation. Remember, atomic operations are operations that the CPU executes\nfrom beginning to end, without interruptions from other threads or processes. So,\nthe scenario exposed at @tbl-data-race-ideal do not suffer from a data race, because\nthe operations performed by thread A are not interrupted in the middle by the operations\nfrom thread B.\n\nIf we also think about the discussion of critical section from @sec-critical-section, we can identify\nthe section that representes the critical section of the program, which is the section that is vulnerable\nto data race conditions. In this example, the critical section of the program is the line where we increment\nthe `counter` variable (`counter += 1`). So, ideally, we want to use a mutex, and lock right before this line, and then,\nunlock right after this line.\n\n\n\n\n### Using mutexes in Zig\n\nNow that we know the problem that mutexes seek to solve, we can learn how to use them in Zig.\nMutexes in Zig are available through the `std.Thread.Mutex` struct from the Zig Standard Library.\nIf we take the same code example from the previous example, and improve it with mutexes, to solve\nour data race problem, we get the code example exposed below.\n\nNotice that we had this time to alter the `increment()` function to receive a pointer to\nthe `Mutex` object as input. All that we need to do, to make this program safe against\ndata race problems, is to call the `lock()` method at the beginning of\nthe critical section, and then, call `unlock()` at the end of the critical section.\nNotice that the output of this program is now the correct number of 200000.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Thread = std.Thread;\nconst Mutex = std.Thread.Mutex;\nvar counter: usize = 0;\nfn increment(mutex: *Mutex) void {\n for (0..100000) |_| {\n mutex.lock();\n counter += 1;\n mutex.unlock();\n }\n}\n\npub fn main() !void {\n var mutex: Mutex = .{};\n const thr1 = try Thread.spawn(.{}, increment, .{&mutex});\n const thr2 = try Thread.spawn(.{}, increment, .{&mutex});\n thr1.join();\n thr2.join();\n try stdout.print(\"Couter value: {d}\\n\", .{counter});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nCouter value: 200000\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## Read/Write locks\n\nMutexes are normally used when is always not safe to have two or more threads running the same\npiece of code at the same time. In contrast, read/write locks are normally used in situations\nwhere you have a mixture of scenarios, i.e. there are some pieces of the codebase that are safe\nto run in parallel, and other pieces that are not safe.\n\nFor example, suppose that you have multiple threads that uses the same shared file in the filesystem to store some configurations, or,\nstatistics. If two or more threads try to read the data from this same file at the same time, nothing bad happens.\nSo this part of the codebase is perfectly safe to be executed in parallel, with multiple threads reading the same file at the same time.\n\nHowever, if two or more threads try to write data into this same file at the same time, then, we cause some race conditions\nproblems. So this other part of the codebase is not safe to be executed in parallel.\nMore specifically, a thread might end up writing data in the middle of the data written by the other thread.\nThis process of two or more threads writing to the same location, might lead to data corruption.\nThis specific situation is usually called of a *torn write*.\n\nThus, what we can extract from this example is that there is certain types of operations that causes\na race condition, but there are also, other types of operations that do not cause a race condition problem.\nYou could also say that, there are types of operations that are susceptible to race condition problems,\nand there are other types of operations that are not.\n\nA read/write lock is a type of lock that acknowledges the existance of this specific scenario, and you can\nuse this type of lock to control which parts of the codebase are safe to run in parallel, and which parts are not safe.\n\n\n\n### Exclusive lock vs shared lock\n\nTherefore, a read/write lock is a little different from a mutex. Because a mutex is always an *exclusive lock*, meaning that, only\none thread is allowed to execute at all times. With an exclusive lock, the other threads are always \"excluded\",\ni.e. they are always blocked from executing. But in a read/write lock, the other threads might be authorized\nto run at the same time, depending on the type of lock that they acquire.\n\nWe have two types of locks in a read/write lock, which are: an exclusive lock and a shared lock. An exclusive lock works exactly the same\nas a mutex, while a shared lock is a lock that does not block the other threads from running at the same time.\nIn the `pthreads` C library, read/write locks are available through the `pthread_rwlock_t` C struct. With\nthis C struct, you can create:\n\n- a \"write lock\", which corresponds to an exclusive lock.\n- a \"read lock\", which corresponds to a shared lock.\n\nThe terminology might be a little different compared to Zig. But the meaning is still the same.\nTherefore, just remember this relationship, write locks are exclusive locks, while read locks are shared locks.\n\nWhen a thread tries to acquire a read lock (i.e. a shared lock), this thread get's the shared lock\nif, and only if another thread does not currently holds a write lock (i.e. an exclusive lock), and also,\nif there are no other threads that are already in the queue,\nwaiting for their turn to acquire a write lock. In other words, the thread in the queue have attempted\nto get a write lock earlier, but this thread was blocked\nbecause there was another thread running that already had a write lock. As consequence, this thread is on the queue to get a write lock,\nand it's currently waiting for the other thread with a write lock to finish its execution.\n\nWhen a thread tries to acquire a read lock, but it fails in acquiring this read lock, either because there is\na thread with a write lock already running, or, because there is a thread in the queue to get a write lock,\nthe execution of this thread is instantly blocked, i.e. paused. This thread will indefinitely attempt to get the\nread lock, and its execution will be unblocked (or unpaused) only after this thread successfully acquires the read lock.\n\nIf you think deeply about this dynamic between read locks versus write locks, you might notice that a read lock is basically a safety mechanism.\nMore specifically, it is a way for us to\nallow a particular thread to run together with the other threads, only when it's safe to. In other words, if there is currently\na thread with a write lock running, then, it is very likely not safe for the thread that is trying to acquire the read lock to run now.\nAs consequence, the read lock protects this thread from running into dangerous waters, and patiently waits for the\n\"write lock\" thread to finishes its tasks before it continues.\n\nOn the other hand, if there are only \"read lock\" (i.e. \"shared lock\") threads currently running\n(i.e. not a single \"write lock\" thread currently exists), then,\nis perfectly safe for this thread that is acquiring the read lock to run in parallel with the other\nthreads. As a result, the read lock just\nallows for this thread to run together with the other threads.\n\nThus, by using read locks (shared locks) in conjunction with write locks (exclusive locks), we can control which regions or sections\nof our multithreaded code is safe to have parallelism, and which sections are not safe to have parallelism.\n\n\n\n\n\n### Using read/write locks in Zig\n\nThe Zig Standard Library supports read/write locks through the `std.Thread.RwLock` module.\nIf you want to a particular thread to acquire a shared lock (i.e. a read lock), you should\ncall the `lockShared()` method from the `RwLock` object. But, if you want for this thread\nto acquire an exclusive lock (i.e. a write lock) instead, then, you should call the\n`lock()` method from the `RwLock` object.\n\nAs with mutexes, we also have to unlock the shared or exclusive locks that we acquire through a read/write lock object,\nonce we are at the end of our \"critical section\". If you have acquired an exclusive lock, then, you unlock\nthis exclusive lock by calling the `unlock()` method from the read/write lock object. In contrast,\nif you have acquired a shared lock instead, then, call `unlockShared()` to unlock this shared lock.\n\nAs a simple example, the snippet exposed below creates three separate threads responsible for reading the\ncurrent value in a `counter` object, and it also creates another thread, responsible for writing\nnew data into the `counter` object (incrementing it, more specifically).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar counter: u32 = 0;\nfn reader(lock: *RwLock) !void {\n while (true) {\n lock.lockShared();\n const v: u32 = counter;\n try stdout.print(\"{d}\", .{v});\n lock.unlockShared();\n std.time.sleep(2 * std.time.ns_per_s);\n }\n}\nfn writer(lock: *RwLock) void {\n while (true) {\n lock.lock();\n counter += 1;\n lock.unlock();\n std.time.sleep(2 * std.time.ns_per_s);\n }\n}\n\npub fn main() !void {\n var lock: RwLock = .{};\n const thr1 = try Thread.spawn(.{}, reader, .{&lock});\n const thr2 = try Thread.spawn(.{}, reader, .{&lock});\n const thr3 = try Thread.spawn(.{}, reader, .{&lock});\n const wthread = try Thread.spawn(.{}, writer, .{&lock});\n\n thr1.join();\n thr2.join();\n thr3.join();\n wthread.join();\n}\n```\n:::\n\n\n\n\n\n## Yielding a thread\n\nThe `Thread` struct supports yielding through the `yield()` method.\nYielding a thread means that the execution of the thread is temporarily stopped,\nand the thread comes back to the end of the queue of priority of the scheduler from\nyour operating system.\n\nThat is, when you yield a thread, you are essentially saying the following to your OS:\n\"Hey! Could you please stop executing this thread for now, and comeback to continue it later?\".\nYou could also interpret this yield operation as: \"Could you please deprioritize this thread,\nto focus on doing other things instead?\".\nSo this yield operation is also a way for you\nto stop a particular thread, so that you can work and prioritize other threads instead.\n\nIs important to say that, yielding a thread is a \"not so common\" thread operation these days.\nIn other words, not many programmers use yielding in production, simply because is hard to use\nthis operation and make it work properly, and also, there\nare better alternatives. Most programmers prefer to use `join()` instead.\nIn fact, most of the times, when you see somebody using this \"yield\" operation in some code example,\nthey are mostly using it to help them debug race conditions in their applications.\nThat is, this \"yield\" operation is mostly used as a debug tool nowadays.\n\nAnyway, if you want to yield a thread, just call the `yield()` method from it, like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nthread.yield();\n```\n:::\n\n\n\n\n\n\n\n\n\n## Common problems in threads\n\n\n\n### Deadlocks\n\nA deadlock occurs when two or more threads are blocked forever,\nwaiting for each other to release a resource. This usually happens when multiple locks are involved,\nand the order of acquiring them is not well managed.\n\nThe code example below demonstrates a deadlock situation. We have two different threads that execute\ntwo different functions (`work1()` and `work2()`) in this example. And we also have two separate\nmutexes. If you compile and run this code example, you will notice that the program just runs indefinitely,\nwithout ending.\n\nWhen we look into the first thread, which executes the `work1()` function, we can\nnotice that this function acquires the `mut1` lock first. Because this is the first operation\nthat is executed inside this thread, which is the first thread created in the program.\nAfter that, the function sleeps for 1 second, to\nsimulate some type of work, and then, the function tries to acquire the `mut2` lock.\n\nOn the other hand, when we look into the second thread, which executes the `work2()` function,\nwe can see that this function acquires the `mut2` lock first. Because when this thread get's created and it tries\nto acquire this `mut2` lock, the first thread is still sleeping on that \"sleep 1 second\" line.\nAfter acquiring `mut2`, the `work2()` function also sleeps for 1 second, to\nsimulate some type of work, and then, the function tries to acquire the `mut1` lock.\n\nThis creates a deadlock situation, because after the \"sleep for 1 second\" line in both threads,\nthe thread 1 is trying to acquire the `mut2` lock, but this lock is currently being used by thread 2.\nHowever, at this moment, the thread 2 is also trying to acquire the `mut1` lock, which is currently\nbeing used by thread 1. Therefore, both threads end up waiting for ever. Waiting for their peer to\nfree the lock that they want to acquire.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar mut1: Mutex = .{}; var mut2: Mutex = .{};\nfn work1() !void {\n mut1.lock();\n std.time.sleep(1 * std.time.ns_per_s);\n mut2.lock();\n _ = try stdout.write(\"Doing some work 1\\n\");\n mut2.unlock(); mut1.unlock();\n}\n\nfn work2() !void {\n mut2.lock();\n std.time.sleep(1 * std.time.ns_per_s);\n mut1.lock();\n _ = try stdout.write(\"Doing some work 1\\n\");\n mut1.unlock(); mut2.unlock();\n}\n\npub fn main() !void {\n const thr1 = try Thread.spawn(.{}, work1, .{});\n const thr2 = try Thread.spawn(.{}, work2, .{});\n thr1.join();\n thr2.join();\n}\n```\n:::\n\n\n\n\n\n### Not calling `join()` or `detach()` {#sec-not-call-join-detach}\n\nWhen you do not call either `join()` or `detach()` over a thread, then, this thread becomes a \"zombie thread\",\nbecause it does not have a clear \"return point\".\nYou could also interpret this as: \"nobody is properly responsible for managing the thread\".\nWhen we don't establish if a thread is either *joinable* or *detached*,\nnobody becomes responsible for dealing with the return value of this thread, and also,\nnobody becomes responsible for clearing (or freeing) the resources associated with this thread.\n\nYou don't want to be in this situation, so remember to always use `join()` or `detach()`\non the threads that you create. When you don't use one of these methods, we lose\ncontrol over the thread, and its resources are never freed\n(i.e. you have leaked resources in the system).\n\n\n### Cancelling or killing a particular thread\n\nWhen we think about the `pthreads` C library, there is a possible way to asynchronously kill or cancel\na thread, which is by sending a `SIGTERM` signal to the thread through the `pthread_kill()` function.\nBut canceling a thread like this is bad. Is dangerously bad. As consequence, the Zig implementation\nof threads does not have a similar function, or, a similar way to asynchronously cancel or kill\na thread.\n\nTherefore, if you want to cancel a thread in the middle of its execution in Zig,\nthen, one good strategy that you can take is to use control flow in conjunction with `join()`.\nMore specifically, you can design your thread around a while loop, that is constantly\nchecking if the thread should continue running.\nIf is time to cancel the thread, we could make the while loop break, and join the thread with the main thread\nby calling `join()`.\n\nThe code example below demonstrates to some extent this strategy.\nHere, we are using control flow to break the while loop, and exit the thread earlier than\nwhat we have initially planned to. This example also demonstrates how can we use\natomic objects in Zig with the `Value()` generic function that we have mentioned at @sec-atomic-operation.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Thread = std.Thread;\nconst stdout = std.io.getStdOut().writer();\nvar running = std.atomic.Value(bool).init(true);\nvar counter: u64 = 0;\nfn do_more_work() void {\n std.time.sleep(2 * std.time.ns_per_s);\n}\nfn work() !void {\n while (running.load(.monotonic)) {\n for (0..10000) |_| { counter += 1; }\n if (counter < 15000) {\n _ = try stdout.write(\n \"Time to cancel the thread.\\n\"\n );\n running.store(false, .monotonic);\n } else {\n _ = try stdout.write(\"Time to do more work.\\n\");\n do_more_work();\n running.store(false, .monotonic);\n }\n }\n}\n\npub fn main() !void {\n const thread = try Thread.spawn(.{}, work, .{});\n thread.join();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nTime to cancel the thread.\n```\n\n\n:::\n:::\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Introducing threads and parallelism in Zig {#sec-thread}\n\nThreads are available in Zig through the `Thread` struct from the Zig Standard Library.\nThis struct represents a kernel thread, and it follows a POSIX Thread pattern,\nmeaning that, it works similarly to a thread from the `pthread` C library, which is usually available on any distribution\nof the GNU C Compiler (`gcc`). If you are not familiar with threads, I will give you some theory behind it first, shall we?\n\n\n## What are threads? {#sec-what-thread}\n\nA thread is basically a separate context of execution.\nWe use threads to introduce parallelism into our program,\nwhich in most cases, makes the program run faster, because we have multiple tasks\nbeing performed at the same time, parallel to each other.\n\nPrograms are normally single-threaded by default. Which means that each program\nusually runs on a single thread, or, a single context of execution. When we have only one thread running, we have no\nparallelism. And when we don't have parallelism, the commands are executed sequentially, that is,\nonly one command is executed at a time, one after another. By creating multiple threads inside our program,\nwe start to execute multiple commands at the same time.\n\nPrograms that create multiple threads are very common in the wild. Because many different types\nof applications are well suited for parallelism. Good examples are video and photo-editing applications\n(e.g. Adobe Photoshop or DaVinci Resolve), games (e.g. The Witcher 3), and also web browsers\n(e.g. Google Chrome, Firefox, Microsoft Edge, etc).\nFor example, in web browsers, threads are normally used to implement tabs.\nThe tabs in a web browsers usually run as separate threads in the main process of\nthe web browser. That is, each new tab that you open in your web browser\nusually runs on a separate thread of execution.\n\nBy running each tab in a separate thread, we allow all open tabs in the browser to run at the same time,\nand independently from each other. For example, you might have YouTube or Spotify currently open in\na tab, and you are listening to some podcast in that tab while at the same time\nworking in another tab, writing an essay on Google Docs. Even if you are not looking\ninto the YouTube tab, you can still hear the podcast only because this YouTube tab is running in parallel\nwith the other tab where Google Docs is running.\n\nWithout threads, the other alternative would be to run each tab as a completely separate\nprocess in your computer. But that would be a bad choice because just a few tabs would already consume\ntoo much power and resources from your computer. In other words, it's very expensive to create a completely new process,\ncompared to creating a new thread of execution. Also, the chances of you experiencing lag and overhead\nwhile using the browser would be significant. Threads are faster to create, and they also consume\nmuch, much less resources from the computer, especially because they share some resources\nwith the main process.\n\nTherefore, it's the use of threads in modern web browsers that allow you to hear the podcast\nat the same time while you are writing something on Google Docs.\nWithout threads, a web browser would probably be limited to just one single tab.\n\nThreads are also well-suited for anything that involves serving requests or orders.\nBecause serving a request takes time, and usually involves a lot of \"waiting time\".\nIn other words, we spend a lot of time in idle, waiting for something to complete.\nFor example, consider a restaurant. Serving orders in a restaurant usually involves\nthe following steps:\n\n1. receive order from the client.\n1. pass the order to the kitchen, and wait for the food to be cooked.\n1. start cooking the food in the kitchen.\n1. when the food is fully cooked deliver this food to the client.\n\nIf you think about the bullet points above, you will notice that one big moment of waiting time\nis present in this whole process, which is while the food is being cooked\ninside the kitchen. While the food is being prepped, both the waiter and the client\nthemselves are waiting for the food to be ready and delivered.\n\nIf we write a program to represent this restaurant, more specifically, a single-threaded program, then\nthis program would be very inefficient. Because the program would stay in idle, waiting for a considerable amount\nof time on the \"check if food is ready\" step. Consider the code snippet exposed below that could\npotentially represent such program.\n\nThe problem with this program is the while loop. This program will spend a lot of time\nwaiting on the while loop, doing nothing more than just checking if the food is ready.\nThis is a waste of time. Instead of waiting for something to happen, the waiter\ncould just send the order to the kitchen, and just move on, and continue with receiving\nmore orders from other clients, and sending more orders to the kitchen, instead\nof doing nothing and waiting for the food to be ready.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst order = Order.init(\"Pizza Margherita\", n = 1);\nconst waiter = Waiter.init();\nwaiter.receive_order(order);\nwaiter.ask_kitchen_to_cook();\nvar food_not_ready = true;\nwhile (food_not_ready) {\n food_not_ready = waiter.is_food_ready();\n}\nconst food = waiter.get_food_from_kitchen();\nwaiter.send_food_to_client(food);\n```\n:::\n\n\n\n\nThis is why threads would be a great fit for this program. We could use threads\nto free the waiters from their \"waiting duties\", so they can go on with their\nother tasks, and receive more orders. Take a look at the next example, where I have re-written the above\nprogram into a different program that uses threads to cook and deliver the orders.\n\nYou can see in this program that when a waiter receives a new order\nfrom a client, this waiter executes the `send_order()` function.\nThe only thing that this function does is to create a new thread\nand detaches it. Since creating a thread is a very fast operation,\nthis `send_order()` function returns almost immediately,\nso the waiter spends almost no time worrying about the order, and just\nmove on and tries to get the next order from the clients.\n\nInside the new thread created, the order gets cooked by a chef, and when the\nfood is ready, it's delivered to the client's table.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn cook_and_deliver_order(order: *Order) void {\n const chef = Chef.init();\n const food = chef.cook(order.*);\n chef.deliver_food(food);\n}\nfn send_order(order: Order) void {\n const cook_thread = Thread.spawn(\n .{}, cook_and_deliver_order, .{&order}\n );\n cook_thread.detach();\n}\n\nconst waiter = Waiter.init();\nwhile (true) {\n const order = waiter.get_new_order();\n if (order) {\n send_order(order);\n }\n}\n```\n:::\n\n\n\n\n\n\n## Threads versus processes\n\nWhen we run a program, this program is executed as a *process* in the operating system.\nThis is a one to one relationship, each program or application that you execute\nis a separate process in the operating system. But each program, or each process,\ncan create and contain multiple threads inside of it. Therefore,\nprocesses and threads have a one to many relationship.\n\nThis also means that every thread that we create is always associated with a particular process in our computer.\nIn other words, a thread is always a subset (or a children) of an existing process.\nAll threads share some of the resources associated with the process from which they were created.\nAnd because threads share resources with the process, they are very good for making communication\nbetween tasks easier.\n\nFor example, suppose that you were developing a big and complex application\nthat would be much simpler if you could split it in two, and make these two separate pieces talk\nwith each other. Some programmers opt to effectively write these two pieces of the codebase as two\ncompletely separate programs, and then, they use IPC (*inter-process communication*) to make these\ntwo separate programs/processes talk to each other, and make them work together.\n\nHowever, some programmers find IPC hard to deal with, and, as consequence,\nthey prefer to write one piece of the codebase as the \"main part of the program\",\nor, as the part of the code that runs as the process in the operating system,\nwhile the other piece of the codebase is written as a task to be executed in\na new thread. A process and a thread can easily comunicate with each other\nthrough both control flow, and also, through data, because they share and have\naccess to the same standard file descriptors (`stdout`, `stdin`, `stderr`), and also to the\nsame memory space on the heap and global data section.\n\n\nIn more details, each thread that you create have a separate stack frame reserved just for that thread,\nwhich essentially means that each local object that you create inside this thread, is local to that\nthread, i.e., the other threads cannot see this local object. Unless this object that you have created\nis an object that lives on the heap. In other words, if the memory associated with this object\nis on the heap, then, the other threads can potentially access this object.\n\nTherefore, objects that are stored in the stack are local to the thread where they were created.\nBut objects that are stored on the heap are potentially accessible to other threads. All of this means that,\neach thread has its own separate stack frame, but, at the same time, all threads share\nthe same heap, the same standard file descriptors (which means that they share the same `stdout`, `stdin`, `stderr`),\nand the same global data section in the program.\n\n\n\n## Creating a thread\n\nWe create new threads in Zig by first importing the `Thread` struct into\nour current Zig module and then calling the `spawn()` method of this struct,\nwhich creates (or \"spawns\") a new thread of execution from our current process.\nThis method has three arguments, which are, respectively:\n\n1. a `SpawnConfig` object, which contains configurations for the spawn process.\n1. the name of the function that is going to be executed (or that is going to be \"called\") inside this new thread.\n1. a list of arguments (or inputs) to be passed to the function provided in the second argument.\n\nWith these three arguments, you can control how the thread gets created, and also, specify which\nwork (or \"tasks\") will be performed inside this new thread. A thread is just a separate context of execution,\nand we usually create new threads in our code because we want to perform some work inside this\nnew context of execution. And we specify which exact work, or which exact steps that are going to be\nperformed inside this context by providing the name of a function as the second argument of the `spawn()` method.\n\nThus, when this new thread gets created, this function that you provided as input to the `spawn()`\nmethod gets called, or gets executed inside this new thread. You can control the\narguments, or the inputs that are passed to this function when it gets called by providing\na list of arguments (or a list of inputs) in the third argument of the `spawn()` method.\nThese arguments are passed to the function in the same order that they are\nprovided to `spawn()`.\n\nFurthermore, the `SpawnConfig` is a struct object with only two possible fields, or, two possible members, that you\ncan set to tailor the spawn behaviour. These fields are:\n\n- `stack_size`: you can provide a `usize` value to specify the size (in bytes) of the thread's stack frame. By default, this value is: $16 \\times 1024 \\times 1024$.\n- `allocator`: you can provide an allocator object to be used when allocating memory for the thread.\n\nTo use one of these two fields (or \"configs\"), you just have to create a new object of type `SpawnConfig`,\nand provide this object as input to the `spawn()` method. But, if you are not interested in using\none of these configs, and you are ok with using just the defaults, you can just provide an anonymous\nstruct literal (`.{}`) in place of this `SpawnConfig` argument.\n\nAs our first, and very simple example, consider the code exposed below.\nInside the same program, you can create multiple threads of execution if you want to.\nBut, in this first example, we are creating just a single thread of execution, because\nwe call `spawn()` only once.\n\nAlso, notice in this example that we are executing the function `do_some_work()`\ninside the new thread. Since this function receives no inputs, because it has\nno arguments, we have passed an empty list in this instance, or more precisely,\nan empty, anonymous struct (`.{}`) in the third argument of `spawn()`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Thread = std.Thread;\nfn do_some_work() !void {\n _ = try stdout.write(\"Starting the work.\\n\");\n std.time.sleep(100 * std.time.ns_per_ms);\n _ = try stdout.write(\"Finishing the work.\\n\");\n}\n\npub fn main() !void {\n const thread = try Thread.spawn(.{}, do_some_work, .{});\n thread.join();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nStarting the work.Finishing the work.\n```\n\n\n:::\n:::\n\n\n\n\nNotice the use of `try` when calling the `spawn()` method. This means\nthat this method can return an error in some circumstances. One circumstance\nin particular is when you attempt to create a new thread, when you have already\ncreated too much (i.e., you have exceeded the quota of concurrent threads in your system).\n\nBut, if the new thread is successfully created, the `spawn()` method returns a handler\nobject (which is just an object of type `Thread`) to this new thread. You can use\nthis handler object to effectively control all aspects of the thread.\n\nWhen the thread gets created, the function that you provided as input to `spawn()`\ngets invoked (i.e., gets called) to start the execution on this new thread.\nIn other words, every time you call `spawn()`, not only is a new thread created,\nbut the \"start work button\" of this thread is also automatically pressed.\nSo the work being performed in this thread starts as soon as the thread is created.\nThis is similar to how `pthread_create()` from the `pthreads` library in C works,\nwhich also starts the execution as soon as the thread is created.\n\n\n## Returning from a thread\n\nWe have learned in the previous section that the execution of the thread starts as soon as\nthe thread is created. Now, we will learn how to \"join\" or \"detach\" a thread in Zig.\n\"Join\" and \"detach\" are operations that control how the thread returns to\nthe main thread, or to the main process in our program.\n\nWe perform these operations by using the methods `join()` and `detach()` from the thread handler object.\nEvery thread that you create can be marked as either *joinable* or *detached* [@linux_pthread_create].\nYou can turn a thread into a *detached* thread by calling the `detach()` method\nfrom the thread handler object. But if you call the `join()` method instead, then this thread\nbecomes a *joinable* thread.\n\nA thread cannot be both *joinable* and *detached*. Which in general means\nthat you cannot call both `join()` and `detach()` on the same thread.\nBut a thread must be one of the two, meaning that, you should always call\neither `join()` or `detach()` over a thread. If you don't call\none of these two methods over your thread, you introduce undefined behaviour into your program,\nwhich is described in @sec-not-call-join-detach.\n\nNow, let's describe what each of these two methods do to your thread.\n\n\n### Joining a thread\n\nWhen you join a thread, you are essentially saying: \"Hey! Could you please wait for the thread to finish,\nbefore you continue with your execution?\". For example, if we come back to our first and simplest example\nof a thread in Zig, we created a single thread inside the `main()` function of our program\nand just called `join()` on this thread at the end. This section of the code example is reproduced below.\n\nBecause we are joining this new thread inside the `main()`'s scope, it means that the\nexecution of the `main()` function is temporarily stopped, to wait for the execution of the thread\nto finish. That is, the execution of `main()` stops temporarily at the line where `join()` gets called,\nand it will continue only after the thread has finished its tasks.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn main() !void {\n const thread = try Thread.spawn(.{}, do_some_work, .{});\n thread.join();\n}\n```\n:::\n\n\n\n\nBecause we have joined this new thread inside the `main()` scope, we have a\nguarantee that this new thread will finish before the end of the execution of `main()`.\nBecause it's guaranteed that `main()` will wait for the thread to finish its tasks.\n\nIn the example above, there are no more expressions after the `join()` call. We just have the end\nof the `main()`'s scope, and, therefore, the execution of our program just ends after the thread finishes its tasks,\nsince there is nothing more to do. But what if we had more stuff to do after the join call?\n\nTo demonstrate this other possibility, consider the next example exposed\nbelow. Here, we create a `print_id()` function, that just receives an id\nas input, and prints it to `stdout`. In this example, we are creating two\nnew threads, one after another. Then, we join the first thread, then,\nwe wait for two whole seconds, then, at last, we join the second thread.\n\nThe idea behind this example is that the last `join()` call is executed\nonly after the first thread finishes its task (i.e., the first `join()` call),\nand the two-second delay. If you compile and run this\nexample, you will notice that most messages are quickly printed to `stdout`,\ni.e., they appear almost instantly on your screen.\nHowever, the last message (\"Joining thread 2\") takes around 2 seconds to appear\non the screen.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_id(id: *const u8) !void {\n try stdout.print(\"Thread ID: {d}\\n\", .{id.*});\n}\n\npub fn main() !void {\n const id1: u8 = 1;\n const id2: u8 = 2;\n const thread1 = try Thread.spawn(.{}, print_id, .{&id1});\n const thread2 = try Thread.spawn(.{}, print_id, .{&id2});\n\n _ = try stdout.write(\"Joining thread 1\\n\");\n thread1.join();\n std.time.sleep(2 * std.time.ns_per_s);\n _ = try stdout.write(\"Joining thread 2\\n\");\n thread2.join();\n}\n```\n:::\n\n\n\n\n```\nThread ID: Joining thread 1\n1\nThread ID: 2\nJoining thread 2\n```\n\nThis demonstrates that both threads finish their work (i.e., printing the IDs)\nvery fast, before the two seconds of delay end. Because of that, the last `join()` call\nreturns pretty much instantly. Because when this last `join()` call happens, the second\nthread has already finished its task.\n\nNow, if you compile and run this example, you will also notice that, in some cases,\nthe messages intertwine with each other. In other words, you might see\nthe message \"Joining thread 1\" inserted in the middle of the message \"Thread 1\",\nor vice-versa. This happens because:\n\n- the threads are executing basically at the same time as the main process of the program (i.e., the `main()` function).\n- the threads share the same `stdout` from the main process of the program, which means that the messages that the threads produce are sent to exact same place as the messages produced by the main process.\n\nBoth of these points were described previously in @sec-what-thread.\nSo the messages might get intertwined because they are being produced and\nsent to the same `stdout` roughly at the same time.\nAnyway, when you call `join()` over a thread, the current process will wait\nfor the thread to finish before it continues, and, when the thread finishes its\ntask, the resources associated with this thread are automatically freed, and\nthe current process continues with its execution.\n\n\n### Detaching a thread\n\nWhen you detach a thread, the resources associated with this thread are automatically\nreleased back to the system, without the need for another thread to join with this terminated thread.\n\nIn other words, when you call `detach()` on a thread it's like when your children become adults,\ni.e., they become independent from you. A detached thread frees itself, and when this thread finishes its\ntasks, it does not report the results back to you. Thus, you normally mark a thread as *detached*\nwhen you don't need to use the return value of the thread, or when you don't care about\nwhen exactly the thread finishes its job, i.e., the thread solves everything by itself.\n\nTake the code example below. We create a new thread, detach it, and then, we just\nprint a final message before we end our program. We use the same `print_id()`\nfunction that we have used over the previous examples.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_id(id: *const u8) !void {\n try stdout.print(\"Thread ID: {d}\\n\", .{id.*});\n}\n\npub fn main() !void {\n const id1: u8 = 1;\n const thread1 = try Thread.spawn(.{}, print_id, .{&id1});\n thread1.detach();\n _ = try stdout.write(\"Finish main\\n\");\n}\n```\n:::\n\n\n\n\n```\nFinish main\n```\n\nNow, if you look closely at the output of this code example, you will notice\nthat only the final message in main was printed to the console. The message\nthat was supposed to be printed by `print_id()` did not appear in the console.\nWhy? It's because the main process of our program has finished first,\nbefore the thread was able to say anything.\n\nAnd that is perfectly ok behaviour, because the thread was detached, so it was\nable to free itself, without the need to wait for the main process.\nIf you ask main to sleep (or \"wait\") for some extra nanoseconds, before it ends, you will likely\nsee the message printed by `print_id()`, because you give enough time for the thread to\nfinish before the main process ends.\n\n\n## Thread pools\n\nThread pools is a very popular programming pattern, which is used especially on servers and daemons processes.\nA thread pool is just a set of threads, or a \"pool\" of threads. Many programmers like to use this pattern because it makes\nit easier to manage and use multiple threads in your program, instead of manually creating the threads when you need them.\n\nAlso, using thread pools might increase performance as well in your program,\nespecially if your program is constantly creating threads to perform short-lived tasks.\nIn such instance, a thread pool might cause an increase in performance because you do not have be constantly\ncreating and destroying threads all the time, so you don't face a lot of the overhead involved\nin this constant process of creating and destroying threads.\n\nThe main idea behind a thread pool is to have a set of threads already created and ready to perform\ntasks at all times. You create a set of threads at the moment that your program starts, and keep\nthese threads alive while your program runs. Each of these threads will be either performing a task, or\nwaiting for a task to be assigned.\nEvery time a new task emerges in your program, this task is added to a \"queue of tasks\",\nand the moment that a thread becomes available and ready to perform a new task,\nthis thread takes the next task from the \"queue of tasks\", and it simply performs the task.\n\nThe Zig Standard Library offers a thread pool implementation on the `std.Thread.Pool` struct.\nYou create a new instance of a `Pool` object by providing a `Pool.Options` object\nas input to the `init()` method of this struct. A `Pool.Options` object, is a struct object that contains\nconfigurations for the pool of threads. The most important settings in this struct object are\nthe members `n_jobs` and `allocator`. As the name suggests, the member `allocator` should receive an allocator object,\nwhile the member `n_jobs` specifies the number of threads to be created and maintained in this pool.\n\nConsider the example exposed below, that demonstrates how can we create a new thread pool object.\nHere, we create a `Pool.Options` object that contains\na general purpose allocator object, and also, the `n_jobs` member was set to 4, which\nmeans that the thread pool will create and use 4 threads.\n\nAlso notice that the `pool` object was initially set to `undefined`. This allow us\nto initially declare the thread pool object, but not properly instantiate the\nunderlying memory of the object. You have to initially declare your thread pool object\nby using `undefined` like this, because the `init()` method of `Pool` needs\nto have an initial pointer to properly instantiate the object.\n\nSo, just remember to create your thread pool object by using `undefined`, and then,\nafter that, you call the `init()` method over the object.\nYou should also not forget to call the `deinit()` method over the thread pool\nobject, once you are done with it, to release the resources allocated for the thread pool. Otherwise, you will\nhave a memory leak in your program.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Pool = std.Thread.Pool;\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const opt = Pool.Options{\n .n_jobs = 4,\n .allocator = allocator,\n };\n var pool: Pool = undefined;\n try pool.init(opt);\n defer pool.deinit();\n}\n```\n:::\n\n\n\n\nNow that we know how to create `Pool` objects, we have\nto understand how to assign tasks to be executed by the threads in this pool object.\nTo assign a task to be performed by a thread, we need to call the `spawn()` method\nfrom the thread pool object.\n\nThis `spawn()` method works identical to the `spawn()` method from the\n`Thread` object. The method has almost the same arguments as the previous one,\nmore precisely, we don't have to provide a `SpawnConfig` object in this case.\nBut instead of creating a new thread, this `spawn()` method from\nthe thread pool object just registers a new task in the internal \"queue of tasks\" to be performed,\nand any available thread in the pool will get this task, and it will simply perform the task.\n\nIn the example below, we are using our previous `print_id()` function once again.\nBut you may notice that the `print_id()` function is a little different this time,\nbecause now we are using `catch` instead of `try` in the `print()` call.\nCurrently, the `Pool` struct only supports functions that don't return errors\nas tasks. Thus, when assigning tasks to threads in a thread pool, it is essential to use functions\nthat don't return errors. That is why we are using `catch` here, so that the\n`print_id()` function don't return an error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_id(id: *const u8) void {\n _ = stdout.print(\"Thread ID: {d}\\n\", .{id.*})\n catch void;\n}\nconst id1: u8 = 1;\nconst id2: u8 = 2;\ntry pool.spawn(print_id, .{&id1});\ntry pool.spawn(print_id, .{&id2});\n```\n:::\n\n\n\n\nThis limitation should probably not exist, and, in fact, it's already on the radar of the\nZig team to fix this issue, and it's being tracked in an [open issue](https://github.com/ziglang/zig/issues/18810)[^issue].\nSo, if you do need to provide a function that might return an error as the task\nto be performed by the threads in the thread pool, then, you are either limited to:\n\n- implementing your own thread pool that does not have this limitation.\n- wait for the Zig team to actually fix this issue.\n\n[^issue]: \n\n\n\n\n## Mutexes\n\nMutexes are a classic component of every thread library. In essence, a mutex is a *Mutually Exclusive Flag*, and this flag\nacts like a type of \"lock\", or as a gate keeper to a particular section of your code. Mutexes are related to thread synchronization,\nmore specifically, they prevent you from having some classic race conditions in your program,\nand, therefore, major bugs and undefined behaviour that are usually difficult to track and understand.\n\nThe main idea behind a mutex is to help us to control the execution of a particular section of the code, and to\nprevent two or more threads from executing this particular section of the code at the same time.\nMany programmers like to compare a mutex to a bathroom door (which typically has a lock).\nWhen a thread locks its own mutex object, it's like if the bathroom door was locked.\nTherefore, other people (in this case, other threads) who want to use the same bathroom at the same time\nmust be patient and simply wait for the current occupant (or thread) to unlock the door and get out of the bathroom.\n\nSome other programmers also like to explain mutexes by using the analogy of \"each person will have their turn to speak\".\nThis is the analogy used in the [*Multithreading Code* video from the Computerphile project](https://www.youtube.com/watch?v=7ENFeb-J75k&ab_channel=Computerphile)[^computerphile].\nImagine if you are in a conversation circle. There is a moderator in this circle, which is the person that decides who\nhas the right to speak at that particular moment. The moderator gives a green card (or some sort of an authorization card) to the person that\nis going to speak, and, as a result, everyone else must be silent and hear this person that has the green card.\nWhen the person finishes talking, they give the green card back to the moderator, and the moderator decides\nwho is going to talk next, and delivers the green card to that person. And the cycle goes on like this.\n\n[^computerphile]: \n\n\nA mutex acts like the moderator in this conversation circle. The mutex authorizes one single thread to execute a specific section of the code,\nand it also blocks the other threads from executing this same section of the code. If these other threads want to execute this same\npiece of the code, they are forced to wait for the the authorized thread to finish first.\nWhen the authorized thread finishes executing this code, the mutex authorizes the next thread to execute this code,\nwhile the remaining threads remain blocked. Therefore, a mutex is like a moderator that does a \"each\nthread will have their turn to execute this section of the code\" type of control.\n\n\nMutexes are especially used to prevent data race problems from happening. A data race problem happens when two or more threads\nare trying to read from or write to the same shared object at the same time.\nSo, when you have an object that is shared will all threads, and, you want to avoid two or more threads from\naccessing this same object at the same time, you can use a mutex to lock the part of the code that access this specific object.\nWhen a thread tries to run this code that is locked by a mutex, this thread stops its execution,\nand patiently waits for this section of the codebase to be unlocked to continue.\n\nNotice that mutexes are normally used to lock areas of the codebase that access/modify data that is **shared** with all threads,\ni.e., objects that are either stored in the global data section, or in the heap space of your program.\nSo mutexes are not normally used on areas of the codebase that access/modify objects that are local to the thread.\n\n\n\n### Critical section {#sec-critical-section}\n\nCritical section is a concept commonly associated with mutexes and thread synchronization.\nIn essence, a critical section is the section of the program that a thread access/modify a shared resource\n(i.e., an object, a file descriptor, something that all threads have access to). In other words,\na critical section is the section of the program where race conditions might happen, and, therefore,\nwhere undefined behaviour can be introduced into the program.\n\nWhen we use mutexes in our program, the critical section defines the area of the codebase that we want to lock.\nSo we normally lock the mutex object at the beginning of the critical section,\nand then, we unlock it at the end of the critical section.\nThe two bullet points exposed below comes from the \"Critical Section\" article from GeekFromGeeks,\nand they summarise well the role that a critical section plays in the thread synchronization problem [@geeks_critical_section].\n\n\n1. The critical section must be executed as an atomic operation, which means that once one thread or process has entered the critical section, all other threads or processes must wait until the executing thread or process exits the critical section. The purpose of synchronization mechanisms is to ensure that only one thread or process can execute the critical section at a time.\n1. The concept of a critical section is central to synchronization in computer systems, as it is necessary to ensure that multiple threads or processes can execute concurrently without interfering with each other. Various synchronization mechanisms such as semaphores, mutexes, monitors, and condition variables are used to implement critical sections and ensure that shared resources are accessed in a mutually exclusive manner.\n\n\n### Atomic operations {#sec-atomic-operation}\n\nYou will also see the term \"atomic operation\" a lot when reading about threads, race conditions and mutexes.\nIn summary, an operation is categorized as \"atomic\" when a context switch cannot occur in\nthe middle of the operation. In other words, this operation is always done from beginning to end, without interruptions\nof another process or operation in the middle of its execution phase.\n\nNot many operations today are atomic. But why do atomic operations matter here? It's because data races\n(which is a type of a race condition) cannot happen on operations that are atomic.\nSo if a particular line in your code performs an atomic operation, then this line will never\nsuffer from a data race problem. Therefore, programmers sometimes use an atomic operation\nto protect themselves from data race problems in their code.\n\nWhen you have an operation that is compiled into just one single assembly instruction, this operation might be atomic,\nbecause it's just one assembly instruction. But this is not guaranteed. This is usually true for old CPU architectures\n(such as `x86`). But nowadays, most assembly instructions in modern CPU architectures are broken down into multiple micro-tasks,\nwhich inherently makes the operation non-atomic, even if it consists of a single assembly instruction.\n\nThe Zig Standard Library offers some atomic functionality in the `std.atomic` module.\nIn this module, you will find a public and generic function called `Value()`. With this function we create an \"atomic object\", which is\na value that contains some native atomic operations, most notably, a `load()` and a `fetchAdd()` operation.\nIf you have experience with multithreading in C++, you probably have recognized this pattern. So yes, this generic\n\"atomic object\" in Zig is essentially identical to the template struct `std::atomic` from the C++ Standard Library.\nIt's important to emphasize that only primitive data types (i.e., the types presented in @sec-primitive-data-types)\nare supported by these atomic operations in Zig.\n\n\n\n\n\n### Data races and race conditions\n\nTo understand why mutexes are used, we need to understand better the problem that they seek\nto solve, which can be summarized into data race problems. A data race problem is a type of a race condition,\nwhich happens when one thread is accessing a particular memory location (i.e., a particular shared object) at the same\ntime that another thread is trying to write/save new data into this same memory location (i.e., the same shared object).\n\nWe can simply define a race condition as any type of bug in your program that is based\non a \"who gets there first\" problem. A data race problem is a type of a race condition, because it occurs when two or more parties\nare trying to read and write into the same memory location at the same time, and, therefore, the end result of this operation\ndepends completely on who gets to this memory location first.\nAs a consequence, a program that has a data race problem will likely produce a different result each time that we execute it.\n\nThus, race conditions produce undefined behaviour and unpredictability because the program produces\na different answer each time a different person gets to the target location before the others.\nAnd, we have no easy way to either predict or control who is getting to this target location first.\nIn other words, each time your program runs, you may get a different answer because a different person,\nfunction, or part of the code finishes its tasks before the others.\n\nAs an example, consider the code snippet exposed below. In this example, we create a global counter\nvariable, and we also create an `increment()` function, whose job is to just increment this global counter\nvariable in a for loop.\n\nSince the for loop iterates 1 hundred thousand times, and, we create two separate threads\nin this code example, what number do you expect to see in the final message printed to `stdout`?\nThe answer should be 2 hundred thousand. Right? Well, in theory, this program was supposed\nto print 2 hundred thousand at the end, but in practice, every time that I execute this program\nI get a different answer.\n\nIn the example exposed below, you can see that this time the end\nresult was 117254, instead of the expected 200000. The second time I executed this program,\nI got the number 108592 as the result. So the end result of this program is varying, but it never gets\nto the expected 200000 that we want.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// Global counter variable\nvar counter: usize = 0;\n// Function to increment the counter\nfn increment() void {\n for (0..100000) |_| {\n counter += 1;\n }\n}\n\npub fn main() !void {\n const thr1 = try Thread.spawn(.{}, increment, .{});\n const thr2 = try Thread.spawn(.{}, increment, .{});\n thr1.join();\n thr2.join();\n try stdout.print(\"Couter value: {d}\\n\", .{counter});\n}\n```\n:::\n\n\n\n\n```\nCouter value: 117254\n```\n\n\nWhy this is happening? The answer is: because this program contains a data race problem.\nThis program would print the correct number 200000 if and only if the first thread finishes\nits tasks before the second thread starts to execute. But that is very unlikely to happen.\nBecause the process of creating the thread is too fast, and therefore, both threads start to execute roughly\nat the same time. If you change this code to add some nanoseconds of sleep between the first and the second calls to `spawn()`,\nyou will increase the chances of the program producing the \"correct result\".\n\nSo the data race problem happens because both threads are reading and writing to the same\nmemory location at roughly the same time. In this example, each thread is essentially performing\nthree basic operations at each iteration of the for loop, which are:\n\n1. reading the current value of `count`.\n1. incrementing this value by 1.\n1. writing the result back into `count`.\n\nIdeally, a thread B should read the value of `count`, only after the other thread A has finished\nwriting the incremented value back into the `count` object. Therefore, in the ideal scenario, which is demonstrated\nin @tbl-data-race-ideal, the threads should work in sync with each other. But the reality is that these\nthreads are out of sync, and because of that, they suffer from a data race problem, which is demonstrated\nin @tbl-data-race-not.\n\nNotice that, in the data race scenario (@tbl-data-race-not), the read performed by a thread B happens\nbefore the write operation of thread A, and that ultimately leads to wrong results at the end of the program.\nBecause when thread B reads the value of the `count` variable, thread A is still processing\nthe initial value from `count`, and has not yet written the new, incremented value back to `count`. As a result,\nthread B ends up reading the same initial (or \"old\") value from `count` instead of\nthe updated, incremented value that thread A would have written.\n\n\n::: {#tbl-data-race-ideal}\n\n| Thread 1 | Thread 2 | Integer value |\n|-------------|-------------|---------------|\n| read value | | 0 |\n| increment | | 1 |\n| write value | | 1 |\n| | read value | 1 |\n| | increment | 2 |\n| | write value | 2 |\n\n: An ideal scenario for two threads incrementing the same integer value\n:::\n\n::: {#tbl-data-race-not}\n\n| Thread 1 | Thread 2 | Integer value |\n|-------------|-------------|---------------|\n| read value | | 0 |\n| | read value | 0 |\n| increment | | 1 |\n| | increment | 1 |\n| write value | | 1 |\n| | write value | 1 |\n\n: A data race scenario when two threads are incrementing the same integer value\n:::\n\n\nIf you think about these diagrams exposed in form of tables, you will notice that they relate back to our discussion of atomic operations\nin @sec-atomic-operation. Remember, atomic operations are operations that the CPU executes\nfrom beginning to end, without interruptions from other threads or processes. So,\nthe scenario exposed in @tbl-data-race-ideal does not suffer from a data race, because\nthe operations performed by thread A are not interrupted in the middle by the operations\nfrom thread B.\n\nIf we also think about the discussion of critical section from @sec-critical-section, we can identify\nthe section that representes the critical section of the program, which is the section that is vulnerable\nto data race conditions. In this example, the critical section of the program is the line where we increment\nthe `counter` variable (`counter += 1`). So, ideally, we want to use a mutex, and lock right before this line, and then\nunlock right after this line.\n\n\n\n\n### Using mutexes in Zig\n\nNow that we know the problem that mutexes seek to solve, we can learn how to use them in Zig.\nMutexes in Zig are available through the `std.Thread.Mutex` struct from the Zig Standard Library.\nIf we take the same code from the previous example, and improve it with mutexes, to solve\nour data race problem, we get the code example below.\n\nNotice that this time, we had to alter the `increment()` function to receive a pointer to\nthe `Mutex` object as input. All that we need to do, to make this program safe against\ndata race problems, is to call the `lock()` method at the beginning of\nthe critical section, and then, call `unlock()` at the end of the critical section.\nNotice that the output of this program is now the correct number of 200000.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Thread = std.Thread;\nconst Mutex = std.Thread.Mutex;\nvar counter: usize = 0;\nfn increment(mutex: *Mutex) void {\n for (0..100000) |_| {\n mutex.lock();\n counter += 1;\n mutex.unlock();\n }\n}\n\npub fn main() !void {\n var mutex: Mutex = .{};\n const thr1 = try Thread.spawn(.{}, increment, .{&mutex});\n const thr2 = try Thread.spawn(.{}, increment, .{&mutex});\n thr1.join();\n thr2.join();\n try stdout.print(\"Couter value: {d}\\n\", .{counter});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nCouter value: 200000\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## Read/Write locks\n\nMutexes are normally used when it's not always safe for two or more threads running the same\npiece of code at the same time. In contrast, read/write locks are normally used in situations\nwhere you have a mixture of scenarios, i.e., there are some pieces of the codebase that are safe\nto run in parallel, and other pieces that are not safe.\n\nFor example, suppose that you have multiple threads that uses the same shared file in the filesystem to store some configurations, or\nstatistics. If two or more threads try to read the data from this same file at the same time, nothing bad happens.\nSo this part of the codebase is perfectly safe to be executed in parallel, with multiple threads reading the same file at the same time.\n\nHowever, if two or more threads try to write data into this same file at the same time, then we cause some race condition\nproblems. So this other part of the codebase is not safe to be executed in parallel.\nMore specifically, a thread might end up writing data in the middle of the data written by the other thread.\nThis process of two or more threads writing to the same location might lead to data corruption.\nThis specific situation is usually called a *torn write*.\n\nThus, what we can extract from this example is that there are certain types of operations that cause\na race condition, but there are also other types of operations that do not cause a race condition problem.\nYou could also say that there are types of operations that are susceptible to race condition problems,\nand there are other types of operations that are not.\n\nA read/write lock is a type of lock that acknowledges the existence of this specific scenario, and you can\nuse this type of lock to control which parts of the codebase are safe to run in parallel and which parts are not.\n\n\n\n### Exclusive lock vs shared lock\n\nTherefore, a read/write lock is a little different from a mutex. Because a mutex is always an *exclusive lock*, meaning that, only\none thread is allowed to execute at all times. With an exclusive lock, the other threads are always \"excluded\",\ni.e., they are always blocked from executing. But in a read/write lock, the other threads might be authorized\nto run at the same time, depending on the type of lock that they acquire.\n\nWe have two types of locks in a read/write lock, which are: an exclusive lock and a shared lock. An exclusive lock works exactly the same\nas a mutex, while a shared lock is a lock that does not block the other threads from running at the same time.\nIn the `pthreads` C library, read/write locks are available through the `pthread_rwlock_t` C struct. With\nthis C struct, you can create:\n\n- a \"write lock\", which corresponds to an exclusive lock.\n- a \"read lock\", which corresponds to a shared lock.\n\nThe terminology might be a little different compared to Zig. But the meaning is still the same.\nTherefore, just remember this relationship, write locks are exclusive locks, while read locks are shared locks.\n\nWhen a thread tries to acquire a read lock (i.e., a shared lock), this thread gets the shared lock\nif and only if another thread does not currently hold a write lock (i.e., an exclusive lock), and also\nif there are no other threads already in the queue,\nwaiting for their turn to acquire a write lock. In other words, the thread in the queue has attempted\nto get a write lock earlier, but this thread was blocked\nbecause there was another thread running that already had a write lock. As a consequence, this thread is in the queue to get a write lock,\nand it's currently waiting for the other thread with a write lock to finish its execution.\n\nWhen a thread tries to acquire a read lock, but it fails in acquiring this read lock, either because there is\na thread with a write lock already running, or because there is a thread in the queue to get a write lock,\nthe execution of this thread is instantly blocked, i.e., paused. This thread will indefinitely attempt to get the\nread lock, and its execution will be unblocked (or unpaused) only after this thread successfully acquires the read lock.\n\nIf you think deeply about this dynamic between read locks versus write locks, you might notice that a read lock is basically a safety mechanism.\nMore specifically, it's a way for us to\nallow a particular thread to run together with the other threads only when it's safe to. In other words, if there is currently\na thread with a write lock running, then it's very likely not safe for the thread that is trying to acquire the read lock to run now.\nAs a consequence, the read lock protects this thread from running into dangerous waters, and patiently waits for the\n\"write lock\" thread to finishes its tasks before it continues.\n\nOn the other hand, if there are only \"read lock\" (i.e., \"shared lock\") threads currently running\n(i.e., not a single \"write lock\" thread currently exists), then it\nis perfectly safe for this thread that is acquiring the read lock to run in parallel with the other\nthreads. As a result, the read lock just\nallows for this thread to run together with the other threads.\n\nThus, by using read locks (shared locks) in conjunction with write locks (exclusive locks), we can control which regions or sections\nof our multithreaded code is safe to have parallelism, and which sections are not safe to have parallelism.\n\n\n\n\n\n### Using read/write locks in Zig\n\nThe Zig Standard Library supports read/write locks through the `std.Thread.RwLock` module.\nIf you want a particular thread to acquire a shared lock (i.e., a read lock), you should\ncall the `lockShared()` method from the `RwLock` object. But, if you want this thread\nto acquire an exclusive lock (i.e., a write lock) instead, then you should call the\n`lock()` method from the `RwLock` object.\n\nAs with mutexes, we also have to unlock the shared or exclusive locks that we acquire through a read/write lock object,\nonce we are at the end of our \"critical section\". If you have acquired an exclusive lock, then, you unlock\nthis exclusive lock by calling the `unlock()` method from the read/write lock object. In contrast,\nif you have acquired a shared lock instead, then, call `unlockShared()` to unlock this shared lock.\n\nAs a simple example, the snippet below creates three separate threads responsible for reading the\ncurrent value in a `counter` object, and it also creates another thread responsible for writing\nnew data into the `counter` object (incrementing it, more specifically).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar counter: u32 = 0;\nfn reader(lock: *RwLock) !void {\n while (true) {\n lock.lockShared();\n const v: u32 = counter;\n try stdout.print(\"{d}\", .{v});\n lock.unlockShared();\n std.time.sleep(2 * std.time.ns_per_s);\n }\n}\nfn writer(lock: *RwLock) void {\n while (true) {\n lock.lock();\n counter += 1;\n lock.unlock();\n std.time.sleep(2 * std.time.ns_per_s);\n }\n}\n\npub fn main() !void {\n var lock: RwLock = .{};\n const thr1 = try Thread.spawn(.{}, reader, .{&lock});\n const thr2 = try Thread.spawn(.{}, reader, .{&lock});\n const thr3 = try Thread.spawn(.{}, reader, .{&lock});\n const wthread = try Thread.spawn(.{}, writer, .{&lock});\n\n thr1.join();\n thr2.join();\n thr3.join();\n wthread.join();\n}\n```\n:::\n\n\n\n\n\n## Yielding a thread\n\nThe `Thread` struct supports yielding through the `yield()` method.\nYielding a thread means that the execution of the thread is temporarily stopped,\nand it moves to the end of the priority queue managed by the scheduler of\nyour operating system.\n\nThat is, when you yield a thread, you are essentially saying the following to your OS:\n\"Hey! Could you please stop executing this thread for now, and comeback to continue it later?\".\nYou could also interpret this yield operation as: \"Could you please deprioritize this thread,\nto focus on doing other things instead?\".\nSo this yield operation is also a way for you\nto stop a particular thread, so that you can work and prioritize other threads instead.\n\nIt's important to say that, yielding a thread is a \"not so common\" thread operation these days.\nIn other words, not many programmers use yielding in production, simply because it's hard to use\nthis operation and make it work properly, and also, there\nare better alternatives. Most programmers prefer to use `join()` instead.\nIn fact, most of the time, when you see someone using this \"yield\" operation in some code example,\nthey are usually doing so to help debug race conditions in their applications.\nThat is, this \"yield\" operation is mostly used as a debug tool nowadays.\n\nAnyway, if you want to yield a thread, just call the `yield()` method from it, like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nthread.yield();\n```\n:::\n\n\n\n\n\n\n\n\n\n## Common problems in threads\n\n\n\n### Deadlocks\n\nA deadlock occurs when two or more threads are blocked forever,\nwaiting for each other to release a resource. This usually happens when multiple locks are involved,\nand the order of acquiring them is not well managed.\n\nThe code example below demonstrates a deadlock situation. We have two different threads that execute\ntwo different functions (`work1()` and `work2()`) in this example. And we also have two separate\nmutexes. If you compile and run this code example, you will notice that the program just runs indefinitely,\nwithout ending.\n\nWhen we look into the first thread, which executes the `work1()` function, we can\nnotice that this function acquires the `mut1` lock first. Because this is the first operation\nthat is executed inside this thread, which is the first thread created in the program.\nAfter that, the function sleeps for 1 second, to\nsimulate some type of work, and then, the function tries to acquire the `mut2` lock.\n\nOn the other hand, when we look into the second thread, which executes the `work2()` function,\nwe can see that this function acquires the `mut2` lock first. Because when this thread gets created and it tries\nto acquire this `mut2` lock, the first thread is still sleeping on that \"sleep 1 second\" line.\nAfter acquiring `mut2`, the `work2()` function also sleeps for 1 second, to\nsimulate some type of work, and then the function tries to acquire the `mut1` lock.\n\nThis creates a deadlock situation, because after the \"sleep for 1 second\" line in both threads,\nthread 1 is trying to acquire the `mut2` lock, but this lock is currently being used by thread 2.\nHowever, at this moment, thread 2 is also trying to acquire the `mut1` lock, which is currently\nbeing used by thread 1. Therefore, both threads end up waiting for ever. Waiting for their peer to\nfree the lock that they want to acquire.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar mut1: Mutex = .{}; var mut2: Mutex = .{};\nfn work1() !void {\n mut1.lock();\n std.time.sleep(1 * std.time.ns_per_s);\n mut2.lock();\n _ = try stdout.write(\"Doing some work 1\\n\");\n mut2.unlock(); mut1.unlock();\n}\n\nfn work2() !void {\n mut2.lock();\n std.time.sleep(1 * std.time.ns_per_s);\n mut1.lock();\n _ = try stdout.write(\"Doing some work 1\\n\");\n mut1.unlock(); mut2.unlock();\n}\n\npub fn main() !void {\n const thr1 = try Thread.spawn(.{}, work1, .{});\n const thr2 = try Thread.spawn(.{}, work2, .{});\n thr1.join();\n thr2.join();\n}\n```\n:::\n\n\n\n\n\n### Not calling `join()` or `detach()` {#sec-not-call-join-detach}\n\nWhen you do not call either `join()` or `detach()` over a thread, then this thread becomes a \"zombie thread\",\nbecause it does not have a clear \"return point\".\nYou could also interpret this as: \"nobody is properly responsible for managing the thread\".\nWhen we don't establish if a thread is either *joinable* or *detached*,\nnobody becomes responsible for dealing with the return value of this thread, and also,\nnobody becomes responsible for clearing (or freeing) the resources associated with this thread.\n\nYou don't want to be in this situation, so remember to always use `join()` or `detach()`\non the threads that you create. When you don't use one of these methods, we lose\ncontrol over the thread, and its resources are never freed\n(i.e., you have leaked resources in the system).\n\n\n### Cancelling or killing a particular thread\n\nWhen we think about the `pthreads` C library, there is a possible way to asynchronously kill or cancel\na thread, which is by sending a `SIGTERM` signal to the thread through the `pthread_kill()` function.\nBut canceling a thread like this is bad. It's dangerously bad. As a consequence, the Zig implementation\nof threads does not have a similar function, or, a similar way to asynchronously cancel or kill\na thread.\n\nTherefore, if you want to cancel a thread in the middle of its execution in Zig,\nthen one good strategy that you can take is to use control flow in conjunction with `join()`.\nMore specifically, you can design your thread around a while loop that is constantly\nchecking if the thread should continue running.\nIf it's time to cancel the thread, we could make the while loop break, and join the thread with the main thread\nby calling `join()`.\n\nThe code example below demonstrates to some extent this strategy.\nHere, we are using control flow to break the while loop, and exit the thread earlier than\nwhat we have initially planned to. This example also demonstrates how can we use\natomic objects in Zig with the `Value()` generic function that we have mentioned in @sec-atomic-operation.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Thread = std.Thread;\nconst stdout = std.io.getStdOut().writer();\nvar running = std.atomic.Value(bool).init(true);\nvar counter: u64 = 0;\nfn do_more_work() void {\n std.time.sleep(2 * std.time.ns_per_s);\n}\nfn work() !void {\n while (running.load(.monotonic)) {\n for (0..10000) |_| { counter += 1; }\n if (counter < 15000) {\n _ = try stdout.write(\n \"Time to cancel the thread.\\n\"\n );\n running.store(false, .monotonic);\n } else {\n _ = try stdout.write(\"Time to do more work.\\n\");\n do_more_work();\n running.store(false, .monotonic);\n }\n }\n}\n\npub fn main() !void {\n const thread = try Thread.spawn(.{}, work, .{});\n thread.join();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nTime to cancel the thread.\n```\n\n\n:::\n:::\n", + "supporting": [ + "14-threads_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/14-zig-c-interop/execute-results/html.json b/_freeze/Chapters/14-zig-c-interop/execute-results/html.json index dac50d94..fe46362b 100644 --- a/_freeze/Chapters/14-zig-c-interop/execute-results/html.json +++ b/_freeze/Chapters/14-zig-c-interop/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "f39e8db0da66759da16d297f7de43596", + "hash": "7f0fb45d8337d93333a20759133b82dc", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Zig interoperability with C\n\nIn this chapter, we are going to discuss the interoperability of Zig with C.\nWe have discussed at @sec-building-c-code how you can use the `zig` compiler to build C code.\nBut we haven't discussed yet how to actually use C code in Zig. In other words,\nwe haven't discussed yet how to call and use C code from Zig.\n\nThis is the main subject of this chapter.\nAlso, in our next small project in this book, we are going to use a C library in it.\nAs consequence, we will put in practice a lot of the knowledge discussed here on\nthis next project.\n\n\n## How to call C code from Zig\n\nInteroperability with C is not something new. Most high-level programming languages have FFI (foreign function interfaces),\nwhich can be used to call C code. For example, Python have Cython, R have `.Call()`, Javascript have `ccall()`, etc.\nBut Zig integrates with C in a deeper level, which affects not only the way that C code get's called, but also,\nhow this C code is compiled and incorporated into your Zig project.\n\nIn summary, Zig have great interoperability with C. If you want to call any C code from Zig,\nyou have to perform the following steps:\n\n- import a C header file into your Zig code.\n- link your Zig code with the C library.\n\n\n### Strategies to import C header files {#sec-strategy-c}\n\nUsing C code in Zig always involves performing the two steps cited above. However, when\nwe talk specifically about the first step listed above, there are currently two\ndifferent ways to perform this first step, which are:\n\n- translating the C header file into Zig code, through the `zig translate-c` command, and then, import and use the translated Zig code.\n- importing the C header file directly into your Zig module through the `@cImport()` built-in function.\n\nIf you are not familiar with `translate-c`, this is a subcommand inside the `zig` compiler that takes C files\nas input, and outputs the Zig representation of the C code present in these C files.\nIn other words, this subcommand works like a transpiler. It takes C code, and translates it into\nthe equivalent Zig code.\n\nI think it would be ok to interpret `translate-c` as a tool to generate Zig bindings\nto C code, similarly to the `rust-bindgen`[^bindgen] tool, which generates Rust FFI bindings to C code.\nBut that would not be a precise interpretation of `translate-c`. The idea behind this tool is\nto really translate the C code into Zig code.\n\n[^bindgen]: \n\nNow, on a surface level, `@cImport()` versus `translate-c` might seem like\ntwo completely different strategies. But in fact, they are effectively the exact same strategy.\nBecause, under the hood, the `@cImport()` built-in function is just a shortcut to `translate-c`.\nBoth tools use the same \"C to Zig\" translation functionality. So when you use `@cImport()`,\nyou are essentially asking the `zig` compiler to translate the C header file into Zig code, then,\nto import this Zig code into your current Zig module.\n\nAt the present moment, there is an accepted proposal at the Zig project, to move `@cImport()`\nto the Zig build system[^cimport-issue]. If this proposal is completed, then, the \"use `@cImport()`\"\nstrategy would be transformed into \"call a translate C function in your Zig build script\".\nSo, the step of translating the C code into Zig code would be moved to\nthe build script of your Zig project, and you would only need to import the translated Zig code into\nyour Zig module to start calling C code from Zig.\n\n[^cimport-issue]: \n\nIf you think about this proposal for a minute, you will understand that this is actually\na small change. I mean, the logic is the same, and the steps are still essentially the same.\nThe only difference is that one of the steps will be moved to the build script of your Zig project.\n\n\n\n### Linking Zig code with a C library {#sec-linking-c}\n\nRegardless of which of the two strategies from the previous section you choose,\nif you want to call C code from Zig, you must link your Zig code\nwith the C library that contains the C code that you want to call.\n\nIn other words, everytime you use some C code in your Zig code, **you introduce a dependency in your build process**.\nThis should come as no surprise to anyone that have any experience with C and C++.\nBecause this is no different in C. Everytime you use a C library in your C code, you also\nhave to build and link your C code with this C library that you are using.\n\nWhen we use a C library in our Zig code, the `zig` compiler needs to access the definition of the C functions that\nare being called in your Zig code. The C header file of this library provides the\ndeclarations of these C functions, but not their definitions. So, in order to access these definitions,\nthe `zig` compiler needs to build your Zig code and link it with the C library during the build process.\n\nAs we discussed across the @sec-build-system, there are different strategies to link something with a library.\nThis might involve building the C library first, and then, linking it with the Zig code. Or,\nit could also involve just the linking step, if this C library is already built and\ninstalled in your system. Anyway, if you have doubts about this, comeback to @sec-build-system.\n\n\n\n## Importing C header files {#sec-import-c-header}\n\nAt @sec-strategy-c, we have described that, currently, there are two different paths that\nyou can take to import a C header file into your Zig modules, `translate-c` or `@cImport()`.\nThis section describes each strategy separately in more details.\n\n### Strategy 1: using `translate-c`\n\nWhen we choose this strategy, we first need to use the `translate-c` tool to translate\nthe C header files that we want to use into Zig code. For example, suppose we wanted to\nuse the `fopen()` C function from the `stdio.h` C header file. We can translate the\n`stdio.h` C header file through the bash command below:\n\n```bash\nzig translate-c /usr/include/stdio.h \\\n -lc -I/usr/include \\\n -D_NO_CRT_STDIO_INLINE=1 > c.zig \\\n```\n\nNotice that, in this bash command, we are passing the necessary compiler flags (`-D` to define macros,\n`-l` to link libraries, `-I` to add an \"include path\") to compile and use the `stdio.h` header file.\nAlso notice that we are saving the results of the translation process inside a Zig module called `c.zig`.\n\nTherefore, after running this command, all we have to do is to import this `c.zig` module, and start\ncalling the C functions that you want to call from it. The example below demonstrates that.\nIs important to remember what we've discussed at @sec-linking-c. In order to compile this\nexample you have to link this code with `libc`, by passing the flag `-lc` to the `zig` compiler.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @import(\"c.zig\");\npub fn main() !void {\n const x: f32 = 1772.94122;\n _ = c.printf(\"%.3f\\n\", x);\n}\n```\n:::\n\n\n\n\n```\n1772.941\n```\n\n\n### Strategy 2: using `@cImport()`\n\nTo import a C header file into our Zig code, we can use the built-in functions `@cInclude()` and `@cImport()`.\nInside the `@cImport()` function, we open a block (with a pair of curly braces). Inside this block\nwe can (if we need to) include multiple `@cDefine()` calls to define C macros when including this specific C header file.\nBut for the most part, you will probably need to use just a single call inside this block,\nwhich is a call to `@cInclude()`.\n\nThis `@cInclude()` function is equivalent to the `#include` statement in C.\nYou provide the name of the C header that you want to include as input to this `@cInclude()` function,\nthen, in conjunction with `@cImport()`, it will perform the necessary steps\nto include this C header file into your Zig code.\n\nYou should bind the result of `@cImport()` to a constant object, pretty much like you would do with\n`@import()`. You just assign the result to a constant object in your\nZig code, and, as consequence, all C functions, C structs, C macros, etc. that are defined inside the\nC header files will be available through this constant object.\n\nLook at the code example below, where we are importing the Standard I/O C Library (`stdio.h`),\nand calling the `printf()`[^printf] C function. Notice that we have also used in this example the C function `powf()`[^powf],\nwhich comes from the C Math Library (`math.h`).\nIn order to compile this example, you have to link this Zig code with both\nthe C Standard Library and the C Math Library, by passing the flags `-lc` and `-lm`\nto the `zig` compiler.\n\n[^printf]: \n[^powf]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cDefine(\"_NO_CRT_STDIO_INLINE\", \"1\");\n @cInclude(\"stdio.h\");\n @cInclude(\"math.h\");\n});\n\npub fn main() !void {\n const x: f32 = 15.2;\n const y = c.powf(x, @as(f32, 2.6));\n _ = c.printf(\"%.3f\\n\", y);\n}\n```\n:::\n\n\n\n\n```\n1182.478\n```\n\n\n## About passing Zig values to C functions {#sec-zig-obj-to-c}\n\nZig objects have some intrinsic differences between their C equivalents.\nProbably the most noticeable one is the difference between C strings and Zig strings,\nwhich I described at @sec-zig-strings.\nZig strings are objects that contains both an array of arbitrary bytes and a length value.\nOn the other hand, a C string is usually just a pointer to a null-terminated array of arbitrary bytes.\n\nBecause of these intrinsic differences, in some specific cases, you cannot pass Zig objects directly\nas inputs to C functions before you convert them into C compatible values. However, in some other cases,\nyou are allowed to pass Zig objects and Zig literal values directly as inputs to C functions,\nand everything will work just fine, because the `zig` compiler will handle everything for you.\n\nSo we have two different scenarios being described here. Let's call them \"auto-conversion\" and \"need-conversion\".\nThe \"auto-conversion\" scenario is when the `zig` compiler handles everything for you, and automatically convert your\nZig objects/values into C compatible values. In contrast,\nthe \"need-conversion\" scenario is when you, the programmer, have the responsibility of converting\nthat Zig object into a C compatible value, before passing it to C code.\n\nThere is also a third scenario that is not being described here, which is when you create a C object, or, a C struct, or\na C compatible value in your Zig code, and you pass this C object/value as input to a C function in your Zig code.\nThis scenario will be described later at @sec-c-inputs. In this section, we are focused on the scenarios where\nwe are passing Zig objects/values to C code, instead of C objects/values being passed to C code.\n\n\n### The \"auto-conversion\" scenario\n\nAn \"auto-conversion\" scenario is when the `zig` compiler automatically converts our Zig objects into\nC compatible values for us. This specific scenario happens mostly in two instances:\n\n- with string literal values;\n- with any of the primitive data types that were introduced at @sec-primitive-data-types.\n\nWhen we think about the second instance described above, the `zig` compiler does automatically\nconvert any of the primitive data types into their C equivalents, because the compiler knows how\nto properly convert a `i16` into a `signed short`, or, a `u8` into a `unsigned char`, etc.\nNow, when we think about string literal values, they can be automatically\nconverted into C strings as well, especially because the `zig` compiler does not forces\na specific Zig data type into a string literal at first glance, unless you store this\nstring literal into a Zig object, and explicitly annotate the data type of this object.\n\nThus, with string literal values, the `zig` compiler have more freedom to infer which is the appropriate data type\nto be used in each situation. You could say that the string literal value \"inherits its data type\" depending on the context that\nit is used. Most of the times, this data type is going to be the type that we commonly associate with Zig strings (`[]const u8`).\nBut it might be a different type depending on the situation. When the `zig` compiler detects that you are providing\na string literal value as input to some C function, the compiler automatically interprets this string\nliteral as a C string value.\n\nAs an example, look at the code exposed below. Here we are using\nthe `fopen()` C function to simply open and close a file. If you do not know how this `fopen()`\nfunction works in C, it takes two C strings as input. But in this code example below, we are passing some\nstring literals written in our Zig code directly as inputs to this `fopen()` C function.\n\nIn other words, we are not doing any conversion from a Zig string to a C string.\nWe are just passing the Zig string literals directly as inputs to the C function. And it works just fine!\nBecause the compiler interprets the string `\"foo.txt\"` as a C string given the current context.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cDefine(\"_NO_CRT_STDIO_INLINE\", \"1\");\n @cInclude(\"stdio.h\");\n});\n\npub fn main() !void {\n const file = c.fopen(\"foo.txt\", \"rb\");\n if (file == null) {\n @panic(\"Could not open file!\");\n }\n if (c.fclose(file) != 0) {\n return error.CouldNotCloseFileDescriptor;\n }\n}\n```\n:::\n\n\n\n\nLet's make some experiments, by writing the same code in different manners, and we\nsee how this affects the program. As a starting point, let's store the `\"foo.txt\"` string inside\na Zig object, like the `path` object below, and then, we pass this Zig object as input to the `fopen()` C function.\n\nIf we do this, the program still compiles and runs successfully. Notice that I have omitted most of the code in this example below.\nThis is just for brevity reasons, because the remainder of the program is still the same.\nThe only difference between this example and the previous one is just these two lines exposed below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path = \"foo.txt\";\n const file = c.fopen(path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\nNow, what happens if you give an explicit data type to the `path` object? Well, if I force\nthe `zig` compiler to interpret this `path` object as a Zig string object,\nby annotating the `path` object with the data type `[]const u8`, then, I actually get a compile error\nas demonstrated below. We get this compile error because now I'm forcing the `zig` compiler\nto interpret `path` as a Zig string object.\n\nAccording to the error message, the `fopen()` C function was expecting to receive an\ninput value of type `[*c]const u8` (C string) instead of a value of type `[]const u8` (Zig string).\nIn more details, the type `[*c]const u8` is actually the Zig type representation of a C string.\nThe `[*c]` portion of this type identifies a C pointer. So, this Zig type essentially means: a C pointer to an array (`[*c]`) of\nconstant bytes (`const u8`).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const file = c.fopen(path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\n```\nt.zig:2:7 error: expected type '[*c]const u8', found '[]const u8':\n const file = c.fopen(path, \"rb\");\n ^~~~\n```\n\nTherefore, when we talk exclusively about string literal values, as long as you don't give an\nexplicit data type to these string literal values, the `zig` compiler should be capable of automatically\nconverting them into C strings as needed.\n\nBut what about using one of the primitive data types that were introduced at @sec-primitive-data-types?\nLet's take code exposed below as an example of that. Here, we are giving some float literal values as input\nto the C function `powf()`. Notice that this code example compiles and runs successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst cmath = @cImport({\n @cInclude(\"math.h\");\n});\n\npub fn main() !void {\n const y = cmath.powf(15.68, 2.32);\n try stdout.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n```\n593.2023\n```\n\nOnce again, because the `zig` compiler does not associate a specific data type with the literal values\n`15.68` and `2.32` at first glance, the compiler can automatically convert these values\ninto their C `float` (or `double`) equivalents, before it passes to the `powf()` C function.\nNow, even if I give an explicit Zig data type to these literal values, by storing them into a Zig object,\nand explicit annotating the type of these objects, the code still compiles and runs successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const x: f32 = 15.68;\n const y = cmath.powf(x, 2.32);\n // The remainder of the program\n```\n:::\n\n\n\n\n```\n593.2023\n```\n\n\n\n### The \"need-conversion\" scenario\n\nA \"need-conversion\" scenario is when we need to manually convert our Zig objects into C compatible values\nbefore passing them as input to C functions. You will fall in this scenario, when passing Zig string objects\nto C functions.\n\nWe have already seen this specific circumstance in the last `fopen()` example,\nwhich is reproduced below. You can see in this example, that we have given an explicit Zig data type\n(`[]const u8`) to our `path` object, and, as a consequence of that, we have forced the `zig` compiler\nto see this `path` object, as a Zig string object. Therefore, we need now to manually convert\nthis `path` object into a C string before we pass it to `fopen()`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const file = c.fopen(path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\n```\nt.zig:10:26: error: expected type '[*c]const u8', found '[]const u8'\n const file = c.fopen(path, \"rb\");\n ^~~~\n```\n\n\nThere are different ways to convert a Zig string object into a C string.\nOne way to solve this problem is to provide the pointer to the underlying array\nof bytes, instead of providing the Zig object directly as input.\nYou can access this pointer by using the `ptr` property of the Zig string object.\n\nThe code example below demonstrates this strategy. Notice that, by giving the\npointer to the underlying array in `path` through the `ptr` property, we get no compile errors as result\nwhile using the `fopen()` C function.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const file = c.fopen(path.ptr, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\nThis strategy works because this pointer to the underlying array found in the `ptr` property,\nis semantically identical to a C pointer to an array of bytes, i.e. a C object of type `*unsigned char`.\nThis is why this option also solves the problem of converting the Zig string into a C string.\n\nAnother option is to explicitly convert the Zig string object into a C pointer by using the\nbuilt-in function `@ptrCast()`. With this function we can convert\nan object of type `[]const u8` into an object of type `[*c]const u8`.\nAs I described at the previous section, the `[*c]` portion of the type\nmeans that it is a C pointer. This strategy is not-recommended. But it is\nuseful to demonstrate the use of `@ptrCast()`.\n\nYou may recall of `@as()` and `@ptrCast()` from @sec-type-cast. Just as a recap,\nthe `@as()` built-in function is used to explicitly convert (or cast) a Zig value\nfrom a type \"x\" into a value of type \"y\". But in our case here, we are converting\na pointer object. Everytime a pointer is involved in some \"type casting operation\" in Zig,\nthe `@ptrCast()` function is involved.\n\nIn the example below, we are using this function to cast our `path` object\ninto a C pointer to an array of bytes. Then, we pass this C pointer as input\nto the `fopen()` function. Notice that this code example compiles successfully\nwith no errors.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const c_path: [*c]const u8 = @ptrCast(path);\n const file = c.fopen(c_path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\n\n\n## Creating C objects in Zig {#sec-c-inputs}\n\nCreating C objects, or, in other words, creating instances of C structs in your Zig code\nis actually something quite easy to do. You first need to import the C header file (like I described at @sec-import-c-header) that defines\nthe C struct that you are trying to instantiate in your Zig code. After that, you can just\ncreate a new object in your Zig code, and annotate it with the data type of the C struct.\n\nFor example, suppose we have a C header file called `user.h`, and that this header file is declaring a new struct named `User`.\nThis C header file is exposed below:\n\n```c\n#include \n\ntypedef struct {\n uint64_t id;\n char* name;\n} User;\n```\n\nThis `User` C struct have two distinct fields, or two struct members, named `id` and `name`.\nThe field `id` is an unsigned 64-bit integer value, while the field `name` is just a standard C string.\nNow, suppose that I want to create an instance of this `User` struct in my Zig code.\nI can do that by importing this `user.h` header file into my Zig code, and creating\na new object with type `User`. These steps are reproduced in the code example below.\n\nNotice that I have used the keyword `undefined` in this example. This allows me to\ncreate the `new_user` object without the need to provide an initial value to the object.\nAs consequence, the underlying memory associated with this `new_user` object is uninitialized,\ni.e. the memory is currently populated with \"garbage\" values.\nThus, this expression have the exact same effect of the expression `User new_user;` in C,\nwhich means \"declare a new object named `new_user` of type `User`\".\n\nIs our responsibility to properly initialize this memory associated with this `new_user` object,\nby assigning valid values to the members (or the fields) of the C struct. In the example below,\nI'm assigning the integer 1 to the member `id`. I am also saving the string `\"pedropark99\"` into the member `name`.\nNotice in this example that I manually add the null character (zero byte) to the end of the allocated array\nfor this string. This null character marks the end of the array in C.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst c = @cImport({\n @cInclude(\"user.h\");\n});\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n\n var new_user: c.User = undefined;\n new_user.id = 1;\n var user_name = try allocator.alloc(u8, 12);\n defer allocator.free(user_name);\n @memcpy(user_name[0..(user_name.len - 1)], \"pedropark99\");\n user_name[user_name.len - 1] = 0;\n new_user.name = user_name.ptr;\n}\n```\n:::\n\n\n\n\nSo, in this example above, we are manually initializing each field of the C struct.\nWe could say that, in this instance, we are \"manually instantiating\nthe C struct object\". However, when we use C libraries in our Zig code, we rarely need\nto manually instantiate the C structs like that. Only because C libraries\nusually provide a \"constructor function\" in their public APIs. As consequence, we normally rely on\nthese constructor functions to properly initialize the C structs, and\nthe struct fields for us.\n\nFor example, consider the Harfbuzz C library. This a text shaping C library,\nand it works around a \"buffer object\", or, more specifically, an instance of\nthe C struct `hb_buffer_t`. Therefore, we need to create an instance of\nthis C struct if we want to use this C library. Luckily, this library offers\nthe function `hb_buffer_create()`, which we can use to create such object.\nSo the Zig code necessary to create such object would probably look something like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cInclude(\"hb.h\");\n});\nvar buf: c.hb_buffer_t = c.hb_buffer_create();\n// Do stuff with the \"buffer object\"\n```\n:::\n\n\n\n\nTherefore, we do not need to manually create an instance of the C struct\n`hb_buffer_t` here, and manually assign valid values to each field in this C struct.\nBecause the constructor function `hb_buffer_create()` is doing this heavy job for us.\n\nSince this `buf` object, and also, the `new_user` object from previous examples, are instances of C structs, these\nobjects are by themselves C compatible values. They are C objects defined in our Zig code. As consequence,\nyou can freely pass these objects as input to any C function that expects to receive this type\nof C struct as input. You do not need to use any special syntax, or, to convert them in\nany special manner to use them in C code. This is how we create and use C objects in our Zig code.\n\n\n\n## Passing C structs across Zig functions {#sec-pass-c-structs}\n\nNow that we have learned how to create/declare C objects in our Zig code, we\nneed to learn how to pass these C objects as inputs to Zig functions.\nAs I described at @sec-c-inputs, we can freely pass these C objects as inputs to C code\nthat we call from our Zig code. But what about passing these C objects to Zig functions?\n\nIn essence, this specific case requires one small adjustment in the Zig function declaration.\nAll you need to do, is to make sure that you pass your C object *by reference* to the function,\ninstead of passing it *by value*. To do that, you have to annotate the data type of the function argument\nthat is receiving this C object as \"a pointer to the C struct\", instead of annotating it as \"an instance of the C struct\".\n\nLet's consider the C struct `User` from the `user.h` C header file that we have used at @sec-c-inputs.\nNow, consider that we want to create a Zig function that sets the value of the `id` field\nin this C struct, like the `set_user_id()` function declared below.\nNotice that the `user` argument in this function is annotated as a pointer (`*`) to a `c.User` object.\n\nTherefore, all you have to do when passing C objects to Zig functions, is to add `*` to the\ndata type of the function argument that is receiving the C object. This will make sure that\nthe C object is passed *by reference* to the function.\n\nBecause we have transformed the function argument into a pointer,\neverytime that you have to access the value pointed by this input pointer inside the function body, for whatever reason (e.g. you want\nto read, update, or delete this value), you have to dereference the pointer with the `.*` syntax that we\nlearned from @sec-pointer. Notice that the `set_user_id()` function is using this syntax to alter\nthe value in the `id` field of the `User` struct pointed by the input pointer.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst c = @cImport({\n @cInclude(\"user.h\");\n});\nfn set_user_id(id: u64, user: *c.User) void {\n user.*.id = id;\n}\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n\n var new_user: c.User = undefined;\n new_user.id = 1;\n var user_name = try allocator.alloc(u8, 12);\n defer allocator.free(user_name);\n @memcpy(user_name[0..(user_name.len - 1)], \"pedropark99\");\n user_name[user_name.len - 1] = 0;\n new_user.name = user_name.ptr;\n\n set_user_id(25, &new_user);\n try stdout.print(\"New ID: {any}\\n\", .{new_user.id});\n}\n```\n:::\n\n\n\n\n```\nNew ID: 25\n```\n\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Zig interoperability with C\n\nIn this chapter, we are going to discuss the interoperability of Zig with C.\nWe have discussed in @sec-building-c-code how you can use the `zig` compiler to build C code.\nBut we haven't discussed yet how to actually use C code in Zig. In other words,\nwe haven't discussed yet how to call and use C code from Zig.\n\nThis is the main subject of this chapter.\nAlso, in our next small project in this book, we are going to use a C library in it.\nAs consequence, we will put in practice a lot of the knowledge discussed here on\nthis next project.\n\n\n## How to call C code from Zig\n\nInteroperability with C is not something new. Most high-level programming languages have FFI (foreign function interfaces),\nwhich can be used to call C code. For example, Python have Cython, R have `.Call()`, Javascript have `ccall()`, etc.\nBut Zig integrates with C in a deeper level, which affects not only the way that C code gets called, but also,\nhow this C code is compiled and incorporated into your Zig project.\n\nIn summary, Zig have great interoperability with C. If you want to call any C code from Zig,\nyou have to perform the following steps:\n\n- import a C header file into your Zig code.\n- link your Zig code with the C library.\n\n\n### Strategies to import C header files {#sec-strategy-c}\n\nUsing C code in Zig always involves performing the two steps cited above. However, when\nwe talk specifically about the first step listed above, there are currently two\ndifferent ways to perform this first step, which are:\n\n- translating the C header file into Zig code, through the `zig translate-c` command, and then, import and use the translated Zig code.\n- importing the C header file directly into your Zig module through the `@cImport()` built-in function.\n\nIf you are not familiar with `translate-c`, this is a subcommand inside the `zig` compiler that takes C files\nas input, and outputs the Zig representation of the C code present in these C files.\nIn other words, this subcommand works like a transpiler. It takes C code, and translates it into\nthe equivalent Zig code.\n\nI think it would be ok to interpret `translate-c` as a tool to generate Zig bindings\nto C code, similarly to the `rust-bindgen`[^bindgen] tool, which generates Rust FFI bindings to C code.\nBut that would not be a precise interpretation of `translate-c`. The idea behind this tool is\nto really translate the C code into Zig code.\n\n[^bindgen]: \n\nNow, on a surface level, `@cImport()` versus `translate-c` might seem like\ntwo completely different strategies. But in fact, they are effectively the exact same strategy.\nBecause, under the hood, the `@cImport()` built-in function is just a shortcut to `translate-c`.\nBoth tools use the same \"C to Zig\" translation functionality. So when you use `@cImport()`,\nyou are essentially asking the `zig` compiler to translate the C header file into Zig code, then,\nto import this Zig code into your current Zig module.\n\nAt the present moment, there is an accepted proposal at the Zig project, to move `@cImport()`\nto the Zig build system[^cimport-issue]. If this proposal is completed, then, the \"use `@cImport()`\"\nstrategy would be transformed into \"call a translate C function in your Zig build script\".\nSo, the step of translating the C code into Zig code would be moved to\nthe build script of your Zig project, and you would only need to import the translated Zig code into\nyour Zig module to start calling C code from Zig.\n\n[^cimport-issue]: \n\nIf you think about this proposal for a minute, you will understand that this is actually\na small change. I mean, the logic is the same, and the steps are still essentially the same.\nThe only difference is that one of the steps will be moved to the build script of your Zig project.\n\n\n\n### Linking Zig code with a C library {#sec-linking-c}\n\nRegardless of which of the two strategies from the previous section you choose,\nif you want to call C code from Zig, you must link your Zig code\nwith the C library that contains the C code that you want to call.\n\nIn other words, everytime you use some C code in your Zig code, **you introduce a dependency in your build process**.\nThis should come as no surprise to anyone that have any experience with C and C++.\nBecause this is no different in C. Everytime you use a C library in your C code, you also\nhave to build and link your C code with this C library that you are using.\n\nWhen we use a C library in our Zig code, the `zig` compiler needs to access the definition of the C functions that\nare being called in your Zig code. The C header file of this library provides the\ndeclarations of these C functions, but not their definitions. So, in order to access these definitions,\nthe `zig` compiler needs to build your Zig code and link it with the C library during the build process.\n\nAs we discussed across the @sec-build-system, there are different strategies to link something with a library.\nThis might involve building the C library first, and then, linking it with the Zig code. Or,\nit could also involve just the linking step, if this C library is already built and\ninstalled in your system. Anyway, if you have doubts about this, comeback to @sec-build-system.\n\n\n\n## Importing C header files {#sec-import-c-header}\n\nIn @sec-strategy-c, we have described that, currently, there are two different paths that\nyou can take to import a C header file into your Zig modules, `translate-c` or `@cImport()`.\nThis section describes each strategy separately in more details.\n\n### Strategy 1: using `translate-c`\n\nWhen we choose this strategy, we first need to use the `translate-c` tool to translate\nthe C header files that we want to use into Zig code. For example, suppose we wanted to\nuse the `fopen()` C function from the `stdio.h` C header file. We can translate the\n`stdio.h` C header file through the bash command below:\n\n```bash\nzig translate-c /usr/include/stdio.h \\\n -lc -I/usr/include \\\n -D_NO_CRT_STDIO_INLINE=1 > c.zig \\\n```\n\nNotice that, in this bash command, we are passing the necessary compiler flags (`-D` to define macros,\n`-l` to link libraries, `-I` to add an \"include path\") to compile and use the `stdio.h` header file.\nAlso notice that we are saving the results of the translation process inside a Zig module called `c.zig`.\n\nTherefore, after running this command, all we have to do is to import this `c.zig` module, and start\ncalling the C functions that you want to call from it. The example below demonstrates that.\nIt's important to remember what we've discussed in @sec-linking-c. In order to compile this\nexample you have to link this code with `libc`, by passing the flag `-lc` to the `zig` compiler.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @import(\"c.zig\");\npub fn main() !void {\n const x: f32 = 1772.94122;\n _ = c.printf(\"%.3f\\n\", x);\n}\n```\n:::\n\n\n\n\n```\n1772.941\n```\n\n\n### Strategy 2: using `@cImport()`\n\nTo import a C header file into our Zig code, we can use the built-in functions `@cInclude()` and `@cImport()`.\nInside the `@cImport()` function, we open a block (with a pair of curly braces). Inside this block\nwe can (if we need to) include multiple `@cDefine()` calls to define C macros when including this specific C header file.\nBut for the most part, you will probably need to use just a single call inside this block,\nwhich is a call to `@cInclude()`.\n\nThis `@cInclude()` function is equivalent to the `#include` statement in C.\nYou provide the name of the C header that you want to include as input to this `@cInclude()` function,\nthen, in conjunction with `@cImport()`, it will perform the necessary steps\nto include this C header file into your Zig code.\n\nYou should bind the result of `@cImport()` to a constant object, pretty much like you would do with\n`@import()`. You just assign the result to a constant object in your\nZig code, and, as consequence, all C functions, C structs, C macros, etc. that are defined inside the\nC header files will be available through this constant object.\n\nLook at the code example below, where we are importing the Standard I/O C Library (`stdio.h`),\nand calling the `printf()`[^printf] C function. Notice that we have also used in this example the C function `powf()`[^powf],\nwhich comes from the C Math Library (`math.h`).\nIn order to compile this example, you have to link this Zig code with both\nthe C Standard Library and the C Math Library, by passing the flags `-lc` and `-lm`\nto the `zig` compiler.\n\n[^printf]: \n[^powf]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cDefine(\"_NO_CRT_STDIO_INLINE\", \"1\");\n @cInclude(\"stdio.h\");\n @cInclude(\"math.h\");\n});\n\npub fn main() !void {\n const x: f32 = 15.2;\n const y = c.powf(x, @as(f32, 2.6));\n _ = c.printf(\"%.3f\\n\", y);\n}\n```\n:::\n\n\n\n\n```\n1182.478\n```\n\n\n## About passing Zig values to C functions {#sec-zig-obj-to-c}\n\nZig objects have some intrinsic differences between their C equivalents.\nProbably the most noticeable one is the difference between C strings and Zig strings,\nwhich I described in @sec-zig-strings.\nZig strings are objects that contains both an array of arbitrary bytes and a length value.\nOn the other hand, a C string is usually just a pointer to a null-terminated array of arbitrary bytes.\n\nBecause of these intrinsic differences, in some specific cases, you cannot pass Zig objects directly\nas inputs to C functions before you convert them into C compatible values. However, in some other cases,\nyou are allowed to pass Zig objects and Zig literal values directly as inputs to C functions,\nand everything will work just fine, because the `zig` compiler will handle everything for you.\n\nSo we have two different scenarios being described here. Let's call them \"auto-conversion\" and \"need-conversion\".\nThe \"auto-conversion\" scenario is when the `zig` compiler handles everything for you, and automatically convert your\nZig objects/values into C compatible values. In contrast,\nthe \"need-conversion\" scenario is when you, the programmer, have the responsibility of converting\nthat Zig object into a C compatible value, before passing it to C code.\n\nThere is also a third scenario that is not being described here, which is when you create a C object, or, a C struct, or\na C compatible value in your Zig code, and you pass this C object/value as input to a C function in your Zig code.\nThis scenario will be described later in @sec-c-inputs. In this section, we are focused on the scenarios where\nwe are passing Zig objects/values to C code, instead of C objects/values being passed to C code.\n\n\n### The \"auto-conversion\" scenario\n\nAn \"auto-conversion\" scenario is when the `zig` compiler automatically converts our Zig objects into\nC compatible values for us. This specific scenario happens mostly in two instances:\n\n- with string literal values;\n- with any of the primitive data types that were introduced in @sec-primitive-data-types.\n\nWhen we think about the second instance described above, the `zig` compiler does automatically\nconvert any of the primitive data types into their C equivalents, because the compiler knows how\nto properly convert a `i16` into a `signed short`, or, a `u8` into a `unsigned char`, etc.\nNow, when we think about string literal values, they can be automatically\nconverted into C strings as well, especially because the `zig` compiler does not forces\na specific Zig data type into a string literal at first glance, unless you store this\nstring literal into a Zig object, and explicitly annotate the data type of this object.\n\nThus, with string literal values, the `zig` compiler has more freedom to infer which is the appropriate data type\nto be used in each situation. You could say that the string literal value \"inherits its data type\" depending on the context that\nit's used in. Most of the times, this data type is going to be the type that we commonly associate with Zig strings (`[]const u8`).\nBut it might be a different type depending on the situation. When the `zig` compiler detects that you are providing\na string literal value as input to some C function, the compiler automatically interprets this string\nliteral as a C string value.\n\nAs an example, look at the code exposed below. Here we are using\nthe `fopen()` C function to simply open and close a file. If you do not know how this `fopen()`\nfunction works in C, it takes two C strings as input. But in this code example below, we are passing some\nstring literals written in our Zig code directly as inputs to this `fopen()` C function.\n\nIn other words, we are not doing any conversion from a Zig string to a C string.\nWe are just passing the Zig string literals directly as inputs to the C function. And it works just fine!\nBecause the compiler interprets the string `\"foo.txt\"` as a C string given the current context.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cDefine(\"_NO_CRT_STDIO_INLINE\", \"1\");\n @cInclude(\"stdio.h\");\n});\n\npub fn main() !void {\n const file = c.fopen(\"foo.txt\", \"rb\");\n if (file == null) {\n @panic(\"Could not open file!\");\n }\n if (c.fclose(file) != 0) {\n return error.CouldNotCloseFileDescriptor;\n }\n}\n```\n:::\n\n\n\n\nLet's make some experiments, by writing the same code in different manners, and we\nsee how this affects the program. As a starting point, let's store the `\"foo.txt\"` string inside\na Zig object, like the `path` object below, and then, we pass this Zig object as input to the `fopen()` C function.\n\nIf we do this, the program still compiles and runs successfully. Notice that I have omitted most of the code in this example below.\nThis is just for brevity reasons, because the remainder of the program is still the same.\nThe only difference between this example and the previous one is just these two lines exposed below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path = \"foo.txt\";\n const file = c.fopen(path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\nNow, what happens if you give an explicit data type to the `path` object? Well, if I force\nthe `zig` compiler to interpret this `path` object as a Zig string object,\nby annotating the `path` object with the data type `[]const u8`, then, I actually get a compile error\nas demonstrated below. We get this compile error because now I'm forcing the `zig` compiler\nto interpret `path` as a Zig string object.\n\nAccording to the error message, the `fopen()` C function was expecting to receive an\ninput value of type `[*c]const u8` (C string) instead of a value of type `[]const u8` (Zig string).\nIn more details, the type `[*c]const u8` is actually the Zig type representation of a C string.\nThe `[*c]` portion of this type identifies a C pointer. So, this Zig type essentially means: a C pointer to an array (`[*c]`) of\nconstant bytes (`const u8`).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const file = c.fopen(path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\n```\nt.zig:2:7 error: expected type '[*c]const u8', found '[]const u8':\n const file = c.fopen(path, \"rb\");\n ^~~~\n```\n\nTherefore, when we talk exclusively about string literal values, as long as you don't give an\nexplicit data type to these string literal values, the `zig` compiler should be capable of automatically\nconverting them into C strings as needed.\n\nBut what about using one of the primitive data types that were introduced in @sec-primitive-data-types?\nLet's take code exposed below as an example of that. Here, we are giving some float literal values as input\nto the C function `powf()`. Notice that this code example compiles and runs successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst cmath = @cImport({\n @cInclude(\"math.h\");\n});\n\npub fn main() !void {\n const y = cmath.powf(15.68, 2.32);\n try stdout.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n```\n593.2023\n```\n\nOnce again, because the `zig` compiler does not associate a specific data type with the literal values\n`15.68` and `2.32` at first glance, the compiler can automatically convert these values\ninto their C `float` (or `double`) equivalents, before it passes to the `powf()` C function.\nNow, even if I give an explicit Zig data type to these literal values, by storing them into a Zig object,\nand explicit annotating the type of these objects, the code still compiles and runs successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const x: f32 = 15.68;\n const y = cmath.powf(x, 2.32);\n // The remainder of the program\n```\n:::\n\n\n\n\n```\n593.2023\n```\n\n\n\n### The \"need-conversion\" scenario\n\nA \"need-conversion\" scenario is when we need to manually convert our Zig objects into C compatible values\nbefore passing them as input to C functions. You will fall in this scenario, when passing Zig string objects\nto C functions.\n\nWe have already seen this specific circumstance in the last `fopen()` example,\nwhich is reproduced below. You can see in this example, that we have given an explicit Zig data type\n(`[]const u8`) to our `path` object, and, as a consequence of that, we have forced the `zig` compiler\nto see this `path` object, as a Zig string object. Therefore, we need now to manually convert\nthis `path` object into a C string before we pass it to `fopen()`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const file = c.fopen(path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\n```\nt.zig:10:26: error: expected type '[*c]const u8', found '[]const u8'\n const file = c.fopen(path, \"rb\");\n ^~~~\n```\n\n\nThere are different ways to convert a Zig string object into a C string.\nOne way to solve this problem is to provide the pointer to the underlying array\nof bytes, instead of providing the Zig object directly as input.\nYou can access this pointer by using the `ptr` property of the Zig string object.\n\nThe code example below demonstrates this strategy. Notice that, by giving the\npointer to the underlying array in `path` through the `ptr` property, we get no compile errors as result\nwhile using the `fopen()` C function.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const file = c.fopen(path.ptr, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\nThis strategy works because this pointer to the underlying array found in the `ptr` property,\nis semantically identical to a C pointer to an array of bytes, i.e., a C object of type `*unsigned char`.\nThis is why this option also solves the problem of converting the Zig string into a C string.\n\nAnother option is to explicitly convert the Zig string object into a C pointer by using the\nbuilt-in function `@ptrCast()`. With this function we can convert\nan object of type `[]const u8` into an object of type `[*c]const u8`.\nAs I described at the previous section, the `[*c]` portion of the type\nmeans that it's a C pointer. This strategy is not-recommended. But it's\nuseful to demonstrate the use of `@ptrCast()`.\n\nYou may recall of `@as()` and `@ptrCast()` from @sec-type-cast. Just as a recap,\nthe `@as()` built-in function is used to explicitly convert (or cast) a Zig value\nfrom a type \"x\" into a value of type \"y\". But in our case here, we are converting\na pointer object. Everytime a pointer is involved in some \"type casting operation\" in Zig,\nthe `@ptrCast()` function is involved.\n\nIn the example below, we are using this function to cast our `path` object\ninto a C pointer to an array of bytes. Then, we pass this C pointer as input\nto the `fopen()` function. Notice that this code example compiles successfully\nwith no errors.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const c_path: [*c]const u8 = @ptrCast(path);\n const file = c.fopen(c_path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\n\n\n## Creating C objects in Zig {#sec-c-inputs}\n\nCreating C objects, or, in other words, creating instances of C structs in your Zig code\nis actually something quite easy to do. You first need to import the C header file (like I described in @sec-import-c-header) that defines\nthe C struct that you are trying to instantiate in your Zig code. After that, you can just\ncreate a new object in your Zig code, and annotate it with the data type of the C struct.\n\nFor example, suppose we have a C header file called `user.h`, and that this header file is declaring a new struct named `User`.\nThis C header file is exposed below:\n\n```c\n#include \n\ntypedef struct {\n uint64_t id;\n char* name;\n} User;\n```\n\nThis `User` C struct have two distinct fields, or two struct members, named `id` and `name`.\nThe field `id` is an unsigned 64-bit integer value, while the field `name` is just a standard C string.\nNow, suppose that I want to create an instance of this `User` struct in my Zig code.\nI can do that by importing this `user.h` header file into my Zig code, and creating\na new object with type `User`. These steps are reproduced in the code example below.\n\nNotice that I have used the keyword `undefined` in this example. This allows me to\ncreate the `new_user` object without the need to provide an initial value to the object.\nAs consequence, the underlying memory associated with this `new_user` object is uninitialized,\ni.e., the memory is currently populated with \"garbage\" values.\nThus, this expression have the exact same effect of the expression `User new_user;` in C,\nwhich means \"declare a new object named `new_user` of type `User`\".\n\nIt's our responsibility to properly initialize this memory associated with this `new_user` object,\nby assigning valid values to the members (or the fields) of the C struct. In the example below,\nI'm assigning the integer 1 to the member `id`. I am also saving the string `\"pedropark99\"` into the member `name`.\nNotice in this example that I manually add the null character (zero byte) to the end of the allocated array\nfor this string. This null character marks the end of the array in C.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst c = @cImport({\n @cInclude(\"user.h\");\n});\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n\n var new_user: c.User = undefined;\n new_user.id = 1;\n var user_name = try allocator.alloc(u8, 12);\n defer allocator.free(user_name);\n @memcpy(user_name[0..(user_name.len - 1)], \"pedropark99\");\n user_name[user_name.len - 1] = 0;\n new_user.name = user_name.ptr;\n}\n```\n:::\n\n\n\n\nSo, in this example above, we are manually initializing each field of the C struct.\nWe could say that, in this instance, we are \"manually instantiating\nthe C struct object\". However, when we use C libraries in our Zig code, we rarely need\nto manually instantiate the C structs like that. Only because C libraries\nusually provide a \"constructor function\" in their public APIs. As consequence, we normally rely on\nthese constructor functions to properly initialize the C structs, and\nthe struct fields for us.\n\nFor example, consider the Harfbuzz C library. This a text shaping C library,\nand it works around a \"buffer object\", or, more specifically, an instance of\nthe C struct `hb_buffer_t`. Therefore, we need to create an instance of\nthis C struct if we want to use this C library. Luckily, this library offers\nthe function `hb_buffer_create()`, which we can use to create such object.\nSo the Zig code necessary to create such object would probably look something like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cInclude(\"hb.h\");\n});\nvar buf: c.hb_buffer_t = c.hb_buffer_create();\n// Do stuff with the \"buffer object\"\n```\n:::\n\n\n\n\nTherefore, we do not need to manually create an instance of the C struct\n`hb_buffer_t` here, and manually assign valid values to each field in this C struct.\nBecause the constructor function `hb_buffer_create()` is doing this heavy job for us.\n\nSince this `buf` object, and also, the `new_user` object from previous examples, are instances of C structs, these\nobjects are by themselves C compatible values. They are C objects defined in our Zig code. As consequence,\nyou can freely pass these objects as input to any C function that expects to receive this type\nof C struct as input. You do not need to use any special syntax, or, to convert them in\nany special manner to use them in C code. This is how we create and use C objects in our Zig code.\n\n\n\n## Passing C structs across Zig functions {#sec-pass-c-structs}\n\nNow that we have learned how to create/declare C objects in our Zig code, we\nneed to learn how to pass these C objects as inputs to Zig functions.\nAs I described in @sec-c-inputs, we can freely pass these C objects as inputs to C code\nthat we call from our Zig code. But what about passing these C objects to Zig functions?\n\nIn essence, this specific case requires one small adjustment in the Zig function declaration.\nAll you need to do, is to make sure that you pass your C object *by reference* to the function,\ninstead of passing it *by value*. To do that, you have to annotate the data type of the function argument\nthat is receiving this C object as \"a pointer to the C struct\", instead of annotating it as \"an instance of the C struct\".\n\nLet's consider the C struct `User` from the `user.h` C header file that we have used in @sec-c-inputs.\nNow, consider that we want to create a Zig function that sets the value of the `id` field\nin this C struct, like the `set_user_id()` function declared below.\nNotice that the `user` argument in this function is annotated as a pointer (`*`) to a `c.User` object.\n\nTherefore, all you have to do when passing C objects to Zig functions, is to add `*` to the\ndata type of the function argument that is receiving the C object. This will make sure that\nthe C object is passed *by reference* to the function.\n\nBecause we have transformed the function argument into a pointer,\neverytime that you have to access the value pointed by this input pointer inside the function body, for whatever reason (e.g. you want\nto read, update, or delete this value), you have to dereference the pointer with the `.*` syntax that we\nlearned from @sec-pointer. Notice that the `set_user_id()` function is using this syntax to alter\nthe value in the `id` field of the `User` struct pointed by the input pointer.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst c = @cImport({\n @cInclude(\"user.h\");\n});\nfn set_user_id(id: u64, user: *c.User) void {\n user.*.id = id;\n}\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n\n var new_user: c.User = undefined;\n new_user.id = 1;\n var user_name = try allocator.alloc(u8, 12);\n defer allocator.free(user_name);\n @memcpy(user_name[0..(user_name.len - 1)], \"pedropark99\");\n user_name[user_name.len - 1] = 0;\n new_user.name = user_name.ptr;\n\n set_user_id(25, &new_user);\n try stdout.print(\"New ID: {any}\\n\", .{new_user.id});\n}\n```\n:::\n\n\n\n\n```\nNew ID: 25\n```\n", + "supporting": [ + "14-zig-c-interop_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/15-vectors/execute-results/html.json b/_freeze/Chapters/15-vectors/execute-results/html.json index 3b0c6a8d..d68d2db0 100644 --- a/_freeze/Chapters/15-vectors/execute-results/html.json +++ b/_freeze/Chapters/15-vectors/execute-results/html.json @@ -1,9 +1,11 @@ { - "hash": "79d14ec3c3354d3a9fca4cbd05f42110", + "hash": "3da767c3f773d387d2d0a42df4405278", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Introducing Vectors and SIMD {#sec-vectors-simd}\n\nIn this chapter, I want to discuss vectors in Zig, which are\nrelated to SIMD operations (i.e. they have no relationship with the `std::vector` class\nfrom C++).\n\n## What is SIMD?\n\nSIMD (*Single Instruction/Multiple Data*) is a group of operations that are widely used\non video/audio editing programs, and also in graphics applications. SIMD is not a new technology,\nbut the massive use of SIMD on normal desktop computers is somewhat recent. In the old days, SIMD\nwas only used on \"supercomputer models\".\n\nMost modern CPU models (from AMD, Intel, etc.) these days (either in a desktop or in a\nnotebook model) have support for SIMD operations. So, if you have a very old CPU model installed in your\ncomputer, then, is possible that you have no support for SIMD operations in your computer.\n\nWhy people have started using SIMD on their software? The answer is performance.\nBut what SIMD precisely do to achieve better performance? Well, in essence, SIMD operations are a different\nstrategy to get parallel computing in your program, and therefore, make faster calculations.\n\nThe basic idea behind SIMD is to have a single instruction that operates over multiple data\nat the same time. When you perform a normal scalar operation, like for example, four add instructions,\neach addition is performed separately, one after another. But with SIMD, these four add instructions\nare translated into a single instruction, and, as consequence, the four additions are performed\nin parallel, at the same time.\n\nCurrently, the `zig` compiler allows you to apply the following group of operators on vector objects.\nWhen you apply one of these operators on vector objects, SIMD is used to make the calculations, and,\ntherefore, these operators are applied element-wise and in parallel by default.\n\n- Arithmetic (`+`, `-`, `/`, `*`, `@divFloor()`, `@sqrt()`, `@ceil()`, `@log()`, etc.).\n- Bitwise operators (`>>`, `<<`, `&`, `|`, `~`, etc.).\n- Comparison operators (`<`, `>`, `==`, etc.).\n\n\n## Vectors {#sec-what-vectors}\n\nA SIMD operation is usually performed through a *SIMD intrinsic*, which is just a fancy\nname for a function that performs a SIMD operation. These SIMD intrinsics (or \"SIMD functions\")\nalways operate over a special type of object, which are called \"vectors\". So,\nin order to use SIMD, you have to create a \"vector object\".\n\nA vector object is usually a fixed-sized block of 128 bits (16 bytes).\nAs consequence, most vectors that you find in the wild are essentially arrays that contains 2 values of 8 bytes each,\nor, 4 values of 4 bytes each, or, 8 values of 2 bytes each, etc.\nHowever, different CPU models may have different extensions (or, \"implementations\") of SIMD,\nwhich may offer more types of vector objects that are bigger in size (256 bits or 512 bits)\nto accomodate more data into a single vector object.\n\nYou can create a new vector object in Zig by using the `@Vector()` built-in function. Inside this function,\nyou specify the vector length (number of elements in the vector), and the data type of the elements\nof the vector. Only primitive data types are supported in these vector objects.\nIn the example below, I'm creating two vector objects (`v1` and `v2`) of 4 elements of type `u32` each.\n\nAlso notice in the example below, that a third vector object (`v3`) is created from the\nsum of the previous two vector objects (`v1` plus `v2`). Therefore,\nmath operations over vector objects take place element-wise by default, because\nthe same operation (in this case, addition) is transformed into a single instruction\nthat is replicated in parallel, across all elements of the vectors.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = @Vector(4, u32){4, 12, 37, 9};\nconst v2 = @Vector(4, u32){10, 22, 5, 12};\nconst v3 = v1 + v2;\ntry stdout.print(\"{any}\\n\", .{v3});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 14, 34, 42, 21 }\n```\n\n\n:::\n:::\n\n\n\n\nThis is how SIMD introduces more performance in your program. Instead of using a for loop\nto iterate through the elements of `v1` and `v2`, and adding them together, one element at a time,\nwe enjoy the benefits of SIMD, which performs all 4 additions in parallel, at the same time.\n\nTherefore, the `@Vector` structure is essentially the Zig representation of SIMD vector objects.\nThe elements on these vector objects will be operated in parallel, if, and only if your current CPU model\nsupports SIMD operations. If your CPU model does not have support for SIMD, then, the `@Vector` structure will\nlikely produce a similar performance from a \"for loop solution\".\n\n\n### Transforming arrays into vectors\n\nThere are different ways to transform a normal array into a vector object.\nYou can either use implicit conversion (which is when you assign the array to\na vector object directly), or, use slices to create a vector object from a normal array.\n\nIn the example below, we are implicitly converting the array `a1` into a vector object (`v1`)\nof length 4. We first explicitly annotate the data type of the vector object,\nand then, we assign the array object to this vector object.\n\nAlso notice in the example below, that a second vector object (`v2`) is also created\nby taking a slice of the array object (`a1`), and then, storing the pointer to this\nslice (`.*`) into this vector object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a1 = [4]u32{4, 12, 37, 9};\nconst v1: @Vector(4, u32) = a1;\nconst v2: @Vector(2, u32) = a1[1..3].*;\n_ = v1; _ = v2;\n```\n:::\n\n\n\n\n\nIs worth emphasizing that only arrays and slices whose sizes\nare compile-time known can be transformed into vectors. Vectors in general\nare structures that work only with compile-time known sizes. Therefore, if\nyou have an array whose size is runtime known, then, you first need to\ncopy it into an array with a compile-time known size, before transforming it into a vector.\n\n\n\n### The `@splat()` function\n\nYou can use the `@splat()` built-in function to create a vector object that is filled\nwith the same value across all of its elements. This function was created to offer a quick\nand easy way to directly convert a scalar value (a.k.a. a single value, like a single character, or a single integer, etc.)\ninto a vector object.\n\nThus, we can use `@splat()` to convert a single value, like the integer `16` into a vector object\nof length 1. But we can also use this function to convert the same integer `16` into a\nvector object of length 10, that is filled with 10 `16` values. The example below demonstrates\nthis idea.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1: @Vector(10, u32) = @splat(16);\ntry stdout.print(\"{any}\\n\", .{v1});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Careful with vectors that are too big\n\nAs I described at @sec-what-vectors, each vector object is usually a small block of 128, 256 or 512 bits.\nThis means that a vector object is usually small in size, and when you try to go in the opposite direction,\nby creating a vector object that is very big in size (i.e. sizes that are close to $2^{20}$),\nyou usually end up with crashes and loud errors from the compiler.\n\nFor example, if you try to compile the program below, you will likely face segmentation faults, or, LLVM errors during\nthe build process. Just be careful to not create vector objects that are too big in size.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1: @Vector(1000000, u32) = @splat(16);\n_ = v1;\n```\n:::\n\n\n\n\n```\nSegmentation fault (core dumped)\n```\n\n\n\n\n", - "supporting": [], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Introducing Vectors and SIMD {#sec-vectors-simd}\n\nIn this chapter, I want to discuss vectors in Zig, which are\nrelated to SIMD operations (i.e., they have no relationship with the `std::vector` class\nfrom C++).\n\n## What is SIMD?\n\nSIMD (*Single Instruction/Multiple Data*) is a group of operations that are widely used\non video/audio editing programs, and also in graphics applications. SIMD is not a new technology,\nbut the massive use of SIMD on normal desktop computers is somewhat recent. In the old days, SIMD\nwas only used on \"supercomputer models\".\n\nMost modern CPU models (from AMD, Intel, etc.) these days (either in a desktop or in a\nnotebook model) have support for SIMD operations. So, if you have a very old CPU model installed in your\ncomputer, then, it's possible that you have no support for SIMD operations in your computer.\n\nWhy have people started using SIMD in their software? The answer is performance.\nBut what does SIMD precisely do to achieve better performance? Well, in essence, SIMD operations are a different\nstrategy to get parallel computing in your program, and therefore, make faster calculations.\n\nThe basic idea behind SIMD is to have a single instruction that operates over multiple data\nat the same time. When you perform a normal scalar operation, like for example, four add instructions,\neach addition is performed separately, one after another. But with SIMD, these four add instructions\nare translated into a single instruction, and, as consequence, the four additions are performed\nin parallel, at the same time.\n\nCurrently, the `zig` compiler allows you to apply the following group of operators on vector objects.\nWhen you apply one of these operators on vector objects, SIMD is used to make the calculations, and,\ntherefore, these operators are applied element-wise and in parallel by default.\n\n- Arithmetic (`+`, `-`, `/`, `*`, `@divFloor()`, `@sqrt()`, `@ceil()`, `@log()`, etc.).\n- Bitwise operators (`>>`, `<<`, `&`, `|`, `~`, etc.).\n- Comparison operators (`<`, `>`, `==`, etc.).\n\n\n## Vectors {#sec-what-vectors}\n\nA SIMD operation is usually performed through a *SIMD intrinsic*, which is just a fancy\nname for a function that performs a SIMD operation. These SIMD intrinsics (or \"SIMD functions\")\nalways operate over a special type of object, which are called \"vectors\". So,\nin order to use SIMD, you have to create a \"vector object\".\n\nA vector object is usually a fixed-sized block of 128 bits (16 bytes).\nAs a consequence, most vectors that you find in the wild are essentially arrays that contains 2 values of 8 bytes each,\nor, 4 values of 4 bytes each, or, 8 values of 2 bytes each, etc.\nHowever, different CPU models may have different extensions (or, \"implementations\") of SIMD,\nwhich may offer more types of vector objects that are bigger in size (256 bits or 512 bits)\nto accomodate more data into a single vector object.\n\nYou can create a new vector object in Zig by using the `@Vector()` built-in function. Inside this function,\nyou specify the vector length (number of elements in the vector), and the data type of the elements\nof the vector. Only primitive data types are supported in these vector objects.\nIn the example below, I'm creating two vector objects (`v1` and `v2`) of 4 elements of type `u32` each.\n\nAlso notice in the example below, that a third vector object (`v3`) is created from the\nsum of the previous two vector objects (`v1` plus `v2`). Therefore,\nmath operations over vector objects take place element-wise by default, because\nthe same operation (in this case, addition) is transformed into a single instruction\nthat is replicated in parallel, across all elements of the vectors.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = @Vector(4, u32){4, 12, 37, 9};\nconst v2 = @Vector(4, u32){10, 22, 5, 12};\nconst v3 = v1 + v2;\ntry stdout.print(\"{any}\\n\", .{v3});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 14, 34, 42, 21 }\n```\n\n\n:::\n:::\n\n\n\n\nThis is how SIMD introduces more performance in your program. Instead of using a for loop\nto iterate through the elements of `v1` and `v2`, and adding them together, one element at a time,\nwe enjoy the benefits of SIMD, which performs all 4 additions in parallel, at the same time.\n\nTherefore, the `@Vector` structure is essentially the Zig representation of SIMD vector objects.\nThe elements in these vector objects will be operated in parallel, if, and only if your current CPU model\nsupports SIMD operations. If your CPU model does not have support for SIMD, then, the `@Vector` structure will\nlikely produce a similar performance from a \"for loop solution\".\n\n\n### Transforming arrays into vectors\n\nThere are different ways to transform a normal array into a vector object.\nYou can either use implicit conversion (which is when you assign the array to\na vector object directly), or, use slices to create a vector object from a normal array.\n\nIn the example below, we are implicitly converting the array `a1` into a vector object (`v1`)\nof length 4. We first explicitly annotate the data type of the vector object,\nand then, we assign the array object to this vector object.\n\nAlso notice in the example below, that a second vector object (`v2`) is also created\nby taking a slice of the array object (`a1`), and then, storing the pointer to this\nslice (`.*`) into this vector object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a1 = [4]u32{4, 12, 37, 9};\nconst v1: @Vector(4, u32) = a1;\nconst v2: @Vector(2, u32) = a1[1..3].*;\n_ = v1; _ = v2;\n```\n:::\n\n\n\n\n\nIt's worth emphasizing that only arrays and slices whose sizes\nare compile-time known can be transformed into vectors. Vectors in general\nare structures that work only with compile-time known sizes. Therefore, if\nyou have an array whose size is runtime known, then, you first need to\ncopy it into an array with a compile-time known size, before transforming it into a vector.\n\n\n\n### The `@splat()` function\n\nYou can use the `@splat()` built-in function to create a vector object that is filled\nwith the same value across all of its elements. This function was created to offer a quick\nand easy way to directly convert a scalar value (a.k.a. a single value, like a single character, or a single integer, etc.)\ninto a vector object.\n\nThus, we can use `@splat()` to convert a single value, like the integer `16` into a vector object\nof length 1. But we can also use this function to convert the same integer `16` into a\nvector object of length 10, that is filled with 10 `16` values. The example below demonstrates\nthis idea.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1: @Vector(10, u32) = @splat(16);\ntry stdout.print(\"{any}\\n\", .{v1});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Careful with vectors that are too big\n\nAs I described in @sec-what-vectors, each vector object is usually a small block of 128, 256 or 512 bits.\nThis means that a vector object is usually small in size, and when you try to go in the opposite direction,\nby creating a vector object that is very big in size (i.e., sizes that are close to $2^{20}$),\nyou usually end up with crashes and loud errors from the compiler.\n\nFor example, if you try to compile the program below, you will likely face segmentation faults, or LLVM errors during\nthe build process. Just be careful to not create vector objects that are too big in size.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1: @Vector(1000000, u32) = @splat(16);\n_ = v1;\n```\n:::\n\n\n\n\n```\nSegmentation fault (core dumped)\n```\n", + "supporting": [ + "15-vectors_files" + ], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/index/execute-results/html.json b/_freeze/index/execute-results/html.json index df53cb9c..9f591c93 100644 --- a/_freeze/index/execute-results/html.json +++ b/_freeze/index/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "b59fabe5a5ffda4f02945f654dba67de", + "hash": "335ac568e17c5057352e05da9521e5ae", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy\nof the book, either at Amazon, or at Leanpub:\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e. it is open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion)\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy\nof the book, either at Amazon, or at Leanpub:\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion), glystik (\\@glystik), Michael Lynch (\\@mtlynch)\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/contributors.txt b/contributors.txt index d3b64d0c..8a789f25 100644 --- a/contributors.txt +++ b/contributors.txt @@ -22,3 +22,5 @@ Jorge Jímenez,@jorge-j1m Alexander,@alexwheezy Maarten Coopens,@maarteNNNN Niklas Johansson,@Raphexion +glystik,@glystik +Michael Lynch,@mtlynch diff --git a/docs/Chapters/01-base64.html b/docs/Chapters/01-base64.html index 9e6d25c9..e32e01a4 100644 --- a/docs/Chapters/01-base64.html +++ b/docs/Chapters/01-base64.html @@ -385,7 +385,7 @@

    Section 4.2.

    4.1.1 The base64 scale

    -

    The base64 encoding system is based on a scale that goes from 0 to 63 (hence the name). Each index in this scale is represented by a character (it is a scale of 64 characters). So, in order to convert some binary data, to the base64 encoding, we need to convert each binary number to the corresponding character in this “scale of 64 characters”.

    +

    The base64 encoding system is based on a scale that goes from 0 to 63 (hence the name). Each index in this scale is represented by a character (it’s a scale of 64 characters). So, in order to convert some binary data, to the base64 encoding, we need to convert each binary number to the corresponding character in this “scale of 64 characters”.

    The base64 scale starts with all ASCII uppercase letters (A to Z) which represents the first 25 indexes in this scale (0 to 25). After that, we have all ASCII lowercase letters (a to z), which represents the range 26 to 51 in the scale. After that, we have the one digit numbers (0 to 9), which represents the indexes from 52 to 61 in the scale. Finally, the last two indexes in the scale (62 and 63) are represented by the characters + and /, respectively.

    These are the 64 characters that compose the base64 scale. The equal sign character (=) is not part of the scale itself, but it is a special character in the base64 encoding system. This character is used solely as a suffix, to mark the end of the character sequence, or, to mark the end of meaningful characters in the sequence.

    The bullet points below summarises the base64 scale:

    @@ -401,7 +401,7 @@

    4.1.2 Creating the scale as a lookup table

    The best way to represent this scale in code, is to represent it as a lookup table. Lookup tables are a classic strategy in computer science to speed up calculations. The basic idea is to replace a runtime calculation (which can take a long time to be done) with a basic array indexing operation.

    Instead of calculating the results everytime you need them, you calculate all possible results at once, and then, you store them in an array (which behaves lake a “table”). Then, every time you need to use one of the characters in the base64 scale, instead of using many resources to calculate the exact character to be used, you simply retrieve this character from the array where you stored all the possible characters in the base64 scale. We retrieve the character that we need directly from memory.

    -

    We can start building a Zig struct to store our base64 decoder/encoder logic. We start with the Base64 struct below. For now, we only have one single data member in this struct, i.e. the member _table, which represents our lookup table. We also have an init() method, to create a new instance of a Base64 object, and, a _char_at() method, which is a “get character at index \(x\)” type of function.

    +

    We can start building a Zig struct to store our base64 decoder/encoder logic. We start with the Base64 struct below. For now, we only have one single data member in this struct, i.e., the member _table, which represents our lookup table. We also have an init() method, to create a new instance of a Base64 object, and, a _char_at() method, which is a “get character at index \(x\)” type of function.

    const Base64 = struct {
         _table: *const [64]u8,
    @@ -420,7 +420,7 @@ 

    } };

    -

    In other words, the _char_at() method is responsible for getting the character in the lookup table (i.e. the _table struct data member) that corresponds to a particular index in the “base64 scale”. So, in the example below, we know that the character that corresponds to the index 28 in the “base64 scale” is the character “c”.

    +

    In other words, the _char_at() method is responsible for getting the character in the lookup table (i.e., the _table struct data member) that corresponds to a particular index in the “base64 scale”. So, in the example below, we know that the character that corresponds to the index 28 in the “base64 scale” is the character “c”.

    const base64 = Base64.init();
     try stdout.print(
    @@ -434,7 +434,7 @@ 

    4.1.3 A base64 encoder

    The algorithm behind a base64 encoder usually works on a window of 3 bytes. Because each byte has 8 bits, so, 3 bytes forms a set of \(8 \times 3 = 24\) bits. This is desirable for the base64 algorithm, because 24 bits is divisible by 6, which forms \(24 / 6 = 4\) groups of 6 bits each.

    Therefore, the base64 algorithm works by converting 3 bytes at a time into 4 characters from the base64 scale. It keeps iterating through the input string, 3 bytes at a time, and converting them into the base64 scale, producing 4 characters per iteration. It keeps iterating, and producing these “new characters” until it hits the end of the input string.

    -

    Now, you may think, what if you have a particular string that have a number of bytes that is not divisible by 3? What happens? For example, if you have a string that contains only two characters/bytes, such as “Hi”. How the algorithm would behave in such situation? You find the answer at Figure 4.1. You can see at Figure 4.1 that the string “Hi”, when converted to base64, becomes the string “SGk=”:

    +

    Now you may think, what if you have a particular string that has a number of bytes that is not divisible by 3 - what happens? For example, if you have a string that contains only two characters/bytes, such as “Hi”. How would the algorithm behave in such situation? You find the answer in Figure 4.1. You can see in Figure 4.1 that the string “Hi”, when converted to base64, becomes the string “SGk=”:

    @@ -446,16 +446,17 @@

    \(0 < nbits < 6\), being \(nbits\) the number of bits), meaning that, it lacks some bits to fill the 6-bits requirement, the algorithm simply add extra zeros in this group to fill the space that it needs. That is why at Figure 4.1, on the third group after the 6-bit transformation, 2 extra zeros were added to fill the gap in this group.

    +

    If the algorithm notices that there is a group of 6 bits that it’s not complete, meaning that, this group contains \(nbits\), where \(0 < nbits < 6\),

    +

    the algorithm simply adds extra zeros in this group to fill the space that it needs. That is why in Figure 4.1, in the third group after the 6-bit transformation, 2 extra zeros were added to fill the gap.

    When we have a 6-bit group that is not completely full, like the third group, extra zeros are added to fill the gap. But what about when an entire 6-bit group is empty, or, it simply doesn’t exist? This is the case of the fourth 6-bit group exposed at Figure 4.1.

    This fourth group is necessary, because the algorithm works on 4 groups of 6 bits. But the input string does not have enough bytes to create a fourth 6-bit group. Every time this happens, where an entire group of 6 bits is empty, this group becomes a “padding group”. Every “padding group” is mapped to the character = (equal sign), which represents “null”, or, the end of meaningful characters in the sequence. Hence, everytime that the algorithm produces a “padding group”, this group is automatically mapped to =.

    -

    As another example, if you give the string “0” as input to a base64 encoder, this string is translated into the base64 sequence “MA==”. The character “0” is, in binary, the sequence 001100001. So, with the 6-bit transformation exposed at Figure 4.1, this single character would produce these two 6-bit groups: 001100, 000000. The remaining two 6-bit groups become “padding groups”. That is why the last two characters in the output sequence (MA==) are ==.

    +

    As another example, if you give the string “0” as input to a base64 encoder, this string is translated into the base64 sequence “MA==”. The character “0” is, in binary, the sequence 001100001. So, with the 6-bit transformation exposed in Figure 4.1, this single character would produce these two 6-bit groups: 001100, 000000. The remaining two 6-bit groups become “padding groups”. That is why the last two characters in the output sequence (MA==) are ==.

    4.1.4 A base64 decoder

    -

    The algorithm behind a base64 decoder is essentially the inverse process of a base64 encoder. A base64 decoder needs to translate base64 messages back into their original meaning, i.e. into the original sequence of binary data.

    +

    The algorithm behind a base64 decoder is essentially the inverse process of a base64 encoder. A base64 decoder needs to translate base64 messages back into their original meaning, i.e., into the original sequence of binary data.

    A base64 decoder usually works on a window of 4 bytes. Because it wants to convert these 4 bytes back into the original sequence of 3 bytes, that was converted into 4 groups of 6 bits by the base64 encoder. Remember, in a base64 decoder we are essentially reverting the process made by the base64 encoder.

    -

    Each byte in the input string (the base64 encoded string) normally contributes to re-create two different bytes in the output (the original binary data). In other words, each byte that comes out of a base64 decoder is created by transforming merging two different bytes in the input together. You can visualize this relationship at Figure 4.2:

    +

    Each byte in the input string (the base64 encoded string) normally contributes to re-create two different bytes in the output (the original binary data). In other words, each byte that comes out of a base64 decoder is created by transforming merging two different bytes in the input together. You can visualize this relationship in Figure 4.2:

    @@ -467,15 +468,15 @@

    Figure 4.2, you will notice that the character = was completely ignored by the algorithm. Remember, this is just a special character that marks the end of meaningful characters in the base64 sequence. So, every = character in a base64 encoded sequence should be ignored by a base64 decoder.

    +

    Besides that, if you look again in Figure 4.2, you will notice that the character = was completely ignored by the algorithm. Remember, this is just a special character that marks the end of meaningful characters in the base64 sequence. So, every = character in a base64 encoded sequence should be ignored by a base64 decoder.

    4.2 Difference between encode and decode

    -

    If you don’t have any previous experience with base64, you might not understand the differences between “encode” and “decode”. Essentially, the terms “encode” and “decode” here have the exact same meaning as they have in the field of encryption (i.e. they mean the same thing as “encode” and “decode” in hashing algorithms, like the MD5 algorithm).

    +

    If you don’t have any previous experience with base64, you might not understand the differences between “encode” and “decode”. Essentially, the terms “encode” and “decode” here have the exact same meaning as they have in the field of encryption (i.e., they mean the same thing as “encode” and “decode” in hashing algorithms, like the MD5 algorithm).

    Thus, “encode” means that we want to encode, or, in other words, we want to translate some message into the base64 encoding system. We want to produce the sequence of base64 characters that represent this original message in the base64 encoding system.

    In contrast, “decode” represents the inverse process. We want to decode, or, in other words, translate a base64 message back to its original content. So, in this process we get a sequence of base64 characters as input, and produce as output, the binary data that is represented by this sequence of base64 characters.

    -

    Any base64 library is normally composed of these two parts: 1) the encoder, which is a function that encodes (i.e. it converts) any sequence of binary data into a sequence of base64 characters; 2) the decoder, which is a function that converts a sequence of base64 characters back into the original sequence of binary data.

    +

    Any base64 library is normally composed of these two parts: 1) the encoder, which is a function that encodes (i.e., it converts) any sequence of binary data into a sequence of base64 characters; 2) the decoder, which is a function that converts a sequence of base64 characters back into the original sequence of binary data.

    4.3 Calculating the size of the output

    @@ -495,9 +496,9 @@

    return n_output * 4; } -

    Also, you might have notice that, if the input length is less than 3 bytes, then, the output length of the encoder is always 4 bytes. This is the case for every input with less than 3 bytes, because, as I described at Section 4.1.3, the algorithm always produces enough “padding-groups” in the end result, to complete the 4 bytes window.

    -

    Now, for the decoder, we just need to apply the inverse logic: for each 4 bytes in the input, 3 bytes will be produced in the output of the decoder. I mean, this is roughly true, because we also need to take the = character into account, which is always ignored by the decoder, as we described at Section 4.1.4, and, at Figure 4.2. But we can ignore this fact for now, just to keep things simple.

    -

    The function _calc_decode_length() exposed below summarizes this logic that we described. It is very similar to the function _calc_encode_length(). Only the division part is twisted, and also, in the special case where we have less than 4 bytes in the input to work on. Also notice that this time, we apply a floor operation over the output of the division, by using the divFloor() function (instead of a ceiling operation with divCeil()).

    +

    Also, you might have notice that, if the input length is less than 3 bytes, then, the output length of the encoder is always 4 bytes. This is the case for every input with less than 3 bytes, because, as I described in Section 4.1.3, the algorithm always produces enough “padding-groups” in the end result, to complete the 4 bytes window.

    +

    Now, for the decoder, we just need to apply the inverse logic: for each 4 bytes in the input, 3 bytes will be produced in the output of the decoder. I mean, this is roughly true, because we also need to take the = character into account, which is always ignored by the decoder, as we described in Section 4.1.4, and, in Figure 4.2. But we can ignore this fact for now, just to keep things simple.

    +

    The function _calc_decode_length() exposed below summarizes this logic that we described. It’s very similar to the function _calc_encode_length(). Only the division part is twisted, and also, in the special case where we have less than 4 bytes in the input to work on. Also notice that this time, we apply a floor operation over the output of the division, by using the divFloor() function (instead of a ceiling operation with divCeil()).

    const std = @import("std");
     fn _calc_decode_length(input: []const u8) !usize {
    @@ -517,7 +518,7 @@ 

    In this section, we can start building the logic behind the encode() function, which will be responsible for encoding messages into the base64 encoding system. If you are an anxious person, and you want to see now the full source code of the implementation for this base64 encoder/decoder, you can find it at the ZigExamples folder in the official repository of this book2.

    4.4.1 The 6-bit transformation

    -

    The 6-bit transformation presented at Figure 4.1 is the core part of the base64 encoder algorithm. By understanding how this transformation is made in code, the rest of the algorithm becomes much simpler to comprehend.

    +

    The 6-bit transformation presented in Figure 4.1 is the core part of the base64 encoder algorithm. By understanding how this transformation is made in code, the rest of the algorithm becomes much simpler to comprehend.

    In essence, this 6-bit transformation is made with the help of bitwise operators. Bitwise operators are essential to any type of low-level operation that is done at the bit-level. For the specific case of the base64 algorithm, the operators bif shift to the left (<<), bit shift to the right (>>), and the bitwise and (&) are used. They are the core solution for the 6-bit transformation.

    There are 3 different scenarios that we need to take into account in this transformation. First, is the perfect scenario, where we have the perfect window of 3 bytes to work on. Second, we have the scenario where we have a window of only two bytes to work with. And last, we have the scenario where we have a window of one single byte.

    In each of these 3 scenarios, the 6-bit transformation works a bit differently. To make the explanation easier, I will use the variable output to refer to the bytes in the output of the base64 encoder, and the variable input to refer to the bytes in the input of the encoder.

    @@ -640,8 +641,8 @@

    4.4.2 Bit-shifting in Zig

    Bit-shifting in Zig works similarly to bit-shifting in C. All bitwise operators that exist in C are available in Zig. Here, in the base64 encoder algorithm, they are essential to produce the result we want.

    For those who are not familiar with these operators, they are operators that operates at the bit-level of your values. This means that these operators takes the bits that form the value you have, and change them in some way. This ultimately also changes the value itself, because the binary representation of this value changes.

    -

    We have already seen at Figure 4.3 the effect produced by a bit-shift. But let’s use the first byte in the output of the base64 encoder as another example of what bit-shifting means. This is the easiest byte of the 4 bytes in the output to build. Because we only need to move the bits from the first byte in the input two positions to the right, with the bit shift to the right (>>) operator.

    -

    If we take the string “Hi” that we used at Figure 4.1 as an example, the first byte in this string is “H”, which is the sequence 01001000 in binary. If we move the bits of this byte, two places to the right, we get the sequence 00010010 as result. This binary sequence is the value 18 in decimal, and also, the value 0x12 in hexadecimal. Notice that the first 6 bits of “H” were moved to the end of the byte. With this operation, we get the first byte of the output.

    +

    We have already seen in Figure 4.3 the effect produced by a bit-shift. But let’s use the first byte in the output of the base64 encoder as another example of what bit-shifting means. This is the easiest byte of the 4 bytes in the output to build. Because we only need to move the bits from the first byte in the input two positions to the right, with the bit shift to the right (>>) operator.

    +

    If we take the string “Hi” that we used in Figure 4.1 as an example, the first byte in this string is “H”, which is the sequence 01001000 in binary. If we move the bits of this byte, two places to the right, we get the sequence 00010010 as result. This binary sequence is the value 18 in decimal, and also, the value 0x12 in hexadecimal. Notice that the first 6 bits of “H” were moved to the end of the byte. With this operation, we get the first byte of the output.

    const std = @import("std");
     const stdout = std.io.getStdOut().writer();
    @@ -679,14 +680,14 @@ 

    4.4.4 Allocating space for the output

    -

    As I described at Section 3.1.4, to store an object in the stack, this object needs to have a known and fixed length at compile-time. This is an important limitation for our base64 encoder/decoder case. Because the size of the output (from both the encoder and decoder) depends directly on the size of the input.

    +

    As I described in Section 3.1.4, to store an object in the stack, this object needs to have a known and fixed length at compile-time. This is an important limitation for our base64 encoder/decoder case. Because the size of the output (from both the encoder and decoder) depends directly on the size of the input.

    Having this in mind, we cannot know at compile time which is the size of the output for both the encoder and decoder. So, if we can’t know the size of the output at compile time, this means that we cannot store the output for both the encoder and decoder in the stack.

    -

    Consequently, we need to store this output on the heap, and, as I commented at Section 3.1.5, we can only store objects in the heap by using allocator objects. So, one the arguments to both the encode() and decode() functions, needs to be an allocator object, because we know for sure that, at some point inside the body of these functions, we need to allocate space on the heap to store the output of these functions.

    +

    Consequently, we need to store this output on the heap, and, as I commented in Section 3.1.5, we can only store objects in the heap by using allocator objects. So, one the arguments to both the encode() and decode() functions, needs to be an allocator object, because we know for sure that, at some point inside the body of these functions, we need to allocate space on the heap to store the output of these functions.

    That is why, both the encode() and decode() functions that I present in this book, have an argument called allocator, which receives a allocator object as input, identified by the type std.mem.Allocator from the Zig Standard Library.

    4.4.5 Writing the encode() function

    -

    Now that we have a basic understanding on how the bitwise operators work, and how exactly they help us to achieve the result we want to achieve. We can now encapsulate all the logic that we have described at Figure 4.1 and Table 4.1 into a nice function that we can add to our Base64 struct definition, that we started at Section 4.1.2.

    +

    Now that we have a basic understanding on how the bitwise operators work, and how exactly they help us to achieve the result we want to achieve. We can now encapsulate all the logic that we have described in Figure 4.1 and Table 4.1 into a nice function that we can add to our Base64 struct definition, that we started in Section 4.1.2.

    You can find the encode() function below. Notice that the first argument of this function, is the Base64 struct itself. Therefore, this argument clearly signals that this function is a method from the Base64 struct.

    Because the encode() function itself is fairly long, I intentionally omitted the Base64 struct definition in this source code, just for brevity reasons. So, just remember that this function is a public function (or a public method) from the Base64 struct.

    Furthermore, this encode() function has two other arguments:

    @@ -694,7 +695,7 @@

    Section 3.3. So, if you are not familiar with them, I highly recommend you to comeback to that section, and read it. By looking at the encode() function, you will see that we use this allocator object to allocate enough memory to store the output of the encoding process.

    +

    I described everything you need to know about allocator objects in Section 3.3. So, if you are not familiar with them, I highly recommend you to comeback to that section, and read it. By looking at the encode() function, you will see that we use this allocator object to allocate enough memory to store the output of the encoding process.

    The main for loop in the function is responsible for iterating through the entire input string. In every iteration, we use a count variable to count how many iterations we had at the moment. When count reaches 3, then, we try to encode the 3 characters (or bytes) that we have accumulated in the temporary buffer object (buf).

    After encoding these 3 characters and storing the result in the output variable, we reset the count variable to zero, and start to count again on the next iteration of the loop. If the loop hits the end of the string, and, the count variable is less than 3, then, it means that the temporary buffer contains the last 1 or 2 bytes from the input. That is why we have two if statements after the for loop. To deal which each possible case.

    @@ -757,14 +758,14 @@

    4.5 Building the decoder logic

    -

    Now, we can focus on writing the base64 decoder logic. Remember from Figure 4.2 that, a base64 decoder does the inverse process of an encoder. So, all we need to do, is to write a decode() function that performs the inverse process that I exposed at Section 4.4.

    +

    Now, we can focus on writing the base64 decoder logic. Remember from Figure 4.2 that, a base64 decoder does the inverse process of an encoder. So, all we need to do, is to write a decode() function that performs the inverse process that I exposed in Section 4.4.

    4.5.1 Mapping base64 characters to their indexes

    One thing that we need to do, in order to decode a base64-encoded message, is to calculate the index in the base64 scale of every base64 character that we encounter in the decoder input.

    In other words, the decoder receives as input, a sequence of base64 characters. We need to translate this sequence of characters into a sequence of indexes. These indexes are the index of each character in the base64 scale. This way, we get the value/byte that was calculated in the 6-bit transformation step of the encoder process.

    There are probably better/faster ways to calculate this, especially using a “divide and conquer” type of strategy. But for now, I am satisfied with a simple and “brute force” type of strategy. The _char_index() function below contains this strategy.

    We are essentially looping through the lookup table with the base64 scale, and comparing the character we got with each character in the base64 scale. If these characters match, then, we return the index of this character in the base64 scale as the result.

    -

    Notice that, if the input character is '=', the function returns the index 64, which is “out of range” in the scale. But, as I described at Section 4.1.1, the character '=' does not belong to the base64 scale itself. It is a special and meaningless character in base64.

    +

    Notice that, if the input character is '=', the function returns the index 64, which is “out of range” in the scale. But, as I described in Section 4.1.1, the character '=' does not belong to the base64 scale itself. It’s a special and meaningless character in base64.

    Also notice that this _char_index() function is a method from our Base64 struct, because of the self argument. Again, I have omitted the Base64 struct definition in this example for brevity reasons.

    fn _char_index(self: Base64, char: u8) u8 {
    @@ -797,8 +798,8 @@ 

    Section 4.4. The first byte in the output of the encoder is produced by moving the bits in the first byte of the input two positions to the right.

    -

    If for example the first byte in the input of the encoder was the sequence ABCDEFGH, then, the first byte in the output of the encoder would be 00ABCDEF (this sequence would be the first byte in the input of the decoder). Now, if the second byte in the input of the encoder was the sequence IJKLMNOP, then, the second byte in the encoder output would be 00GHIJKL (as we demonstrated at Figure 4.3).

    +

    Before we continue, let’s try to visualize how these transformations make the original bytes that we had before the encoding process. First, think back to the 6-bit transformation performed by the encoder exposed in Section 4.4. The first byte in the output of the encoder is produced by moving the bits in the first byte of the input two positions to the right.

    +

    If for example the first byte in the input of the encoder was the sequence ABCDEFGH, then, the first byte in the output of the encoder would be 00ABCDEF (this sequence would be the first byte in the input of the decoder). Now, if the second byte in the input of the encoder was the sequence IJKLMNOP, then, the second byte in the encoder output would be 00GHIJKL (as we demonstrated in Figure 4.3).

    Hence, if the sequences 00ABCDEF and 00GHIJKL are the first and second bytes, respectively, in the input of the decoder, the Figure 4.4 demonstrates visually how these two bytes are transformed into the first byte of the output of the decoder. Notice that the output byte is the sequence ABCDEFGH, which is the original byte from the input of the encoder.

    diff --git a/docs/Chapters/01-memory.html b/docs/Chapters/01-memory.html index 52b997d6..e4c2e35d 100644 --- a/docs/Chapters/01-memory.html +++ b/docs/Chapters/01-memory.html @@ -362,7 +362,7 @@

    When you write a program in Zig, the values of some of the objects that you write in your program are known at compile time. Meaning that, when you compile your Zig source code, during the compilation process, the zig compiler can figure out the exact value of a particular object that exists in your source code. Knowing the length (or the size) of each object is also important. So the length (or the size) of each object that you write in your program is, in some cases, known at compile time.

    The zig compiler cares more about knowing the length (or the size) of a particular object , than to know its actual value. But, if the zig compiler knows the value of the object, then, it automatically knows the size of this object. Because it can simply calculate the size of the object by looking at the size of the value.

    Therefore, the priority for the zig compiler is to discover the size of each object in your source code. If the value of the object in question is known at compile-time, then, the zig compiler automatically knows the size/length of this object. But if the value of this object is not known at compile-time, then, the size of this object is only known at compile-time if, and only if, the type of this object has a known fixed size.

    -

    In order for a type to have a known fixed size, this type must have data members whose size is fixed. If this type includes, for example, a variable sized array in it, then, this type does not have a known fixed size. Because this array can have any size at runtime (i.e. it can be an array of 2 elements, or 50 elements, or 1 thousand elements, etc.).

    +

    In order for a type to have a known fixed size, this type must have data members whose size is fixed. If this type includes, for example, a variable sized array in it, then, this type does not have a known fixed size. Because this array can have any size at runtime (i.e., it can be an array of 2 elements, or 50 elements, or 1 thousand elements, etc.).

    For example, a string object, which internally is an array of constant u8 values ([]const u8) has a variable size. It can be a string object with 100 or 500 characters in it. If we do not know at compile-time, which exact string will be stored inside this string object, then, we cannot calculate the size of this string object at compile-time. So, any type, or any struct declaration that you make, that includes a string data member that does not have an explicit fixed size, makes this type, or this new struct that you are declaring, a type that does not have a known fixed size at compile-time.

    In contrast, if the type of this struct that you are declaring, includes a data member that is an array, but this array has a known fixed size, like [60]u8 (which declares an array of 60 u8 values), then, this type, or, this struct that you are declaring, becomes a type with a known fixed size at compile-time. And because of that, in this case, the zig compiler does not need to know at compile-time the exact value of any object of this type. Since the compiler can find the necessary size to store this object by looking at the size of its type.

    Let’s look at an example. In the source code below, we have two constant objects (name and array) declared. Because the values of these particular objects are written down, in the source code itself ("Pedro" and the number sequence from 1 to 4), the zig compiler can easily discover the values of these constant objects (name and array) during the compilation process. This is what “known at compile time” means. It refers to any object that you have in your Zig source code whose value can be identified at compile time.

    @@ -379,7 +379,7 @@

    }

    The other side of the spectrum are objects whose values are not known at compile time. Function arguments are a classic example of this. Because the value of each function argument depends on the value that you assign to this particular argument, when you call the function.

    -

    For example, the function input_length() contains an argument named input, which is an array of constant u8 integers ([]const u8). It is impossible to know the value of this particular argument at compile time. And it also is impossible to know the size/length of this particular argument. Because it is an array that do not have a fixed size specified explicitly in the argument type annotation.

    +

    For example, the function input_length() contains an argument named input, which is an array of constant u8 integers ([]const u8). It’s impossible to know the value of this particular argument at compile time. And it also is impossible to know the size/length of this particular argument. Because it’s an array that does not have a fixed size specified explicitly in the argument type annotation.

    So, we know that this input argument will be an array of u8 integers. But we do not know at compile-time, its value, and neither its size. This information is known only at runtime, which is the period of time when you program is executed. As a consequence, the value of the expression input.len is also known only at runtime. This is an intrinsic characteristic of any function. Just remember that the value of function arguments is usually not “compile-time known”.

    However, as I mentioned earlier, what really matters to the compiler is to know the size of the object at compile-time, and not necessarily its value. So, although we don’t know the value of the object n, which is the result of the expression input.len, at compile-time, we do know its size. Because the expression input.len always returns a value of type usize, and the type usize has a known fixed size.

    @@ -393,7 +393,7 @@

    <

    3.1.3 Stack vs Heap

    If you are familiar with systems programming, or just low-level programming in general, you probably have heard of the “duel” between Stack vs Heap. These are two different types of memory, or different memory spaces, which are both available in Zig.

    These two types of memory don’t actually duel with each other. This is a common mistake that beginners have, when seeing “x vs y” styles of tabloid headlines. These two types of memory are actually complementary to each other. So, in almost every Zig program that you ever write, you will likely use a combination of both. I will describe each memory space in detail over the next sections. But for now, I just want to stablish the main difference between these two types of memory.

    -

    In essence, the stack memory is normally used to store values whose length is fixed and known at compile time. In contrast, the heap memory is a dynamic type of memory space, meaning that, it is used to store values whose length might grow during the execution (runtime) of your program (Chen and Guo 2022).

    +

    In essence, the stack memory is normally used to store values whose length is fixed and known at compile time. In contrast, the heap memory is a dynamic type of memory space, meaning that, it’s used to store values whose length might grow during the execution (runtime) of your program (Chen and Guo 2022).

    Lengths that grow during runtime are intrinsically associated with “runtime known” type of values. In other words, if you have an object whose length might grow during runtime, then, the length of this object becomes not known at compile time. If the length is not known at compile-time, the value of this object also becomes not known at compile-time. These types of objects should be stored in the heap memory space, which is a dynamic memory space, which can grow or shrink to fit the size of your objects.

    @@ -401,7 +401,7 @@

    The stack is a type of memory that uses the power of the stack data structure, hence the name. A “stack” is a type of data structure that uses a “last in, first out” (LIFO) mechanism to store the values you give it to. I imagine you are familiar with this data structure. But, if you are not, the Wikipedia page1 , or, the Geeks For Geeks page2 are both excellent and easy resources to fully understand how this data structure works.

    So, the stack memory space is a type of memory that stores values using a stack data structure. It adds and removes values from the memory by following a “last in, first out” (LIFO) principle.

    Every time you make a function call in Zig, an amount of space in the stack is reserved for this particular function call (Chen and Guo 2022; Zig Software Foundation 2024). The value of each function argument given to the function in this function call is stored in this stack space. Also, every local object that you declare inside the function scope is usually stored in this same stack space.

    -

    Looking at the example below, the object result is a local object declared inside the scope of the add() function. Because of that, this object is stored inside the stack space reserved for the add() function. The r object (which is declared outside of the add() function scope) is also stored in the stack. But since it is declared in the “outer” scope, this object is stored in the stack space that belongs to this outer scope.

    +

    Looking at the example below, the object result is a local object declared inside the scope of the add() function. Because of that, this object is stored inside the stack space reserved for the add() function. The r object (which is declared outside of the add() function scope) is also stored in the stack. But since it’s declared in the “outer” scope, this object is stored in the stack space that belongs to this outer scope.

    fn add(x: u8, y: u8) u8 {
         const result = x + y;
    @@ -444,8 +444,8 @@ 

    One important consequence of this mechanism is that, once the function returns, you can no longer access any memory address that was inside the space in the stack reserved for this particular function. Because this space was destroyed. This means that, if this local object is stored in the stack, you cannot make a function that returns a pointer to this object.

    Think about that for a second. If all local objects in the stack are destroyed at the end of the function scope, why would you even consider returning a pointer to one of these objects? This pointer is at best, invalid, or, more likely, “undefined”.

    -

    Conclusion, it is totally fine to write a function that returns the local object itself as result, because then, you return the value of that object as the result. But, if this local object is stored in the stack, you should never write a function that returns a pointer to this local object. Because the memory address pointed by the pointer no longer exists.

    -

    So, using again the add() function as an example, if you rewrite this function so that it returns a pointer to the local object result, the zig compiler will actually compile your program, with no warnings or errors. At first glance, it looks that this is good code that works as expected. But this is a lie!

    +

    In conclusion, it’s totally fine to write a function that returns the local object itself as result, because then, you return the value of that object as the result. But, if this local object is stored in the stack, you should never write a function that returns a pointer to this local object. Because the memory address pointed by the pointer no longer exists.

    +

    So, using again the add() function as an example, if you rewrite this function so that it returns a pointer to the local object result, the zig compiler will actually compile your program, with no warnings or errors. At first glance, it looks like this is good code that works as expected. But this is a lie!

    If you try to take a look at the value inside of the r object, or, if you try to use this r object in another expression or function call, then, you would have undefined behaviour, and major bugs in your program (Zig Software Foundation 2024, see “Lifetime and Ownership”3 and “Undefined Behaviour”4 sections).

    fn add(x: u8, y: u8) *const u8 {
    @@ -460,7 +460,7 @@ 

    const r = add(5, 27); _ = r; }

    -

    This “invalid pointer to stack variable” problem is well known across many programming language communities. If you try to do the same thing, for example, in a C or C++ program (i.e. returning an address to a local object stored in the stack), you would also get undefined behaviour in the program.

    +

    This “invalid pointer to stack variable” problem is well known across many programming language communities. If you try to do the same thing, for example, in a C or C++ program (i.e., returning an address to a local object stored in the stack), you would also get undefined behaviour in the program.

    @@ -478,14 +478,14 @@

    3.1.5 Heap

    -

    One important limitation of the stack, is that, only objects whose length/size is known at compile-time can be stored in it. In contrast, the heap is a much more dynamic (and flexible) type of memory. It is the perfect type of memory to use for objects whose size/length might grow during the execution of your program.

    +

    One important limitation of the stack, is that, only objects whose length/size is known at compile-time can be stored in it. In contrast, the heap is a much more dynamic (and flexible) type of memory. It’s the perfect type of memory to use for objects whose size/length might grow during the execution of your program.

    Virtually any application that behaves as a server is a classic use case of the heap. A HTTP server, a SSH server, a DNS server, a LSP server, … any type of server. In summary, a server is a type of application that runs for long periods of time, and that serves (or “deals with”) any incoming request that reaches this particular server.

    The heap is a good choice for this type of system, mainly because the server does not know upfront how many requests it will receive from users, while it is active. It could be a single request, 5 thousand requests, or even zero requests. The server needs to have the ability to allocate and manage its memory according to how many requests it receives.

    Another key difference between the stack and the heap, is that the heap is a type of memory that you, the programmer, have complete control over. This makes the heap a more flexible type of memory, but it also makes it harder to work with. Because you, the programmer, is responsible for managing everything related to it. Including where the memory is allocated, how much memory is allocated, and where this memory is freed.

    Unlike stack memory, heap memory is allocated explicitly by programmers and it won’t be deallocated until it is explicitly freed (Chen and Guo 2022).

    -

    To store an object in the heap, you, the programmer, needs to explicitly tells Zig to do so, by using an allocator to allocate some space in the heap. At Section 3.3, I will present how you can use allocators to allocate memory in Zig.

    +

    To store an object in the heap, you, the programmer, needs to explicitly tells Zig to do so, by using an allocator to allocate some space in the heap. In Section 3.3, I will present how you can use allocators to allocate memory in Zig.

    @@ -515,10 +515,10 @@

    3.2 Stack overflows

    -

    Allocating memory on the stack is generally faster than allocating it on the heap. But this better performance comes with many restrictions. We have already discussed many of these restrictions of the stack at Section 3.1.4. But there is one more important limitation that I want to talk about, which is the size of the stack itself.

    +

    Allocating memory on the stack is generally faster than allocating it on the heap. But this better performance comes with many restrictions. We have already discussed many of these restrictions of the stack in Section 3.1.4. But there is one more important limitation that I want to talk about, which is the size of the stack itself.

    The stack is limited in size. This size varies from computer to computer, and it depends on a lot of things (the computer architecture, the operating system, etc.). Nevertheless, this size is usually not that big. This is why we normally use the stack to store only temporary and small objects in memory.

    In essence, if you try to make an allocation on the stack, that is so big that exceeds the stack size limit, a stack overflow happens, and your program just crashes as a result of that. In other words, a stack overflow happens when you attempt to use more space than is available on the stack.

    -

    This type of problem is very similar to a buffer overflow, i.e. you are trying to use more space than is available in the “buffer object”. However, a stack overflow always causes your program to crash, while a buffer overflow does not always cause your program to crash (although it often does).

    +

    This type of problem is very similar to a buffer overflow, i.e., you are trying to use more space than is available in the “buffer object”. However, a stack overflow always causes your program to crash, while a buffer overflow does not always cause your program to crash (although it often does).

    You can see an example of a stack overflow in the example below. We are trying to allocate a very big array of u64 values on the stack. You can see below that this program does not run successfully, because it crashed with a “segmentation fault” error message.

    var very_big_alloc: [1000 * 1000 * 24]u64 = undefined;
    @@ -558,13 +558,13 @@ 

    3.3.2 Why you need an allocator?

    -

    As we described at Section 3.1.4, everytime you make a function call in Zig, a space in the stack is reserved for this function call. But the stack has a key limitation which is: every object stored in the stack has a known fixed length.

    +

    As we described in Section 3.1.4, everytime you make a function call in Zig, a space in the stack is reserved for this function call. But the stack has a key limitation which is: every object stored in the stack has a known fixed length.

    But in reality, there are two very common instances where this “fixed length limitation” of the stack is a deal braker:

    1. the objects that you create inside your function might grow in size during the execution of the function.
    2. -
    3. sometimes, it is impossible to know upfront how many inputs you will receive, or how big this input will be.
    4. +
    5. sometimes, it’s impossible to know upfront how many inputs you will receive, or how big this input will be.
    -

    Also, there is another instance where you might want to use an allocator, which is when you want to write a function that returns a pointer to a local object. As I described at Section 3.1.4, you cannot do that if this local object is stored in the stack. However, if this object is stored in the heap, then, you can return a pointer to this object at the end of the function. Because you (the programmer) control the lifetime of any heap memory that you allocate. You decide when this memory gets destroyed/freed.

    +

    Also, there is another instance where you might want to use an allocator, which is when you want to write a function that returns a pointer to a local object. As I described in Section 3.1.4, you cannot do that if this local object is stored in the stack. However, if this object is stored in the heap, then, you can return a pointer to this object at the end of the function. Because you (the programmer) control the lifetime of any heap memory that you allocate. You decide when this memory gets destroyed/freed.

    These are common situations for which the stack is not good. That is why you need a different memory management strategy to store these objects inside your function. You need to use a memory type that can grow together with your objects, or that you can control the lifetime of this memory. The heap fits this description.

    Allocating memory on the heap is commonly known as dynamic memory management. As the objects you create grow in size during the execution of your program, you grow the amount of memory you have by allocating more memory in the heap to store these objects. And you do that in Zig, by using an allocator object.

    @@ -620,7 +620,7 @@

    defer allocator.free(input);

    Remember, the memory allocated by these allocator objects can be either from the stack, or, from the heap. It all depends on where the buffer object that you provide lives. In the above example, the buffer object lives in the stack, and, therefore, the memory allocated is based in the stack. But what if it was based on the heap?

    -

    As we described at Section 3.2, one of the main reasons why you would use the heap, instead of the stack, is to allocate huge amounts of space to store very big objects. Thus, let’s suppose you wanted to use a very big buffer object as the basis for your allocator objects. You would have to allocate this very big buffer object on the heap. The example below demonstrates this case.

    +

    As we described in Section 3.2, one of the main reasons why you would use the heap, instead of the stack, is to allocate huge amounts of space to store very big objects. Thus, let’s suppose you wanted to use a very big buffer object as the basis for your allocator objects. You would have to allocate this very big buffer object on the heap. The example below demonstrates this case.

    const heap = std.heap.page_allocator;
     const memory_buffer = try heap.alloc(
    @@ -638,7 +638,7 @@ 

    3.3.7 Arena allocator

    -

    The ArenaAllocator() is an allocator object that takes a child allocator as input. The idea behind the ArenaAllocator() in Zig is similar to the concept of “arenas” in the programming language Go5. It is an allocator object that allows you to allocate memory as many times you want, but free all memory only once. In other words, if you have, for example, called 5 times the method alloc() of an ArenaAllocator() object, you can free all the memory you allocated over these 5 calls at once, by simply calling the deinit() method of the same ArenaAllocator() object.

    +

    The ArenaAllocator() is an allocator object that takes a child allocator as input. The idea behind the ArenaAllocator() in Zig is similar to the concept of “arenas” in the programming language Go5. It’s an allocator object that allows you to allocate memory as many times you want, but free all memory only once. In other words, if you have, for example, called 5 times the method alloc() of an ArenaAllocator() object, you can free all the memory you allocated over these 5 calls at once, by simply calling the deinit() method of the same ArenaAllocator() object.

    If you give, for example, a GeneralPurposeAllocator() object as input to the ArenaAllocator() constructor, like in the example below, then, the allocations you perform with alloc() will actually be made with the underlying object GeneralPurposeAllocator() that was passed. So, with an arena allocator, any new memory you ask for is allocated by the child allocator. The only thing that an arena allocator really does is help you to free all the memory you allocated multiple times with just a single command. In the example below, I called alloc() 3 times. So, if I did not use an arena allocator, then, I would need to call free() 3 times to free all the allocated memory.

    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    @@ -656,8 +656,8 @@ 

    3.3.8 The alloc() and free() methods

    In the code example below, we are accessing the stdin, which is the standard input channel, to receive an input from the user. We read the input given by the user with the readUntilDelimiterOrEof() method.

    Now, after reading the input of the user, we need to store this input somewhere in our program. That is why I use an allocator in this example. I use it to allocate some amount of memory to store this input given by the user. More specifically, the method alloc() of the allocator object is used to allocate an array capable of storing 50 u8 values.

    -

    Notice that this alloc() method receives two inputs. The first one, is a type. This defines what type of values the allocated array will store. In the example below, we are allocating an array of unsigned 8-bit integers (u8). But you can create an array to store any type of value you want. Next, on the second argument, we define the size of the allocated array, by specifying how many elements this array will contain. In the case below, we are allocating an array of 50 elements.

    -

    At Section 1.8 we described that strings in Zig are simply arrays of characters. Each character is represented by a u8 value. So, this means that the array that was allocated in the object input is capable of storing a string that is 50-characters long.

    +

    Notice that this alloc() method receives two inputs. The first one, is a type. This defines what type of values the allocated array will store. In the example below, we are allocating an array of unsigned 8-bit integers (u8). But you can create an array to store any type of value you want. Next, in the second argument, we define the size of the allocated array, by specifying how many elements this array will contain. In the case below, we are allocating an array of 50 elements.

    +

    In Section 1.8 we described that strings in Zig are simply arrays of characters. Each character is represented by a u8 value. So, this means that the array that was allocated in the object input is capable of storing a string that is 50-characters long.

    So, in essence, the expression var input: [50]u8 = undefined would create an array for 50 u8 values in the stack of the current scope. But, you can allocate the same array in the heap by using the expression var input = try allocator.alloc(u8, 50).

    const std = @import("std");
    @@ -680,8 +680,8 @@ 

    std.debug.print("{s}\n", .{input}); }

    -

    Also, notice that in this example, we use the defer keyword (which I described at Section 2.1.3) to run a small piece of code at the end of the current scope, which is the expression allocator.free(input). When you execute this expression, the allocator will free the memory that it allocated for the input object.

    -

    We have talked about this at Section 3.1.5. You should always explicitly free any memory that you allocate using an allocator! You do that by using the free() method of the same allocator object you used to allocate this memory. The defer keyword is used in this example only to help us execute this free operation at the end of the current scope.

    +

    Also, notice that in this example, we use the defer keyword (which I described in Section 2.1.3) to run a small piece of code at the end of the current scope, which is the expression allocator.free(input). When you execute this expression, the allocator will free the memory that it allocated for the input object.

    +

    We have talked about this in Section 3.1.5. You should always explicitly free any memory that you allocate using an allocator! You do that by using the free() method of the same allocator object you used to allocate this memory. The defer keyword is used in this example only to help us execute this free operation at the end of the current scope.

    3.3.9 The create() and destroy() methods

    diff --git a/docs/Chapters/01-zig-weird.html b/docs/Chapters/01-zig-weird.html index 1f772abb..43f740f4 100644 --- a/docs/Chapters/01-zig-weird.html +++ b/docs/Chapters/01-zig-weird.html @@ -310,7 +310,7 @@

    Table of contents

  • 1.2.7 Compiling the entire project
  • 1.3 How to learn Zig?
  • -
  • 1.4 Creating new objects in Zig (i.e. identifiers) +
  • 1.4 Creating new objects in Zig (i.e., identifiers)
    • 1.4.1 Constant objects vs variable objects
    • 1.4.2 Declaring without an initial value
    • @@ -371,8 +371,10 @@

      “Focus on debugging your application rather than debugging your programming language knowledge”.

      This phrase is specially true for C++ programmers. Because C++ is a gigantic language, with tons of features, and also, there are lots of different “flavors of C++”. These elements are what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction. Zig is a very simple language, more closely related to other simple languages such as C and Go.

      -

      The phrase above is still important for C programmers too. Because, even C being a simple language, it is still hard sometimes to read and understand C code. For example, pre-processor macros in C are a frequent source of confusion. They really make it sometimes hard to debug C programs. Because macros are essentially a second language embedded in C that obscures your C code. With macros, you are no longer 100% sure about which pieces of the code are being sent to the compiler, i.e. they obscure the actual source code that you wrote.

      -

      You don’t have macros in Zig. In Zig, the code you write, is the actual code that get’s compiled by the compiler. You also don’t have a hidden control flow happening behind the scenes. And, you also don’t have functions or operators from the standard library that make hidden memory allocations behind your back.

      +

      The phrase above is still important for C programmers too. Because, even C being a simple

      +

      language, it’s still hard sometimes to read and understand C code. For example, pre-processor macros in C are a frequent source of confusion. Sometimes, they really make it hard to debug

      +

      C programs. Because macros are essentially a second language embedded in C that obscures your C code. With macros, you are no longer 100% sure about which pieces of the code are being sent to the compiler, i.e. they obscure the actual source code that you wrote.

      +

      You don’t have macros in Zig. In Zig, the code you write, is the actual code that gets compiled by the compiler. You also don’t have a hidden control flow happening behind the scenes. And, you also don’t have functions or operators from the standard library that make hidden memory allocations behind your back.

      By being a simpler language, Zig becomes much more clear and easier to read/write, but at the same time, it also achieves a much more robust state, with more consistent behaviour in edge situations. Once again, less is more.

  • @@ -389,7 +391,7 @@

    1.2.1 Understanding the project files

    After you run the init command from the zig compiler, some new files are created inside of your current directory. First, a “source” (src) directory is created, containing two files, main.zig and root.zig. Each .zig file is a separate Zig module, which is simply a text file that contains some Zig code.

    -

    By convention, the main.zig module is where your main function lives. Thus, if you are building an executable program in Zig, you need to declare a main() function, which represents the entrypoint of your program, i.e. it is where the execution of your program begins.

    +

    By convention, the main.zig module is where your main function lives. Thus, if you are building an executable program in Zig, you need to declare a main() function, which represents the entrypoint of your program, i.e., where the execution of your program begins.

    However, if you are building a library (instead of an executable program), then, the normal procedure is to delete this main.zig file and start with the root.zig module. By convention, the root.zig module is the root source file of your library.

    tree .
    .
    @@ -400,11 +402,11 @@ 

    -

    The init command also creates two additional files in our working directory: build.zig and build.zig.zon. The first file (build.zig) represents a build script written in Zig. This script is executed when you call the build command from the zig compiler. In other words, this file contain Zig code that executes the necessary steps to build the entire project.

    +

    The init command also creates two additional files in our working directory: build.zig and build.zig.zon. The first file (build.zig) represents a build script written in Zig. This script is executed when you call the build command from the zig compiler. In other words, this file contains Zig code that executes the necessary steps to build the entire project.

    Low-level languages normally use a compiler to build your source code into binary executables or binary libraries. Nevertheless, this process of compiling your source code and building binary executables or binary libraries from it, became a real challenge in the programming world, once the projects became bigger and bigger. As a result, programmers created “build systems”, which are a second set of tools designed to make this process of compiling and building complex projects, easier.

    Examples of build systems are CMake, GNU Make, GNU Autoconf and Ninja, which are used to build complex C and C++ projects. With these systems, you can write scripts, which are called “build scripts”. They simply are scripts that describes the necessary steps to compile/build your project.

    However, these are separate tools, that do not belong to C/C++ compilers, like gcc or clang. As a result, in C/C++ projects, you have not only to install and manage your C/C++ compilers, but you also have to install and manage these build systems separately.

    -

    In Zig, we don’t need to use a separate set of tools to build our projects, because a build system is embedded inside the language itself. Therefore, Zig contains a native build system in it, and we can use this build system to write small scripts in Zig, which describes the necessary steps to build/compile our Zig project1. So, everything you need to build a complex Zig project is the zig compiler, and nothing more.

    +

    In Zig, we don’t need to use a separate set of tools to build our projects, because a build system is embedded inside the language itself. We can use this build system to write small scripts in Zig, which describe the necessary steps to build/compile our Zig project1. So, everything you need to build a complex Zig project is the zig compiler, and nothing more.

    The second generated file (build.zig.zon) is a JSON-like file, in which you can describe your project, and also, declare a set of dependencies of your project that you want to fetch from the internet. In other words, you can use this build.zig.zon file to include a list of external libraries in your project.

    One possible way to include an external Zig library in your project, is to manually build and install the library in your system, and just link your source code with the library at the build step of your project.

    However, if this external Zig library is available on GitHub for example, and it has a valid build.zig.zon file in root folder of the project, which describes the project, you can easily include this library in your project by simply listing this external library in your build.zig.zon file.

    @@ -414,7 +416,7 @@

    1.2.2 The file root.zig

    Let’s take a look into the root.zig file. You might have noticed that every line of code with an expression ends with a semicolon (;). This follows the syntax of a C-family programming language5.

    Also, notice the @import() call at the first line. We use this built-in function to import functionality from other Zig modules into our current module. This @import() function works similarly to the #include pre-processor in C or C++, or, to the import statement in Python or Javascript code. In this example, we are importing the std module, which gives you access to the Zig Standard Library.

    -

    In this root.zig file, we can also see how assignments (i.e. creating new objects) are made in Zig. You can create a new object in Zig by using the following syntax (const|var) name = value;. In the example below, we are creating two constant objects (std and testing). At Section 1.4 we talk more about objects in general.

    +

    In this root.zig file, we can also see how assignments (i.e., creating new objects) are made in Zig. You can create a new object in Zig by using the syntax (const|var) name = value;. In the example below, we are creating two constant objects (std and testing). In Section 1.4 we talk more about objects in general.

    const std = @import("std");
     const testing = std.testing;
    @@ -424,7 +426,7 @@ 

    }

    Functions in Zig are declared using the fn keyword. In this root.zig module, we are declaring a function called add(), which has two arguments named a and b. The function returns an integer of the type i32 as result.

    -

    Zig is a strongly-typed language. There are some specific situations where you can (if you want to) omit the type of an object in your code, if this type can be inferred by the zig compiler (we talk more about that at Section 2.4). But there are other situations where you do need to be explicit. For example, you do have to explicitly specify the type of each function argument, and also, the return type of every function that you create in Zig.

    +

    Zig is a strongly-typed language. There are some specific situations where you can (if you want to) omit the type of an object in your code, if this type can be inferred by the zig compiler (we talk more about that in Section 2.4). But there are other situations where you do need to be explicit. For example, you do have to explicitly specify the type of each function argument, and also, the return type of every function that you create in Zig.

    We specify the type of an object or a function argument in Zig by using a colon character (:) followed by the type after the name of this object/function argument. With the expressions a: i32 and b: i32, we know that both a and b arguments have type i32, which is a signed 32 bit integer. In this part, the syntax in Zig is identical to the syntax in Rust, which also specifies types by using the colon character.

    Lastly, we have the return type of the function at the end of the line, before we open the curly braces to start writing the function’s body. In the example above, this type is also a signed 32 bit integer (i32) value.

    Notice that we also have an export keyword before the function declaration. This keyword is similar to the extern keyword in C. It exposes the function to make it available in the library API. Therefore, if you are writing a library for other people to use, you have to expose the functions you write in the public API of this library by using this export keyword. If we removed the export keyword from the add() function declaration, then, this function would be no longer exposed in the library object built by the zig compiler.

    @@ -433,7 +435,7 @@

    1.2.3 The main.zig file

    Now that we have learned a lot about Zig’s syntax from the root.zig file, let’s take a look at the main.zig file. A lot of the elements we saw in root.zig are also present in main.zig. But there are some other elements that we haven’t seen yet, so let’s dive in.

    First, look at the return type of the main() function in this file. We can see a small change. The return type of the function (void) is accompanied by an exclamation mark (!). This exclamation mark tells us that this main() function might return an error.

    -

    Is worth noting that, a main() function in Zig is allowed to return nothing (void), or an unsigned 8-bit integer (u8) value6, or an error. In other words, you can write your main() function in Zig to return essentially nothing (void), or, if you prefer, you can also write a more C-like main() function, which returns an integer value that usually serves as a “status code” for the process.

    +

    It’s worth noting that, a main() function in Zig is allowed to return nothing (void), or an unsigned 8-bit integer (u8) value6, or an error. In other words, you can write your main() function in Zig to return essentially nothing (void), or, if you prefer, you can also write a more C-like main() function, which returns an integer value that usually serves as a “status code” for the process.

    In this example, the return type annotation of main() indicates that this function can either return nothing (void), or return an error. This exclamation mark in the return type annotation is an interesting and powerful feature of Zig. In summary, if you write a function and something inside the body of this function might return an error, then, you are forced to:

    • either add the exclamation mark to the return type of the function and make it clear that this function might return an error.
    • @@ -441,7 +443,7 @@

      In most programming languages, we normally handle (or deal with) an error through a try catch pattern. Zig does have both try and catch keywords. But they work a little differently than what you’re probably used to in other languages.

      If we look at the main() function below, you can see that we do have a try keyword on the 5th line. But we do not have a catch keyword in this code. In Zig, we use the try keyword to execute an expression that might return an error, which, in this example, is the stdout.print() expression.

      -

      In essence, the try keyword executes the expression stdout.print(). If this expression returns a valid value, then, the try keyword does absolutely nothing. It only passes the value forward. It is like if this try keyword was never there. However, if the expression does return an error, then, the try keyword will unwrap the error value, then, it returns this error from the function and also prints the current stack trace to stderr.

      +

      In essence, the try keyword executes the expression stdout.print(). If this expression returns a valid value, then, the try keyword does absolutely nothing. It only passes the value forward. It’s like if this try keyword was never there. However, if the expression does return an error, then, the try keyword will unwrap the error value, then, it returns this error from the function and also prints the current stack trace to stderr.

      This might sound weird to you if you come from a high-level language. Because in high-level languages, such as Python, if an error occurs somewhere, this error is automatically returned and the execution of your program will automatically stop even if you don’t want to stop the execution. You are obligated to face the error.

      const std = @import("std");
      @@ -477,12 +479,12 @@ 

      <

      1.2.6 Important note for Windows users

      First of all, this is a Windows-specific thing, and, therefore, does not apply to other operating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that includes some global variables whose initialization rely on runtime resources, then, you might have some troubles while trying to compile this Zig code on Windows.

      -

      An example of that is accessing the stdout (i.e. the standard output of your system), which is usually done in Zig by using the expression std.io.getStdOut(). Thus, if you use this expression to instantiate a global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows, with a “unable to evaluate comptime expression” error message.

      -

      This failure in the compilation process happens because all global variables in Zig are initialized at compile-time. However, operations like accessing the stdout (or opening a file) on Windows depends on resources that are available only at runtime (you will learn more about compile-time versus runtime at Section 3.1.1).

      +

      An example of that is accessing the stdout (i.e., the standard output of your system), which is usually done in Zig by using the expression std.io.getStdOut(). If you use this expression to instantiate a global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows, with an “unable to evaluate comptime expression” error message.

      +

      This failure in the compilation process happens because all global variables in Zig are initialized at compile-time. However, on Windows, operations like accessing the stdout (or opening a file) depend on resources that are available only at runtime (you will learn more about compile-time versus runtime in Section 3.1.1).

      For example, if you try to compile this code example on Windows, you will likely get the error message exposed below:

      const std = @import("std");
      -// ERROR! Compile-time error that emerge from
      +// ERROR! Compile-time error that emerges from
       // this next line, on the `stdout` object
       const stdout = std.io.getStdOut().writer();
       
      @@ -494,7 +496,7 @@ 

      Section 12.1.

      +

      This solves the problem because all expressions that are inside a function body in Zig are evaluated only at runtime, unless you use the comptime keyword explicitly to change this behaviour. You will learn more about this comptime keyword in Section 12.1.

      const std = @import("std");
       pub fn main() !void {
      @@ -504,7 +506,8 @@ 

      }

      Hello
      -

      You can read more details about this Windows-specific limitation at a couple of GitHub issues opened at the official Zig repository. More specifically, the issues 17186 7 and 19864 8.

      +

      You can read more details about this Windows-specific limitation in a couple of GitHub issues opened at the official Zig repository. More specifically, the issues

      +

      17186 7 and 19864 8.

      1.2.7 Compiling the entire project

      @@ -552,7 +555,7 @@

      Read the code written by one of the Zig core team members: https://github.com/kubkon;
    • Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: https://www.youtube.com/@ZigSHOWTIME/videos;
    -

    Another great strategy to learn Zig, or honestly, to learn any language you want, is to practice it by solving exercises. For example, there is a famous repository in the Zig community called Ziglings18 , which contains more than 100 small exercises that you can solve. It is a repository of tiny programs written in Zig that are currently broken, and your responsibility is to fix these programs, and make them work again.

    +

    Another great strategy to learn Zig, or honestly, to learn any language you want, is to practice it by solving exercises. For example, there is a famous repository in the Zig community called Ziglings18 , which contains more than 100 small exercises that you can solve. It’s a repository of tiny programs written in Zig that are currently broken, and your responsibility is to fix these programs, and make them work again.

    A famous tech YouTuber known as The Primeagen also posted some videos (on YouTube) where he solves these exercises from Ziglings. The first video is named “Trying Zig Part 1”19.

    Another great alternative, is to solve the Advent of Code exercises20. There are people that already took the time to learn and solve the exercises, and they posted their solutions on GitHub as well, so, in case you need some resource to compare while solving the exercises, you can look at these two repositories:

      @@ -561,7 +564,7 @@

    -

    1.4 Creating new objects in Zig (i.e. identifiers)

    +

    1.4 Creating new objects in Zig (i.e., identifiers)

    Let’s talk more about objects in Zig. Readers that have past experience with other programming languages might know this concept through a different name, such as: “variable” or “identifier”. In this book, I choose to use the term “object” to refer to this concept.

    To create a new object (or a new “identifier”) in Zig, we use the keywords const or var. These keywords specify if the object that you are creating is mutable or not. If you use const, then the object you are creating is a constant (or immutable) object, which means that once you declare this object, you can no longer change the value stored inside this object.

    On the other side, if you use var, then, you are creating a variable (or mutable) object. You can change the value of this object as many times you want. Using the keyword var in Zig is similar to using the keywords let mut in Rust.

    @@ -578,7 +581,7 @@

    var age: u8 = 24;
     age = 25;
    @@ -588,7 +591,7 @@

    1.4.2 Declaring without an initial value

    By default, when you declare a new object in Zig, you must give it an initial value. In other words, this means that we have to declare, and, at the same time, initialize every object we create in our source code.

    On the other hand, you can, in fact, declare a new object in your source code, and not give it an explicit value. But we need to use a special keyword for that, which is the undefined keyword.

    -

    Is important to emphasize that, you should avoid using undefined as much as possible. Because when you use this keyword, you leave your object uninitialized, and, as a consequence, if for some reason, your code use this object while it is uninitialized, then, you will definitely have undefined behaviour and major bugs in your program.

    +

    It’s important to emphasize that, you should avoid using undefined as much as possible. Because when you use this keyword, you leave your object uninitialized, and, as a consequence, if for some reason, your code uses this object while it’s uninitialized, then, you will definitely have undefined behaviour and major bugs in your program.

    In the example below, I’m declaring the age object again. But this time, I do not give it an initial value. The variable is only initialized at the second line of code, where I store the number 25 in this object.

    var age: u8 = undefined;
    @@ -599,7 +602,7 @@ 

    1.4.3 There is no such thing as unused objects

    Every object (being constant or variable) that you declare in Zig must be used in some way. You can give this object to a function call, as a function argument, or, you can use it in another expression to calculate the value of another object, or, you can call a method that belongs to this particular object.

    -

    It doesn’t matter in which way you use it. As long as you use it. If you try to break this rule, i.e. if your try to declare a object, but not use it, the zig compiler will not compile your Zig source code, and it will issue a error message warning that you have unused objects in your code.

    +

    It doesn’t matter in which way you use it. As long as you use it. If you try to break this rule, i.e., if your try to declare a object, but not use it, the zig compiler will not compile your Zig source code, and it will issue a error message warning that you have unused objects in your code.

    Let’s demonstrate this with an example. In the source code below, we declare a constant object called age. If you try to compile a simple Zig program with this line of code below, the compiler will return an error as demonstrated below:

    const age = 15;
    @@ -619,7 +622,7 @@

    const age = 15; _ = age;

    -

    Now, remember, everytime you assign a particular object to the underscore, this object is essentially destroyed. It is discarded by the compiler. This means that you can no longer use this object further in your code. It doesn’t exist anymore.

    +

    Now, remember, everytime you assign a particular object to the underscore, this object is essentially destroyed. It’s discarded by the compiler. This means that you can no longer use this object further in your code. It doesn’t exist anymore.

    So if you try to use the constant age in the example below, after we discarded it, you will get a loud error message from the compiler (talking about a “pointless discard”) warning you about this mistake.

    // It does not compile.
    @@ -630,7 +633,7 @@ 

    1.4.4 You must mutate every variable objects

    @@ -660,7 +663,7 @@

    1.6 Arrays

    -

    You create arrays in Zig by using a syntax that resembles the C syntax. First, you specify the size of the array (i.e. the number of elements that will be stored in the array) you want to create inside a pair of brackets.

    +

    You create arrays in Zig by using a syntax that resembles the C syntax. First, you specify the size of the array (i.e., the number of elements that will be stored in the array) you want to create inside a pair of brackets.

    Then, you specify the data type of the elements that will be stored inside this array. All elements present in an array in Zig must have the same data type. For example, you cannot mix elements of type f32 with elements of type i32 in the same array.

    After that, you simply list the values that you want to store in this array inside a pair of curly braces. In the example below, I am creating two constant objects that contain different arrays. The first object contains an array of 4 integer values, while the second object, an array of 3 floating point values.

    Now, you should notice that in the object ls, I am not explicitly specifying the size of the array inside of the brackets. Instead of using a literal value (like the value 4 that I used in the ns object), I am using the special character underscore (_). This syntax tells the zig compiler to fill this field with the number of elements listed inside of the curly braces. So, this syntax [_] is for lazy (or smart) programmers who leave the job of counting how many elements there are in the curly braces for the compiler.

    @@ -669,7 +672,7 @@

    const ls = [_]f64{432.1, 87.2, 900.05}; _ = ns; _ = ls;

    -

    Is worth noting that these are static arrays, meaning that they cannot grow in size. Once you declare your array, you cannot change the size of it. This is very common in low level languages. Because low level languages normally wants to give you (the programmer) full control over memory, and the way in which arrays are expanded is tightly related to memory management.

    +

    It’s worth noting that these are static arrays, meaning that they cannot grow in size. Once you declare your array, you cannot change the size of it. This is very common in low level languages. Because low level languages normally wants to give you (the programmer) full control over memory, and the way in which arrays are expanded is tightly related to memory management.

    1.6.1 Selecting elements of the array

    One very common activity is to select specific portions of an array you have in your source code. In Zig, you can select a specific element from your array, by simply providing the index of this particular element inside brackets after the object name. In the example below, I am selecting the third element from the ns array. Notice that Zig is a “zero-index” based language, like C, C++, Rust, Python, and many other languages.

    @@ -688,7 +691,7 @@

    _ = sl;

    When you use the start..end syntax, the “end tail” of the range selector is non-inclusive, meaning that, the index at the end is not included in the range that is selected from the array. Therefore, the syntax start..end actually means start..end - 1 in practice.

    -

    You can for example, create a slice that goes from the first to the last elements of the array, by using ar[0..ar.len] syntax In other words, it is a slice that access all elements in the array.

    +

    You can for example, create a slice that goes from the first to the last elements of the array, by using ar[0..ar.len] syntax In other words, it’s a slice that accesses all elements in the array.

    const ar = [4]u8{48, 24, 12, 6};
     const sl = ar[0..ar.len];
    @@ -722,7 +725,7 @@ 

    1.6.3 Array operators

    There are two array operators available in Zig that are very useful. The array concatenation operator (++), and the array multiplication operator (**). As the name suggests, these are array operators.

    -

    One important detail about these two operators is that they work only when both operands have a size (or “length”) that is compile-time known. We are going to talk more about the differences between “compile-time known” and “runtime known” at Section 3.1.1. But for now, keep this information in mind, that you cannot use these operators in every situation.

    +

    One important detail about these two operators is that they work only when both operands have a size (or “length”) that is compile-time known. We are going to talk more about the differences between “compile-time known” and “runtime known” in Section 3.1.1. But for now, keep this information in mind, that you cannot use these operators in every situation.

    In summary, the ++ operator creates a new array that is the concatenation, of both arrays provided as operands. So, the expression a ++ b produces a new array which contains all the elements from arrays a and b.

    const a = [_]u8{1,2,3};
    @@ -733,7 +736,7 @@ 

    { 1, 2, 3, 4, 5 }

    -

    This ++ operator is particularly useful to concatenate strings together. Strings in Zig are described in depth at Section 1.8. In summary, a string object in Zig is essentially an arrays of bytes. So, you can use this array concatenation operator to effectively concatenate strings together.

    +

    This ++ operator is particularly useful to concatenate strings together. Strings in Zig are described in depth in Section 1.8. In summary, a string object in Zig is essentially an arrays of bytes. So, you can use this array concatenation operator to effectively concatenate strings together.

    In contrast, the ** operator is used to replicate an array multiple times. In other words, the expression a ** 3 creates a new array which contains the elements of the array a repeated 3 times.

    const a = [_]u8{1,2,3};
    @@ -746,10 +749,10 @@ 

    1.6.4 Runtime versus compile-time known length in slices

    -

    We are going to talk a lot about the differences between compile-time known and runtime known across this book, especially at Section 3.1.1. But the basic idea is that a thing is compile-time known, when we know everything (the value, the attributes and the characteristics) about this thing at compile-time. In contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime. Therefore, we don’t know the value of this thing at compile-time, only at runtime.

    -

    We have learned at Section 1.6.1 that slices are created by using a range selector, which represents a range of indexes. When this “range of indexes” (i.e. the start and the end of this range) is known at compile-time, the slice object that get’s created is actually, under the hood, just a single-item pointer to an array.

    -

    You don’t need to precisely understand what that means now. We are going to talk a lot about pointers at Chapter 6. For now, just understand that, when the range of indexes is known at compile-time, the slice that get’s created is just a pointer to an array, accompanied by a length value that tells the size of the slice.

    -

    If you have a slice object like this, i.e. a slice that has a compile-time known range, you can use common pointer operations over this slice object. For example, you can dereference the pointer of this slice, by using the .* method, like you would do on a normal pointer object.

    +

    We are going to talk a lot about the differences between compile-time known and runtime known across this book, especially in Section 3.1.1. But the basic idea is that a thing is compile-time known, when we know everything (the value, the attributes and the characteristics) about this thing at compile-time. In contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime. Therefore, we don’t know the value of this thing at compile-time, only at runtime.

    +

    We have learned in Section 1.6.1 that slices are created by using a range selector, which represents a range of indexes. When this “range of indexes” (i.e., the start and the end of this range) is known at compile-time, the slice object that gets created is actually, under the hood, just a single-item pointer to an array.

    +

    You don’t need to precisely understand what that means now. We are going to talk a lot about pointers in Chapter 6. For now, just understand that, when the range of indexes is known at compile-time, the slice that gets created is just a pointer to an array, accompanied by a length value that tells the size of the slice.

    +

    If you have a slice object like this, i.e., a slice that has a compile-time known range, you can use common pointer operations over this slice object. For example, you can dereference the pointer of this slice, by using the .* method, like you would do on a normal pointer object.

    const arr1 = [10]u64 {
         1, 2, 3, 4, 5,
    @@ -759,7 +762,7 @@ 

    // Because we know both the start and end of the range. const slice = arr1[1..4];

    -

    On the other hand, if the range of indexes is not known at compile time, then, the slice object that get’s created is not a pointer anymore, and, thus, it does not support pointer operations. For example, maybe the start index is known at compile time, but the end index is not. In such case, the range of the slice becomes runtime known only.

    +

    On the other hand, if the range of indexes is not known at compile time, then, the slice object that gets created is not a pointer anymore, and, thus, it does not support pointer operations. For example, maybe the start index is known at compile time, but the end index is not. In such case, the range of the slice becomes runtime known only.

    In the example below, the slice object have a runtime known range, because the end index of the range is not known at compile time. In other words, the size of the array at buffer is not known at compile time. When we execute this program, the size of the array might be 10, or, it might be 12 depending on where we execute it. Therefore, we don’t know at compile time if the slice object have a range of size 10, or, a range of size 12.

    const std = @import("std");
    @@ -786,7 +789,7 @@ 

    -
    1/1 filea5b054e42b80.test.arrays are equal?...OKAl
    -  ll 1 tests passed.
    +
    1/1 file81c25513148.test.arrays are equal?...OKAll
    +  l 1 tests passed.

    At last, you might also want to use the expectEqualStrings() function. As the name suggests, you can use this function to test if two strings are equal or not. Just provide the two string objects that you want to compare, as inputs to the function.

    @@ -449,7 +449,7 @@

    ); }

    -
    1/1 t.test.strings are equal?... 
    +
    1/1 t.test.strings are equal?...
     ====== expected this output: =========
     hello, world!␃
     ======== instead found this: =========
    diff --git a/docs/Chapters/04-http-server.html b/docs/Chapters/04-http-server.html
    index 9b222d8b..48b876ef 100644
    --- a/docs/Chapters/04-http-server.html
    +++ b/docs/Chapters/04-http-server.html
    @@ -350,7 +350,7 @@ 

    7 

    7.1 What is a HTTP Server?

    First of all, what is a HTTP Server? A HTTP server, as any other type of server, is essentially a program that runs indefinitely, on an infinite loop, waiting for incoming connections from clients. Once the server receives an incoming connection, it will accept this connection, and it will send messages back-and-forth to the client through this connection.

    -

    But the messages that are transmitted inside this connection are in a specific format. They are HTTP messages (i.e. messages that use the HTTP Protocol specification). The HTTP Protocol is the backbone of the modern web. The world wide web as we know it today, would not exist without the HTTP Protocol.

    +

    But the messages that are transmitted inside this connection are in a specific format. They are HTTP messages (i.e., messages that use the HTTP Protocol specification). The HTTP Protocol is the backbone of the modern web. The world wide web as we know it today, would not exist without the HTTP Protocol.

    So, Web servers (which is just a fancy name to HTTP Servers) are servers that exchange HTTP messages with clients. And these HTTP servers and the HTTP Protocol specification are essential to the operation of the world wide web today.

    That is the whole picture of the process. Again, we have two subjects involved here, a server (which is a program that is running indefinitely, waiting to receive incoming connections), and a client (which is someone that wants to connect to the server, and exchange HTTP messages with it).

    You may find the material about the HTTP Protocol available at the Mozilla MDN Docs1 , a great resource for you to also look at. It gives you a great overview on how HTTP works, and what role the server plays in this matter.

    @@ -362,7 +362,7 @@

    After this entire process of dealing with the customer (searching for available apartments, receiving payment, handing over the keys), the receptionist goes back to what he was doing earlier, which is to wait. Wait for new customers to arrive.

    That is, in a nutshell, what a HTTP Server do. It waits for clients to connect to the server. When a client attempts to connect to the server, the server accepts this connection, and it starts to exchange messages with the client through this connection. The first message that happens inside this connection is always a message from the client to the server. This message is called the HTTP Request.

    This HTTP Request is a HTTP message that contains what the client wants from the server. It is literally a request. The client that connected to the server is asking this server to do something for him.

    -

    There are different “types of request” that a client can send to a HTTP Server. But the most basic type of request, is when a client ask to the HTTP Server to serve (i.e. to send) some specific web page (which is a HTML file) to him. When you type google.com in your web browser, you are essentially sending a HTTP Request to Google’s HTTP servers. This request is asking these servers to send the Google webpage to you.

    +

    There are different “types of request” that a client can send to a HTTP Server. But the most basic type of request, is when a client ask to the HTTP Server to serve (i.e., to send) some specific web page (which is a HTML file) to him. When you type google.com in your web browser, you are essentially sending a HTTP Request to Google’s HTTP servers. This request is asking these servers to send the Google webpage to you.

    Nonetheless, when the server receives this first message, the HTTP Request, it analyzes this request, to understand: who the client is? What he wants the server to do? This client has provided all the necessary information to perform the action that he asked? Etc.

    Once the server understands what the client wants, he simply perform the action that was requested, and, to finish the whole process, the server sends back a HTTP message to the client, informing if the action performed was successful or not, and, at last, the server ends (or closes) the connection with the client.

    This last HTTP message sent from the server to the client, is called the HTTP Response. Because the server is responding to the action that was requested by the client. The main objective of this response message is let the client know if the action requested was successful or not, before the server closes the connection.

    @@ -378,7 +378,7 @@

    When a connection arrive, we accept this connection, and we exchange the HTTP messages (HTTP Request and HTTP Response).
  • Then, we simply close this connection.
  • -

    A socket object is essentially a channel of communication. You are creating a channel where people can send messages through. When you create a socket object, this object is not binded to any particular address. This means that with this object you have a representation of a channel of communication in your hands. But this channel is not currently available, or, it is not currently accessible, because it do not have a known address where you can find it.

    +

    A socket object is essentially a channel of communication. You are creating a channel where people can send messages through. When you create a socket object, this object is not binded to any particular address. This means that with this object you have a representation of a channel of communication in your hands. But this channel is not currently available, or, it is not currently accessible, because it does not have a known address where you can find it.

    That is what the “bind” operation do. It binds a name (or more specifically, an address) to this socket object, or, this channel of communication, so that it becomes available, or, accessible through this address. While the “listen” operation makes the socket object to listen for incoming connections in this address. In other words, the “listen” operation makes the socket to wait for incoming connections. currently Now, when a client actually attempts to connect to the server through the socket address that we have specified, in order to establish this connection with the client, the socket object needs to accept this incoming connection. Thus, when we accept an incoming connection, the client and the server become connected to each other, and they can start reading or writing messages into this established connection.

    After we receive the HTTP Request from the client, analyze it, and send the HTTP Response to the client, we can then close the connection, and end this communication.

    @@ -387,8 +387,8 @@

    7.4.1 Creating the socket object

    Let’s begin with creating the socket object for our server. Just to make things shorter, I will create this socket object in a separate Zig module. I will name it config.zig.

    -

    In Zig, we can create a web socket using the std.posix.socket() function, from the Zig Standard Library. As I mentioned earlier at Section 7.3, every socket object that we create represents a communication channel, and we need to bind this channel to a specific address. An “address” is defined as an IP address, or, more specifically, an IPv4 address2. Every IPv4 address is composed by two components. The first component is the host, which is a sequence of 4 numbers separated by dot characters (.) that identifies the machine used. While the second component is a port number, which identifies the specific door, or, the specific port to use in the host machine.

    -

    The sequence of 4 numbers (i.e. the host) identifies the machine (i.e. the computer itself) where this socket will live in. Every computer normally have multiple “doors” available inside of him, because this allows the computer to receive and work with multiple connections at the same time. He simply use a single door for each connection. So the port number, is essentially a number that identifies the specific door in the computer that will be responsible for receiving the connection. That is, it identifies the “door” in the computer that the socket will use to receive incoming connections.

    +

    In Zig, we can create a web socket using the std.posix.socket() function, from the Zig Standard Library. As I mentioned earlier in Section 7.3, every socket object that we create represents a communication channel, and we need to bind this channel to a specific address. An “address” is defined as an IP address, or, more specifically, an IPv4 address2. Every IPv4 address is composed by two components. The first component is the host, which is a sequence of 4 numbers separated by dot characters (.) that identifies the machine used. While the second component is a port number, which identifies the specific door, or, the specific port to use in the host machine.

    +

    The sequence of 4 numbers (i.e., the host) identifies the machine (i.e., the computer itself) where this socket will live in. Every computer normally have multiple “doors” available inside of him, because this allows the computer to receive and work with multiple connections at the same time. He simply use a single door for each connection. So the port number, is essentially a number that identifies the specific door in the computer that will be responsible for receiving the connection. That is, it identifies the “door” in the computer that the socket will use to receive incoming connections.

    To make things simpler, I will use an IP address that identifies our current machine in this example. This means that, our socket object will reside on the same computer that we are currently using (this is also known as the “localhost”) to write this Zig source code.

    By convention, the IP address that identifies the “localhost”, which is the current machine we are using, is the IP 127.0.0.1. So, that is the IP address we are going to use in our server. I can declare it in Zig by using an array of 4 integers, like this:

    @@ -425,11 +425,11 @@

    7.4.2 Listening and receiving connections

    -

    Remember that we stored the Socket struct declaration that we built at Section 7.4.1 inside a Zig module named config.zig. This is why I imported this module into our main module (main.zig) in the example below, as the SocketConf object, to access the Socket struct.

    +

    Remember that we stored the Socket struct declaration that we built in Section 7.4.1 inside a Zig module named config.zig. This is why I imported this module into our main module (main.zig) in the example below, as the SocketConf object, to access the Socket struct.

    Once we created our socket object, we can focus now on making this socket object listen and receive new incoming connections. We do that, by calling the listen() method from the Address object that is contained inside the socket object, and then, we call the accept() method over the result.

    The listen() method from the Address object produces a server object, which is an object that will stay open and running indefinitely, waiting to receive an incoming connection. Therefore, if you try to run the code example below, by calling the run command from the zig compiler, you will notice that the programs keeps running indefinitely, without a clear end.

    -

    This happens, because the program is waiting for something to happen. It is waiting for someone to try to connect to the address (http://127.0.0.1:3490) where the server is running and listening for incoming connections. This is what the listen() method do, it makes the socket to be active waiting for someone to connect.

    -

    On the other side, the accept() method is the function that establishes the connection when someone tries to connect to the socket. This means that, the accept() method returns a new connection object as a result. And you can use this connection object to read or write messages from or to the client. For now, we are not doing anything with this connection object. But we are going to use it on the next section.

    +

    This happens, because the program is waiting for something to happen. It’s waiting for someone to try to connect to the address (http://127.0.0.1:3490) where the server is running and listening for incoming connections. This is what the listen() method do, it makes the socket to be active waiting for someone to connect.

    +

    On the other side, the accept() method is the function that establishes the connection when someone tries to connect to the socket. This means that, the accept() method returns a new connection object as a result. And you can use this connection object to read or write messages from or to the client. For now, we are not doing anything with this connection object. But we are going to use it in the next section.

    const std = @import("std");
     const SocketConf = @import("config.zig");
    @@ -444,13 +444,13 @@ 

    }

    This code example allows one single connection. In other words, the server will wait for one incoming connection, and as soon as the server is done with this first connection that it establishes, the program ends, and the server stops.

    -

    This is not the norm on the real world. Most people that write a HTTP server like this, usually put the accept() method inside a while (infinite) loop, where if a connection is created with accept(), a new thread of execution is created to deal with this new connection and the client. That is, real-world examples of HTTP Servers normally rely on parallel computing to work.

    +

    This is not the norm in the real world. Most people that write a HTTP server like this, usually put the accept() method inside a while (infinite) loop, where if a connection is created with accept(), a new thread of execution is created to deal with this new connection and the client. That is, real-world examples of HTTP Servers normally rely on parallel computing to work.

    With this design, the server simply accepts the connection, and the whole process of dealing with the client, and receiving the HTTP Request, and sending the HTTP Response, all of this is done in the background, on a separate execution thread.

    So, as soon as the server accepts the connection, and creates the separate thread, the server goes back to what he was doing earlier, which is to wait indefinitely for a new connection to accept. Having this in mind, the code example exposed above, is a server that serves only a single client. Because the program terminates as soon as the connection is accepted.

    7.4.3 Reading the message from the client

    -

    Now that we have a connection established, i.e. the connection object that we created through the accept() function, we can now use this connection object to read any messages that the client send to our server. But we can also use it to send messages back to the client.

    +

    Now that we have a connection established, i.e., the connection object that we created through the accept() function, we can now use this connection object to read any messages that the client send to our server. But we can also use it to send messages back to the client.

    The basic idea is, if we write any data into this connection object, then, we are sending data to the client, and if we read the data present in this connection object, then, we are reading any data that the client sent to us, through this connection object. So, just have this logic in mind. “Read” is for reading messages from the client, and “write” is to send a message to the client.

    Remember from Section 7.2 that, the first thing that we need to do is to read the HTTP Request sent by the client to our server. Because it is the first message that happens inside the established connection, and, as a consequence, it is the first thing that we need to deal with.

    That is why, I’m going to create a new Zig module in this small project, named request.zig to keep all functions related to the HTTP Request together. Then, I will create a new function named read_request() that will use our connection object to read the message sent by the client, which is the HTTP Request.

    @@ -495,7 +495,7 @@

    Figure 7.1. The message Server Addr: 127.0.0.1:3490 is printed to the console, and the program is now waiting for an incoming connection.

    +

    You can see that in Figure 7.1. The message Server Addr: 127.0.0.1:3490 is printed to the console, and the program is now waiting for an incoming connection.

    @@ -512,7 +512,7 @@

    Figure 7.2.

    +

    If you comeback to the console that you left open when you have executed the program, you will see that the program finished its execution, and, a new message is printed in the console, which is the actual HTTP Request message that was sent by the web browser to the server. You can see this message in Figure 7.2.

    @@ -544,7 +544,7 @@

    7.7 Implementing the server - Part 2

    @@ -557,7 +557,7 @@

    7.7.1 The top-level header

    The first line of text in a HTTP Request always come with the three most essential information about the request. These three key attributes of the HTTP Request are separated by a simple space in this first line of the request. The first information is the HTTP method that is being used in the request, second, we have the URI to which this HTTP Request is being sent to, and third, we have the version of the HTTP protocol that is being used in this HTTP Request.

    -

    In the snippet below, you can find an example of this first line in a HTTP Request. First, we have the HTTP method of this request (GET). Many programmers refer to the URI component (/users/list) as the “API endpoint” to which the HTTP Request is being sent to. In the context of this specific request, since it is a GET request, you could also say that the URI component is the path to the resource we want to access, or, the path to the document (or the file) that we want to retrieve from the server.

    +

    In the snippet below, you can find an example of this first line in a HTTP Request. First, we have the HTTP method of this request (GET). Many programmers refer to the URI component (/users/list) as the “API endpoint” to which the HTTP Request is being sent to. In the context of this specific request, since it’s a GET request, you could also say that the URI component is the path to the resource we want to access, or, the path to the document (or the file) that we want to retrieve from the server.

    GET /users/list HTTP/1.1

    Also, notice that this HTTP Request is using the version 1.1 of the HTTP protocol, which is the most popular version of the protocol used in the web.

    @@ -570,7 +570,7 @@

    7.7.3 The body

    -

    The body comes after the list of HTTP headers, and it is an optional section of the HTTP Request, meaning that, not all HTTP Request will come with a body in it. For example, every HTTP Request that uses the GET method usually do not come with a body.

    +

    The body comes after the list of HTTP headers, and it’s an optional section of the HTTP Request, meaning that, not all HTTP Requests will come with a body in them. For example, every HTTP Request that uses the GET method usually does not come with a body.

    Because a GET request is used to request data, instead of sending it to the server. So, the body section is more related to the POST method, which is a method that involves sending data to the server, to be processed and stored.

    Since we are going to support only the GET method in this project, it means that we also do not need to care about the body of the request.

    @@ -585,7 +585,7 @@

    };

    Now, I think we should add two methods to this enum structure. One method is is_supported(), which will be a function that returns a boolean value, indicating if the input HTTP method is supported or not by our HTTP Server. The other is init(), which is a constructor function that takes a string as input, and tries to convert it into a Method value.

    -

    But in order to build these functions, I will use a functionality from the Zig Standard Library, called StaticStringMap(). This function allows us to create a simple map from strings to enum values. In other words, we can use this map structure to map a string to the respective enum value. To some extent, this specific structure from the standard library works almost like a “hashtable” structure, and it is optimized for small sets of words, or, small sets of keys, which is our case here. We are going to talk more about hashtables in Zig at Section 11.2.

    +

    But in order to build these functions, I will use a functionality from the Zig Standard Library, called StaticStringMap(). This function allows us to create a simple map from strings to enum values. In other words, we can use this map structure to map a string to the respective enum value. To some extent, this specific structure from the standard library works almost like a “hashtable” structure, and it’s optimized for small sets of words, or, small sets of keys, which is our case here. We are going to talk more about hashtables in Zig in Section 11.2.

    To use this “static string map” structure, you have to import it from the std.static_string_map module of the Zig Standard Library. Just to make things shorter and easier to type, I am going to import this function through a different and shorter name (Map).

    -

    With Map() imported, we can just apply this function over the enum structure that we are going to use in the resulting map. In our case here, it is the Method enum structure that we declared at the last code example. Then, I call the initComptime() method with the map, i.e. the list of key-value pairs that we are going to use.

    +

    With Map() imported, we can just apply this function over the enum structure that we are going to use in the resulting map. In our case here, it’s the Method enum structure that we declared at the last code example. Then, I call the initComptime() method with the map, i.e., the list of key-value pairs that we are going to use.

    You can see in the example below that I wrote this map using multiple anonymous struct literals. Inside the first (or “top-level”) struct literal, we have a list (or a sequence) of struct literals. Each struct literal in this list represents a separate key-value pair. The first element (or the key) in each key-value pair should always be a string value. While the second element should be a value from the enum structure that you have used inside the Map() function.

    const Map = std.static_string_map.StaticStringMap;
    @@ -630,7 +630,7 @@ 

    7.7.5 Writing the parse request function

    Now that we created the enum that represents our HTTP method, we should start to write the function responsible for actually parsing the HTTP Request.

    -

    The first thing we can do, is to write a struct to represent the HTTP Request. Take the Request struct below as an example. It contains the three essential information from the “top-level” header (i.e. the first line) in the HTTP Request.

    +

    The first thing we can do, is to write a struct to represent the HTTP Request. Take the Request struct below as an example. It contains the three essential information from the “top-level” header (i.e., the first line) in the HTTP Request.

    const Request = struct {
         method: Method,
    @@ -650,7 +650,7 @@ 

    return request; }

    -

    As I described at Section 1.8, strings in Zig are simply arrays of bytes in the language. So, you will find lots of excellent utility functions to work directly with strings inside this mem module from the Zig Standard Library. We have described some of these useful utility functions already at Section 1.8.4.

    +

    As I described in Section 1.8, strings in Zig are simply arrays of bytes in the language. So, you will find lots of excellent utility functions to work directly with strings inside this mem module from the Zig Standard Library. We have described some of these useful utility functions already in Section 1.8.4.

    7.7.6 Using the parse request function

    @@ -735,7 +735,7 @@

    _ = try conn.stream.write(message); } -

    Notice that both functions receives the connection object as input, and use the write() method to write the HTTP Response message directly into this communication channel. As result, the party in the other side of the connection (i.e. the client), will receive such message.

    +

    Notice that both functions receives the connection object as input, and use the write() method to write the HTTP Response message directly into this communication channel. As result, the party in the other side of the connection (i.e., the client), will receive such message.

    Most real-world HTTP Servers will have a single function (or a single struct) to effectively handle the response. It gets the HTTP Request already parsed as input, and then, it tries to build the HTTP Response bit by bit, before the function sends it over the connection.

    We would also have a specialized struct to represent a HTTP Response, and a lot of methods that would be used to build each part or component of the response object. Take the Response struct created by the Javascript runtime Bun as an example. You can find this struct in the response.zig module4 in their GitHub project.

    @@ -744,7 +744,7 @@

    7.8 The end result

    We can now, update once again our main() function to incorporate our new functions from the response.zig module. First, I need to import this module into our main.zig module, then, I add the function calls to send_200() and send_404().

    Notice that I’m using if statements to decide which “response function” to call, based especially on the URI present in the HTTP Request. If the user asked for a content (or a document) that is not present in our server, we should respond with a 404 status code. But since we have just a simple HTTP server, with no real documents to send, we can just check if the URI is the root path (/) or not to decide which function to call.

    -

    Also, notice that I’m using the function std.mem.eql() from the Zig Standard Library to check if the string from uri is equal or not the string "/". We have described this function already at Section 1.8.4, so, comeback to that section if you are not familiar yet with this function.

    +

    Also, notice that I’m using the function std.mem.eql() from the Zig Standard Library to check if the string from uri is equal or not the string "/". We have described this function already in Section 1.8.4, so, comeback to that section if you are not familiar yet with this function.

    const std = @import("std");
     const SocketConf = @import("config.zig");
    diff --git a/docs/Chapters/05-pointers.html b/docs/Chapters/05-pointers.html
    index 1bc398f2..25812334 100644
    --- a/docs/Chapters/05-pointers.html
    +++ b/docs/Chapters/05-pointers.html
    @@ -333,8 +333,8 @@ 

    On our next project we are going to build a HTTP server from scratch. But in order to do that, we need to learn more about pointers and how they work in Zig. Pointers in Zig are similar to pointers in C. But they come with some extra advantages in Zig.

    -

    A pointer is an object that contains a memory address. This memory address is the address where a particular value is stored in memory. It can be any value. Most of the times, it is a value that comes from another object (or variable) present in our code.

    -

    In the example below, I’m creating two objects (number and pointer). The pointer object contains the memory address where the value of the number object (the number 5) is stored. So, that is a pointer in a nutshell. It is a memory address that points to a particular existing value in the memory. You could also say, that, the pointer object points to the memory address where the number object is stored.

    +

    A pointer is an object that contains a memory address. This memory address is the address where a particular value is stored in memory. It can be any value. Most of the times, it’s a value that comes from another object (or variable) present in our code.

    +

    In the example below, I’m creating two objects (number and pointer). The pointer object contains the memory address where the value of the number object (the number 5) is stored. So, that is a pointer in a nutshell. It’s a memory address that points to a particular existing value in the memory. You could also say, that, the pointer object points to the memory address where the number object is stored.

    const number: u8 = 5;
     const pointer = &number;
    @@ -351,7 +351,7 @@ 

    10

    -

    This syntax to dereference the pointer is nice. Because we can easily chain it with methods of the value pointed by the pointer. We can use the User struct that we have created at Section 2.3 as an example. If you comeback to that section, you will see that this struct have a method named print_name().

    +

    This syntax to dereference the pointer is nice. Because we can easily chain it with methods of the value pointed by the pointer. We can use the User struct that we have created in Section 2.3 as an example. If you comeback to that section, you will see that this struct have a method named print_name().

    So, for example, if we have an user object, and a pointer that points to this user object, we can use the pointer to access this user object, and, at the same time, call the method print_name() on it, by chaining the dereference method (*) with the print_name() method. Like in the example below:

    const u = User.init(1, "pedro", "email@gmail.com");
    @@ -369,12 +369,12 @@ 

    6

    -

    Therefore, as I mentioned earlier, people use pointers as an alternative way to access a particular value. And they use it especially when they do not want to “move” these values around. There are situations where, you want to access a particular value in a different scope (i.e. a different location) of your code, but you do not want to “move” this value to this new scope (or location) that you are in.

    +

    Therefore, as I mentioned earlier, people use pointers as an alternative way to access a particular value. And they use it especially when they do not want to “move” these values around. There are situations where, you want to access a particular value in a different scope (i.e., a different location) of your code, but you do not want to “move” this value to this new scope (or location) that you are in.

    This matters especially if this value is big in size. Because if it is, then, moving this value becomes an expensive operation to do. The computer will have to spend a considerable amount of time copying this value to this new location.

    Therefore, many programmers prefer to avoid this heavy operation of copying the value to the new location, by accessing this value through pointers. We are going to talk more about this “moving operation” over the next sections. For now, just keep in mind that avoiding this “move operation” is one of main reasons why pointers are used in programming languages.

    6.1 Constant objects vs variable objects

    -

    You can have a pointer that points to a constant object, or, a pointer that points to a variable object. But regardless of who this pointer is, a pointer must always respect the characteristics of the object that it points to. As a consequence, if the pointer points to a constant object, then, you cannot use this pointer to change the value that it points to. Because it points to a value that is constant. As we discussed at Section 1.4, you cannot change a value that is constant.

    +

    You can have a pointer that points to a constant object, or, a pointer that points to a variable object. But regardless of who this pointer is, a pointer must always respect the characteristics of the object that it points to. As a consequence, if the pointer points to a constant object, then, you cannot use this pointer to change the value that it points to. Because it points to a value that is constant. As we discussed in Section 1.4, you cannot change a value that is constant.

    For example, if I have a number object, which is constant, I cannot execute the expression below where I’m trying to change the value of number to 6 through the pointer object. As demonstrated below, when you try to do something like that, you get a compile time error:

    const number = 5;
    @@ -396,7 +396,7 @@ 

    You can see this relationship between “constant versus variable” on the data type of your pointer object. In other words, the data type of a pointer object already gives you some clues about whether the value that it points to is constant or not.

    When a pointer object points to a constant value, then, this pointer have a data type *const T, which means “a pointer to a constant value of type T”. In contrast, if the pointer points to a variable value, then, the type of the pointer is usually *T, which is simply “a pointer to a value of type T”. Hence, whenever you see a pointer object whose data type is in the format *const T, then, you know that you cannot use this pointer to change the value that it points to. Because this pointer points to a constant value of type T.

    We have talked about the value pointed by the pointer being constant or not, and the consequences that arises from it. But, what about the pointer object itself? I mean, what happens if the pointer object itself is constant or not? Think about it. We can have a constant pointer that points to a constant value. But we can also have a variable pointer that points to a constant value. And vice-versa.

    -

    Until this point, the pointer object was always constant, but what this means for us? What is the consequence of the pointer object being constant? The consequence is that we cannot change the pointer object, because it is constant. We can use the pointer object in multiple ways, but we cannot change the memory address that is inside this pointer object.

    +

    Until this point, the pointer object was always constant, but what does this mean for us? What is the consequence of the pointer object being constant? The consequence is that we cannot change the pointer object, because it is constant. We can use the pointer object in multiple ways, but we cannot change the memory address that is inside this pointer object.

    However, if we mark the pointer object as a variable object, then, we can change the memory address pointed by this pointer object. The example below demonstrates that. Notice that the object pointed by the pointer object changes from c1 to c2.

    const c1: u8 = 5;
    @@ -437,9 +437,9 @@ 

    1 2 3

    -

    Although you can create a pointer to an array like that, and start to walk through this array by using pointer arithmetic, in Zig, we prefer to use slices, which were presented at Section 1.6.

    +

    Although you can create a pointer to an array like that, and start to walk through this array by using pointer arithmetic, in Zig, we prefer to use slices, which were presented in Section 1.6.

    Behind the hood, slices already are pointers, and they also come with the len property, which indicates how many elements are in the slice. This is good because the zig compiler can use it to check for potential buffer overflows, and other problems like that.

    -

    Also, you don’t need to use pointer arithmetic to walk through the elements of a slice. You can simply use the slice[index] syntax to directly access any element you want in the slice. As I mentioned at Section 1.6, you can get a slice from an array by using a range selector inside brackets. In the example below, I’m creating a slice (sl) that covers the entire ar array. I can access any element of ar from this slice, and, the slice itself already is a pointer behind the hood.

    +

    Also, you don’t need to use pointer arithmetic to walk through the elements of a slice. You can simply use the slice[index] syntax to directly access any element you want in the slice. As I mentioned in Section 1.6, you can get a slice from an array by using a range selector inside brackets. In the example below, I’m creating a slice (sl) that covers the entire ar array. I can access any element of ar from this slice, and, the slice itself already is a pointer behind the hood.

    const ar = [_]i32{1,2,3,4};
     const sl = ar[0..ar.len];
    @@ -474,7 +474,7 @@ 

    6.4.2 Optional pointers

    You can also mark a pointer object as an optional pointer, meaning that, this object contains either a null value, or, a pointer that points to a value. When you mark a pointer as optional, the data type of this pointer object becomes ?*const T or ?*T, depending if the value pointed by the pointer is a constant value or not. The ? identifies the object as optional, while the * identifies it as a pointer object.

    -

    In the example below, we are creating a variable object named num, and an optional pointer object named ptr. Notice that the data type of the object ptr indicates that it is either a null value, or a pointer to an i32 value. Also, notice that the pointer object (ptr) can be marked as optional, even if the object num is not optional.

    +

    In the example below, we are creating a variable object named num, and an optional pointer object named ptr. Notice that the data type of the object ptr indicates that it’s either a null value, or a pointer to an i32 value. Also, notice that the pointer object (ptr) can be marked as optional, even if the object num is not optional.

    What this code tells us is that, the num variable will never contain a null value. This variable will always contain a valid i32 value. But in contrast, the ptr object might contain either a null value, or, a pointer to an i32 value.

    var num: i32 = 5;
    @@ -493,7 +493,7 @@ 

    6.4.3 Null handling in optionals

    -

    When you have an optional object in your Zig code, you have to explicitly handle the possibility of this object being null. It is like error-handling with try and catch. In Zig you also have to handle null values like if they were a type of error.

    +

    When you have an optional object in your Zig code, you have to explicitly handle the possibility of this object being null. It’s like error-handling with try and catch. In Zig you also have to handle null values like if they were a type of error.

    We can do that, by using either:

    • an if statement, like you would do in C.
    • diff --git a/docs/Chapters/07-build-system.html b/docs/Chapters/07-build-system.html index 1ea868f0..ed90246f 100644 --- a/docs/Chapters/07-build-system.html +++ b/docs/Chapters/07-build-system.html @@ -322,11 +322,11 @@

      In this chapter, we are going to talk about the build system, and how an entire project is built in Zig. One key advantage of Zig is that it includes a build system embedded in the language itself. This is great, because then you do not have to depend on an external system, separated from the compiler, to build your code.

      -

      You can find a good description of Zig’s build system on the article entitled “Build System”1 from the official Zig’s website. We also have the excellent series of posts written by Felix2. Hence, this chapter represents an extra resource for you to consult and rely on.

      +

      You can find a good description of Zig’s build system in the article entitled “Build System”1 from the official Zig’s website. We also have the excellent series of posts written by Felix2. Hence, this chapter represents an extra resource for you to consult and rely on.

      Building code is one of the things that Zig is best at. One thing that is particularly difficult in C/C++ and even in Rust, is to cross-compile source code to multiple targets (e.g. multiple computer architectures and operating systems), and the zig compiler is known for being one of the best existing pieces of software for this particular task.

      9.1 How source code is built?

      -

      We already have talked about the challenges of building source code in low-level languages at Section 1.2.1. As we described at that section, programmers invented Build Systems to surpass these challenges on the process of building source code in low-level languages.

      +

      We already have talked about the challenges of building source code in low-level languages in Section 1.2.1. As we described at that section, programmers invented Build Systems to surpass these challenges on the process of building source code in low-level languages.

      Low-level languages uses a compiler to compile (or to build) your source code into binary instructions. In C and C++, we normally use compilers like gcc, g++ or clang to compile our C and C++ source code into these instructions. Every language have its own compiler, and this is no different in Zig.

      In Zig, we have the zig compiler to compile our Zig source code into binary instructions that can be executed by our computer. In Zig, the compilation (or the build) process involves the following components:

        @@ -335,7 +335,7 @@

        Compiler flags that tailors the build process to your needs.

      These are the things that you need to connect together in order to build your source code in Zig. In C and C++, you would have an extra component, which are the header files of the libraries that you are using. But header files do not exist in Zig, so, you only need to care about them if you are linking your Zig source code with a C library. If that is not your case, you can forget about it.

      -

      Your build process is usually organized in a build script. In Zig, we normally write this build script into a Zig module in the root directory of our project, named as build.zig. You write this build script, then, when you run it, your project get’s built into binary files that you can use and distribute to your users.

      +

      Your build process is usually organized in a build script. In Zig, we normally write this build script into a Zig module in the root directory of our project, named as build.zig. You write this build script, then, when you run it, your project gets built into binary files that you can use and distribute to your users.

      This build script is normally organized around target objects. A target is simply something to be built, or, in other words, it’s something that you want the zig compiler to build for you. This concept of “targets” is present in most Build Systems, especially in CMake3.

      There are four types of target objects that you can build in Zig, which are:

        @@ -344,11 +344,11 @@

        A static library (e.g. a .a file in Linux or a .lib file on Windows).
      • An executable file that executes only unit tests (or, a “unit tests executable”).
      -

      We are going to talk more about these target objects at Section 9.3.

      +

      We are going to talk more about these target objects in Section 9.3.

      9.2 The build() function

      -

      A build script in Zig always contains a public (and top-level) build() function declared. It is like the main() function on the main Zig module of your project, that we discussed at Section 1.2.3. But instead of creating the entrypoint to your code, this build() function is the entrypoint to the build process.

      +

      A build script in Zig always contains a public (and top-level) build() function declared. It’s like the main() function in the main Zig module of your project, that we discussed in Section 1.2.3. But instead of creating the entrypoint to your code, this build() function is the entrypoint to the build process.

      This build() function should accept a pointer to a Build object as input, and it should use this “build object” to perform the necessary steps to build your project. The return type of this function is always void, and this Build struct comes directly from the Zig Standard Library (std.Build). So, you can access this struct by just importing the Zig Standard Library into your build.zig module.

      Just as a very simple example, here you can see the source code necessary to build an executable file from the hello.zig Zig module.

      @@ -368,7 +368,7 @@

      9.3 Target objects

      As we described over the previous sections, a build script is composed around target objects. Each target object is normally a binary file (or an output) that you want to get from the build process. You can list multiple target objects in your build script, so that the build process generates multiple binary files for you at once.

      For example, maybe you are a developer working in a cross-platform application, and, because this application is cross-platform, you probably need to release binary files of your software for each OS supported by your application to your end users. Thus, you can define a different target object in your build script for each OS (Windows, Linux, etc.) where you want to publish your software. This will make the zig compiler to build your project to multiple target OS’s at once. The Zig Build System official documentation have a great code example that demonstrates this strategy4.

      -

      A target object is created by the following methods of the Build struct that we introduced at Section 9.2:

      +

      A target object is created by the following methods of the Build struct that we introduced in Section 9.2:

      • addExecutable() creates an executable file;
      • addSharedLibrary() creates a shared library file;
      • @@ -384,11 +384,11 @@

        .target = b.host, });

    -

    The name option specify the name that you want to give to the binary file defined by this target object. So, in this example, we are building an executable file named hello. Is common to set this name option to the name of your project.

    +

    The name option specify the name that you want to give to the binary file defined by this target object. So, in this example, we are building an executable file named hello. It’s common to set this name option to the name of your project.

    Furthermore, the target option specify the target computer architecture (or the target operating system) of this binary file. For example, if you want this target object to run on a Windows machine that uses a x86_64 architecture, you can set this target option to x86_64-windows-gnu for example. This will make the zig compiler to compile the project to run on a x86_64 Windows machine. You can see the full list of architectures and OS’s that the zig compiler supports by running the zig targets command in the terminal.

    Now, if you are building the project to run on the current machine that you are using to run this build script, you can set this target option to the host method of the Build object, like we did in the example above. This host method identifies the current machine where you are currently running the zig compiler.

    -

    At last, the root_source_file option specifies the root Zig module of your project. That is the Zig module that contains the entrypoint to your application (i.e. the main() function), or, the main API of your library. This also means that, all the Zig modules that compose your project are automatically discovered from the import statements you have inside this “root source file”. The zig compiler can detect when a Zig module depends on the other through the import statements, and, as a result, it can discover the entire map of Zig modules used in your project.

    -

    This is handy, and it is different from what happens in other build systems. In CMake for example, you have to explicitly list the paths to all source files that you want to include in your build process. This is probably a symptom of the “lack of conditional compilation” in the C and C++ compilers. Since they lack this feature, you have to explicitly choose which source files should be sent to the C/C++ compiler, because not every C/C++ code is portable or supported in every operating system, and, therefore, would cause a compilation error in the C/C++ compiler.

    +

    At last, the root_source_file option specifies the root Zig module of your project. That is the Zig module that contains the entrypoint to your application (i.e., the main() function), or, the main API of your library. This also means that, all the Zig modules that compose your project are automatically discovered from the import statements you have inside this “root source file”. The zig compiler can detect when a Zig module depends on the other through the import statements, and, as a result, it can discover the entire map of Zig modules used in your project.

    +

    This is handy, and it’s different from what happens in other build systems. In CMake for example, you have to explicitly list the paths to all source files that you want to include in your build process. This is probably a symptom of the “lack of conditional compilation” in the C and C++ compilers. Since they lack this feature, you have to explicitly choose which source files should be sent to the C/C++ compiler, because not every C/C++ code is portable or supported in every operating system, and, therefore, would cause a compilation error in the C/C++ compiler.

    Now, one important detail about the build process is that, you have to explicitly install the target objects that you create in your build script, by using the installArtifact() method of the Build struct.

    Everytime you invoke the build process of your project, by calling the build command of the zig compiler, a new directory named zig-out is created in the root directory of your project. This new directory contains the outputs of the build process, that is, the binary files built from your source code.

    What the installArtifact() method do is to install (or copy) the built target objects that you defined to this zig-out directory. This means that, if you do not install the target objects you define in your build script, these target objects are essentially discarded at the end of the build process.

    @@ -407,9 +407,9 @@

    9.4 Setting the build mode

    We have talked about the three essential options that are set when you create a new target object. But there is also a fourth option that you can use to set the build mode of this target object, which is the optimize option. This option is called this way, because the build modes in Zig are treated more of an “optimization vs safety” problem. So optimization plays an important role here. Don’t worry, I’m going back to this question very soon.

    -

    In Zig, we have four build modes (which are listed below). Each one of these build modes offer different advantages and characteristics. As we described at Section 5.2.1, the zig compiler uses the Debug build mode by default, when you don’t explicitly choose a build mode.

    +

    In Zig, we have four build modes (which are listed below). Each one of these build modes offer different advantages and characteristics. As we described in Section 5.2.1, the zig compiler uses the Debug build mode by default, when you don’t explicitly choose a build mode.

      -
    • Debug, mode that produces and includes debugging information in the output of the build process (i.e. the binary file defined by the target object);
    • +
    • Debug, mode that produces and includes debugging information in the output of the build process (i.e., the binary file defined by the target object);
    • ReleaseSmall, mode that tries to produce a binary file that is small in size;
    • ReleaseFast, mode that tries to optimize your code, in order to produce a binary file that is as fast as possible;
    • ReleaseSafe, mode that tries to make your code as safe as possible, by including safeguards when possible.
    • @@ -444,7 +444,7 @@

      9.6 Detecting the OS in your build script

      -

      Is very common in Build Systems to use different options, or, to include different modules, or, to link against different libraries depending on the Operational System (OS) that you are targeting in the build process.

      +

      It’s very common in Build Systems to use different options, or, to include different modules, or, to link against different libraries depending on the Operational System (OS) that you are targeting in the build process.

      In Zig, you can detect the target OS of the build process, by looking at the os.tag inside the builtin module from the Zig library. In the example below, we are using an if statement to run some arbitrary code when the target of the build process is a Windows system.

      const builtin = @import("builtin");
      @@ -456,7 +456,7 @@ 

      9.7 Adding a run step to your build process

      -

      One thing that is neat in Rust is that you can compile and run your source code with one single command (cargo run) from the Rust compiler. We saw at Section 1.2.5 how can we perform a similar job in Zig, by building and running our Zig source code through the run command from the zig compiler.

      +

      One thing that is neat in Rust is that you can compile and run your source code with one single command (cargo run) from the Rust compiler. We saw in Section 1.2.5 how can we perform a similar job in Zig, by building and running our Zig source code through the run command from the zig compiler.

      But how can we, at the same time, build and run the binary file specified by a target object in our build script? The answer is by including a “run artifact” in our build script. A run artifact is created through the addRunArtifact() method from the Build struct. We simply provide as input to this function the target object that describes the binary file that we want to execute. As a result, this function creates a run artifact that is capable of executing this binary file.

      In the example below, we are defining an executable binary file named hello, and we use this addRunArtifact() method to create a run artifact that will execute this hello executable file.

      @@ -492,8 +492,8 @@

      9.8 Build unit tests in your project

      -

      We have talked at length about writing unit tests in Zig at Chapter 8, and we also have talked about how to execute these unit tests through the test command of the zig compiler. However, as we did with the run command on the previous section, we also might want to include some commands in our build script to also build and execute the unit tests in our project.

      -

      So, once again, we are going to discuss how a specific built-in command from the zig compiler, (in this case, the test command) can be used in a build script in Zig. Here is where a “test target object” comes into play. As was described at Section 9.3, we can create a test target object by using the addTest() method of the Build struct. The first thing that we need to do is to declare a test target object in our build script.

      +

      We have talked at length about writing unit tests in Zig in Chapter 8, and we also have talked about how to execute these unit tests through the test command of the zig compiler. However, as we did with the run command on the previous section, we also might want to include some commands in our build script to also build and execute the unit tests in our project.

      +

      So, once again, we are going to discuss how a specific built-in command from the zig compiler, (in this case, the test command) can be used in a build script in Zig. Here is where a “test target object” comes into play. As was described in Section 9.3, we can create a test target object by using the addTest() method of the Build struct. The first thing that we need to do is to declare a test target object in our build script.

      const test_exe = b.addTest(.{
           .name = "unit_tests",
      @@ -502,7 +502,7 @@ 

      }); b.installArtifact(test_exe);

      -

      A test target object essentially selects all test blocks in all Zig modules across your project, and builds only the source code present inside these test blocks in your project. As a result, this target object creates an executable file that contains only the source code present in all of these test blocks (i.e. the unit tests) in your project.

      +

      A test target object essentially selects all test blocks in all Zig modules across your project, and builds only the source code present inside these test blocks in your project. As a result, this target object creates an executable file that contains only the source code present in all of these test blocks (i.e., the unit tests) in your project.

      Perfect! Now that we have declared this test target object, an executable file named unit_tests is built by the zig compiler when we trigger the build script with the build command. After the build process is finished, we can simply execute this unit_tests executable in the terminal.

      However, if you remember the previous section, we already learned how can we create a run step in our build script, to execute an executable file built by the build script.

      So, we could simply add a run step in our build script to run these unit tests from a single command in the zig compiler, to make our lifes easier. In the example below, we demonstrate the commands to register a new build step called “tests” in our build script to run these unit tests.

      @@ -543,7 +543,7 @@

      9.10 Linking to external libraries

      One essential part of every build process is the linking stage. This stage is responsible for combining the multiple object files that represent your code, into a single executable file. It also links this executable file to external libraries, if you use any in your code.

      -

      In Zig, we have two notions of a “library”, which are: 1) a system’s library; 2) a local library. A system’s library is just a library that already is installed in your system. While a local library is a library that belongs to the current project. Is a library that is present in your project directory, and that you are building together with your project source code.

      +

      In Zig, we have two notions of a “library”, which are: 1) a system’s library; 2) a local library. A system’s library is just a library that is already installed in your system. While a local library is a library that belongs to the current project; a library that is present in your project directory, and that you are building together with your project source code.

      The basic difference between the two, is that a system’s library is already built and installed in your system, supposedly, and all you need to do is to link your source code to this library to start using it. We do that by using the linkSystemLibrary() method from a Compile object. This method accepts the name of the library in a string as input. Remember from Section 9.3 that a Compile object is a target object that you declare in your build script.

      When you link a particular target object with a system’s library, the zig compiler will use pkg-config to find where are the binary files and also the header files of this library in your system. When it finds these files, the linker present in the zig compiler will link your object files with the files of this library to produce a single binary file for you.

      In the example below, we are creating an executable file named image_filter, and, we are linking this executable file to the C Standard Library with the method linkLibC(), but we also are linking this executable file to the C library libpng that is currently installed in my system.

      @@ -588,7 +588,7 @@

      9.11 Building C code

      The zig compiler comes with a C compiler embedded in it. In other words, you can use the zig compiler to build C projects. This C compiler is available through the cc command of the zig compiler.

      -

      As an example, let’s use the famous FreeType library9. FreeType is one of the most widely used pieces of software in the world. It is a C library designed to produce high-quality fonts. But it is also heavily used in the industry to natively render text and fonts in the screen of your computer.

      +

      As an example, let’s use the famous FreeType library9. FreeType is one of the most widely used pieces of software in the world. It’s a C library designed to produce high-quality fonts. But it’s also heavily used in the industry to natively render text and fonts in the screen of your computer.

      In this section, we are going to write a build script, piece by piece, that is capable of building the FreeType project from source. You can find the source code of this build script on the freetype-zig repository10 available at GitHub.

      After you download the source code of FreeType from the official website11, you can start writing the build.zig module. We begin by defining the target object that defines the binary file that we want to compile.

      As an example, I will build the project as a static library file using the addStaticLibrary() method to create the target object. Also, since FreeType is a C library, I will also link the library against libc through the linkLibC() method, to guarantee that any use of the C Standard Library is covered in the compilation process.

      @@ -613,7 +613,7 @@

      "-Werror", };

      -

      In theory, there is nothing stopping you from using this array to add “include paths” (with the -I flag) or “library paths” (with the -L flag) to the compilation process. But there are formal ways in Zig to add these types of paths in the compilation process. Both are discussed at Section 9.11.5 and Section 9.11.4.

      +

      In theory, there is nothing stopping you from using this array to add “include paths” (with the -I flag) or “library paths” (with the -L flag) to the compilation process. But there are formal ways in Zig to add these types of paths in the compilation process. Both are discussed in Section 9.11.5 and Section 9.11.4.

      Anyway, in Zig, we add C flags to the build process together with the C files that we want to compile, by using the addCSourceFile() and addCSourceFiles() methods. In the example above, we have just declared the C flags that we want to use. But we haven’t added them to the build process yet. To do that, we also need to list the C files to be compiled.

    @@ -638,8 +638,8 @@

    };

    Now that we declared both the files that we want to include and the C compiler flags to be used, we can add them to the target object that describes the FreeType library, by using the addCSourceFile() and addCSourceFiles() methods.

    -

    Both of these functions are methods from a Compile object (i.e. a target object). The addCSourceFile() method is capable of adding a single C file to the target object, while the addCSourceFiles() method is used to add multiple C files in a single command. You might prefer to use addCSourceFile() when you need to use different compiler flags on specific C files in your project. But, if you can use the same compiler flags across all C files, then, you will probably find addCSourceFiles() a better choice.

    -

    Notice that we are using the addCSourceFiles() method in the example below, to add both the C files and the C compiler flags. Also notice that we are using the os.tag that we learned about at Section 9.6, to add the platform-specific C files.

    +

    Both of these functions are methods from a Compile object (i.e., a target object). The addCSourceFile() method is capable of adding a single C file to the target object, while the addCSourceFiles() method is used to add multiple C files in a single command. You might prefer to use addCSourceFile() when you need to use different compiler flags on specific C files in your project. But, if you can use the same compiler flags across all C files, then, you will probably find addCSourceFiles() a better choice.

    +

    Notice that we are using the addCSourceFiles() method in the example below, to add both the C files and the C compiler flags. Also notice that we are using the os.tag that we learned about in Section 9.6, to add the platform-specific C files.

    const builtin = @import("builtin");
     lib.addCSourceFiles(
    @@ -666,7 +666,7 @@ 

    9.11.3 Defining C Macros

    C Macros are an essential part of the C programming language, and they are commonly defined through the -D flag from a C compiler. In Zig, you can define a C Macro to be used in your build process by using the defineCMacro() method from the target object that defines the binary file that you are building.

    -

    In the example below, we are using the lib object that we have defined on the previous sections to define some C Macros used by the FreeType project in the compilation process. These C Macros specify if FreeType should (or should not) include functionalities from different external libraries.

    +

    In the example below, we are using the lib object that we have defined in the previous sections to define some C Macros used by the FreeType project in the compilation process. These C Macros specify if FreeType should (or should not) include functionalities from different external libraries.

    lib.defineCMacro("FT_DISABLE_ZLIB", "TRUE");
     lib.defineCMacro("FT_DISABLE_PNG", "TRUE");
    @@ -690,7 +690,7 @@ 

    9.11.5 Adding include paths

    -

    The preprocessor search path is a popular concept from the C community, but it is also known by many C programmers as “include paths”, because the paths in this “search path” relate to the #include statements found in the C files.

    +

    The preprocessor search path is a popular concept from the C community, but it’s also known by many C programmers as “include paths”, because the paths in this “search path” relate to the #include statements found in the C files.

    Include paths are similar to library paths. They are a set of pre-defined places in your computer where the C compiler will look for files during the compilation process. But instead of looking for library files, the include paths are places where the compiler looks for header files included in your C source code. This is why many C programmers prefer to call these paths as the “preprocessor search path”. Because header files are processed during the preprocessor stage of the compilation process.

    So, every header file that you include in your C source code, through a #include statements needs to be found somewhere, and the C compiler will search for this header file across the paths listed in this “include paths” set. Include paths are added to the compilation process through the -I flag.

    In Zig, you can add new paths to this pre-defined set of paths, by using the addIncludePath() method from your target object. This method also accepts a LazyPath object as input.

    diff --git a/docs/Chapters/09-data-structures.html b/docs/Chapters/09-data-structures.html index 75cbf5a3..12765e04 100644 --- a/docs/Chapters/09-data-structures.html +++ b/docs/Chapters/09-data-structures.html @@ -384,7 +384,7 @@

    When we talk about dynamic arrays, we usually have two similar concepts that are very essential to how a dynamic array works behind the hood. These concepts are capacity and length. In some contexts, especially in C++, length is also called of size.

    Although they look similar, these concepts represent different things in the context of a dynamic array. Capacity is the number of items (or elements) that your dynamic array can currently hold without the need to allocate more memory.

    In contrast, the length refers to how many elements in the array are currently being used, or, in other words, how many elements in this array that you have assigned a value to. Every dynamic array works around a block of allocated memory, which represents an array with total capacity for \(n\) elements. However, only a portion of these \(n\) elements are being used most of the time. This portion of \(n\) is the length of the array. So every time you append a new value to the array, you are incrementing its length by one.

    -

    This means that a dynamic array usually works with an extra margin, or, an extra space which is currently empty, but it is waiting and ready to be used. This “extra space” is essentially the difference between capacity and length. Capacity represents the total number of elements that the array can hold without the need to re-allocate or re-expand the array, while the length represents how much of this capacity is currently being used to hold/store values.

    +

    This means that a dynamic array usually works with an extra margin, or an extra space that is currently empty, but waiting and ready to be used. This “extra space” is essentially the difference between capacity and length. Capacity represents the total number of elements that the array can hold without the need to re-allocate or re-expand the array, while the length represents how much of this capacity is currently being used to hold/store values.

    Figure 11.1 presents this idea visually. Notice that, at first, the capacity of the array is greater than the length of the array. So, the dynamic array have extra space that is currently empty, but it is ready to receive a value to be stored.

    @@ -396,9 +396,9 @@

    -

    We can also see at Figure 11.1 that, when length and capacity are equal, it means that the array have no space left. We have reached the ceiling of our capacity, and because of that, if we want to store more values in this array, we need to expand it. We need to get a bigger space that can hold more values than what we currently have.

    -

    A dynamic array works by expanding the underlying array, whenever the length becomes equal to the capacity of the array. It basically allocates a new contiguous block of memory that is bigger than the previous one, then, it copies all values that are currently being stored to this new location (i.e. this new block of memory), then, it frees the previous block of memory. At the end of this process, the new underlying array have a bigger capacity, and, therefore, the length becomes, once again, smaller than the capacity of the array.

    -

    This is the cycle of an dynamic array. Notice that, throughout this cycle, the capacity is always either equal to or higher than the length of the array. If youh have an ArrayList object (let’s suppose you named it buffer), you can check the current capacity of your array by accessing the capacity attribute of your ArrayList object, while the current length of it is available at the items.len attribute.

    +

    We can also see in Figure 11.1 that, when length and capacity are equal, it means that the array have no space left. We have reached the ceiling of our capacity, and because of that, if we want to store more values in this array, we need to expand it. We need to get a bigger space that can hold more values than what we currently have.

    +

    A dynamic array works by expanding the underlying array, whenever the length becomes equal to the capacity of the array. It basically allocates a new contiguous block of memory that is bigger than the previous one, then, it copies all values that are currently being stored to this new location (i.e., this new block of memory), then, it frees the previous block of memory. At the end of this process, the new underlying array have a bigger capacity, and, therefore, the length becomes, once again, smaller than the capacity of the array.

    +

    This is the cycle of a dynamic array. Notice that, throughout this cycle, the capacity is always either equal to or higher than the length of the array. If you have an ArrayList object (let’s suppose you named it buffer), you can check the current capacity of your array by accessing the capacity attribute of your ArrayList object, while the current length of it is available at the items.len attribute.

    // Check capacity
     buffer.capacity;
    @@ -408,7 +408,7 @@ 

    11.1.2 Creating an ArrayList object

    -

    In order to use ArrayList, you must provide an allocator object to it. Remember, Zig does not have a default memory allocator. And as I described at Section 3.3, all memory allocations must be done by an allocator object that you define, that you have control over. In our example here, I’m going to use a general purpose allocator, but you can use any other allocator of your preference.

    +

    In order to use ArrayList, you must provide an allocator object to it. Remember, Zig does not have a default memory allocator. And as I described in Section 3.3, all memory allocations must be done by an allocator object that you define, that you have control over. In our example here, I’m going to use a general purpose allocator, but you can use any other allocator of your preference.

    When you initialize an ArrayList object, you must provide the data type of the elements of the array. In other words, this defines the type of data that this array (or container) will store. Therefore, if I provide the u8 type to it, then, I will create a dynamic array of u8 values. However, if I provide a struct that I have defined instead, like the struct User from Section 2.3, then, a dynamic array of User values will be created. In the example below, with the expression ArrayList(u8) we are creating a dynamic array of u8 values.

    After you provide the data type of the elements of the array, you can initialize an ArrayList object by either using the init() or the initCapacity() methods. The former method receives only the allocator object as input, while the latter method receives both the allocator object and a capacity number as inputs. With the latter method, you not only initialize the struct, but you also set the starting capacity of the allocated array.

    Using the initCapacity() method is the preferred way to initialize your dynamic array. Because reallocations, or, in other words, the process of expanding the capacity of the array, is always a high cost operation. You should take any possible opportunity to avoid reallocations in your array. If you know how much space your array needs to occupy at the beginning, you should always use initCapacity() to create your dynamic array.

    @@ -424,7 +424,7 @@

    11.1.3 Adding new elements to the array

    Now that we have created our dynamic array, we can start to use it. You can append (a.k.a “add”) new values to this array by using the append() method. This method works the same way as the append() method from a Python list, or, the emplace_back() method from std::vector of C++. You provide a single value to this method, and the method appends this value to the array.

    -

    You can also use the appendSlice() method to append multiple values at once. You provide a slice (slices were described at Section 1.6) to this method, and the method adds all values present in this slice to your dynamic array.

    +

    You can also use the appendSlice() method to append multiple values at once. You provide a slice (slices were described in Section 1.6) to this method, and the method adds all values present in this slice to your dynamic array.

    try buffer.append('H');
     try buffer.append('e');
    @@ -436,8 +436,8 @@ 

    11.1.4 Removing elements from the array

    -

    You can use the pop() method to “pop” or remove the last element in the array. Is worth noting that this method do not change the capacity of the array. It just deletes or erases the last value stored in the array.

    -

    Also, this method returns as result the value that got deleted. That is, you can use this method to both get the last value in the array, and also, remove it from the array. It is a “get and remove value” type of method.

    +

    You can use the pop() method to “pop” or remove the last element in the array. It’s worth noting that this method do not change the capacity of the array. It just deletes or erases the last value stored in the array.

    +

    Also, this method returns as result the value that got deleted. That is, you can use this method to both get the last value in the array, and also, remove it from the array. It’s a “get and remove value” type of method.

    const exclamation_mark = buffer.pop();
    @@ -504,7 +504,7 @@

    11.2.1 What is a hashtable?

    A hashtable is a data structure based on key-value pairs. You provide a key and a value to this structure, then, the hashtable will store the input value at a location that can be identified by the input key that you provided. It does that by using an underlying array and a hash function. These two components are essential to how a hashtable works.

    Under the hood, the hashtable contains an array. This array is where the values are stored, and the elements of this array are usually called of buckets. So the values that you provide to the hashtable are stored inside buckets, and you access each bucket by using an index.

    -

    When you provide a key to a hashtable, it passes this key to the hash function. This hash function uses some sort of hashing algorithm to transform this key into an index. This index is actually an array index. It is a position in the underlying array of the hashtable. This is how a key identifies a specific position (or location) inside the hashtable structure.

    +

    When you provide a key to a hashtable, it passes this key to the hash function. This hash function uses some sort of hashing algorithm to transform this key into an index. This index is actually an array index. It’s a position in the underlying array of the hashtable. This is how a key identifies a specific position (or location) inside the hashtable structure.

    Therefore, you provide a key to the hashtable, and this key identifies a specific location inside the hashtable, then, the hashtable takes the input value that you provided, and stores this value in the location identified by this input key. You could say that the key maps to the value stored in the hashtable. You find the value, by using the key that identifies the location where the value is stored. The Figure 11.2 presents this process visually.

    @@ -516,16 +516,16 @@

    <

    -

    The operation described in the previous paragraph is normally called an insertion operation. Because you are inserting new values into the hashtable. But there are other types of operations in hashtables such as delete and lookup. Delete is self describing, it is when you delete (or remove) a value from the hashtable. While lookup corresponds to when you look at a value that is stored in the hashtable, by using the key that identifies the location where this value is stored.

    -

    Sometimes, instead of storing the values directly, the underlying array of the hashtable might be an array of pointers, i.e. the buckets of the array stores pointers that points to the value, or also, may be an array of linked lists. These cases are common on hashtables that allows duplicate keys, or, in other words, on hashtables that effectively handle “collisions” that may arise from the hash function.

    -

    Duplicate keys, or this “collision” thing that I’m talking about, is when you have two different keys that points to the same location (i.e. to the same index) in the underlying array of the hashtable. This might happen depending on the characteristics of the hash function that is being used in the hashtable. Some implementations of the hashtable will actively deal with collisions, meaning that, they will handle this case in some way. For example, the hashtable might transform all buckets into linked lists. Because with a linked list you can store multiple values into a single bucket.

    -

    There are different techniques to handle collisions in hashtables, which I will not describe in this book, because it is not our main scope here. But you can find a good description of some of the most common techniques at the Wikipedia page of hashtables (Wikipedia 2024).

    +

    The operation described in the previous paragraph is normally called an insertion operation. Because you are inserting new values into the hashtable. But there are other types of operations in hashtables such as delete and lookup. Delete is self describing, it’s when you delete (or remove) a value from the hashtable. While lookup corresponds to when you look at a value that is stored in the hashtable, by using the key that identifies the location where this value is stored.

    +

    Sometimes, instead of storing the values directly, the underlying array of the hashtable might be an array of pointers, i.e., the buckets of the array stores pointers that points to the value, or also, may be an array of linked lists. These cases are common on hashtables that allows duplicate keys, or, in other words, on hashtables that effectively handle “collisions” that may arise from the hash function.

    +

    Duplicate keys, or this “collision” thing that I’m talking about, is when you have two different keys that points to the same location (i.e., to the same index) in the underlying array of the hashtable. This might happen depending on the characteristics of the hash function that is being used in the hashtable. Some implementations of the hashtable will actively deal with collisions, meaning that, they will handle this case in some way. For example, the hashtable might transform all buckets into linked lists. Because with a linked list you can store multiple values into a single bucket.

    +

    There are different techniques to handle collisions in hashtables, which I will not describe in this book, because it’s not our main scope here. But you can find a good description of some of the most common techniques at the Wikipedia page of hashtables (Wikipedia 2024).

    11.2.2 Hashtables in Zig

    The Zig Standard Library provides different implementations of a hashtable. Each implementation have its own cons and pros, which we will discuss later on, and all of them are available through the std.hash_map module.

    The HashMap struct is a general-purpose hashtable, which have very fast operations (lookup, insertion, delete), and also, quite high load factors for low memory usage. You can create and provide a context object to the HashMap constructor. This context object allows you to tailor the behaviour of the hashtable itself, because you can provide a hash function implementation to be used by the hashtable through this context object.

    -

    But let’s not worry about this context object now, because it is meant to be used by “experts in the field of hashtables”. Since we are most likely not experts in this field, we are going to take the easy way to create a hashtable. Which is by using the AutoHashMap() function.

    +

    But let’s not worry about this context object now, because it’s meant to be used by “experts in the field of hashtables”. Since we are most likely not experts in this field, we are going to take the easy way to create a hashtable. Which is by using the AutoHashMap() function.

    This AutoHashMap() function is essentially a “create a hashtable object that uses the default settings” type of function. It automatically chooses a context object, and, therefore, a hash function implementation, for you. This function receives two data types as input, the first input is the data type of the keys that will be used in this hashtable, while the second input is the data type of the data that will be stored inside the hashtable, that is, the data type of the values to be stored.

    In the example below, we are providing the data type u32 in the first argument, and u16 in the second argument of this function. This means that we are going to use u32 values as keys in this hashtable, while u16 values are the actual values that are going to be stored into this hashtable. At the end of this process, the hash_table object contains a HashMap object that uses the default settings and context.

    @@ -569,12 +569,12 @@

    You can add/put new values into the hashtable by using the put() method. The first argument is the key to be used, and the second argument is the actual value that you want to store inside the hashtable. In the example below, we first add the value 89 using the key 54321, next, we add the value 55 using the key 50050, etc.

    Notice that we have used the method count() to see how many values are currently stored in the hashtable. After that, we also use the get() method to access (or look) at the value stored in the position identified by the key 500050. The output of this get() method is an optional value. This is why we use the ? method at the end to get the actual value.

    Also notice that we can remove (or delete) values from the hashtable by using the remove() method. You provide the key that identifies the value that you want to delete, then, the method will delete this value and return a true value as output. This true value essentially tells us that the method successfully deleted the value.

    -

    But this delete operation might not be always successful. For example, you might provide the wrong key to this method. I mean, maybe you provide (either intentionally or unintentionally) a key that points to an empty bucket, i.e. a bucket that still doesn’t have a value in it. In this case, the remove() method would return a false value.

    +

    But this delete operation might not be always successful. For example, you might provide the wrong key to this method. I mean, maybe you provide (either intentionally or unintentionally) a key that points to an empty bucket, i.e., a bucket that still doesn’t have a value in it. In this case, the remove() method would return a false value.

    11.2.3 Iterating through the hashtable

    Iterating through the keys and values that are currently being stored in the hashtable is a very common necessity. You can do that in Zig by using an iterator object that can iterate through the elements of your hashtable object.

    -

    This iterator object works like any other iterator object that you would find in languages such as C++ and Rust. It is basically a pointer object that points to some value in the container, and has a next() method that you can use to navigate (or iterate) through the values in the container.

    +

    This iterator object works like any other iterator object that you would find in languages such as C++ and Rust. It’s basically a pointer object that points to some value in the container, and has a next() method that you can use to navigate (or iterate) through the values in the container.

    You can create such iterator object by using the iterator() method of the hashtable object. This method returns an iterator object, from which you can use the next() method in conjunction with a while loop to iterate through the elements of your hashtable. The next() method returns an optional Entry value, and therefore, you must unwrap this optional value to get the actual Entry value from which you can access the key and also the value identified by this key.

    With this Entry value at hand, you can access the key of this current entry by using the key_ptr attribute and dereferencing the pointer that lives inside of it, while the value identified by this key is accessed through the value_ptr attribute instead, which is also a pointer to be dereferenced. The code example below demonstrates the use of these elements:

    @@ -620,15 +620,15 @@

    If you need to iterate through the elements of your hashtable constantly, you might want to use the ArrayHashMap struct for your specific case, instead of going with the usual and general-purpose HashMap struct.

    The ArrayHashMap struct creates a hashtable that is faster to iterate over. That is why this specific type of hashtable might be valuable to you. Some other properties of a ArrayHashMap hashtable are:

      -
    • the order of insertion is preserved, i.e. the order of the values that you find while iterating through this hashtable is actually the order in which these values were inserted in the hashtable.
    • +
    • the order of insertion is preserved, i.e., the order of the values that you find while iterating through this hashtable is actually the order in which these values were inserted in the hashtable.
    • the key-value pairs are stored sequentially, one after another.
    -

    You can create an ArrayHashMap object by using, once again, a helper function that chooses automatically for you a hash function implementation. This is the AutoArrayHashMap() function, which works very similarly to the AutoHashMap() function that we presented at Section 11.2.2.

    +

    You can create an ArrayHashMap object by using, once again, a helper function that chooses automatically for you a hash function implementation. This is the AutoArrayHashMap() function, which works very similarly to the AutoHashMap() function that we presented in Section 11.2.2.

    You provide two data types to this function. The data type of the keys that will be used in this hashtable, and the data type of the values that will be stored in this hashtable.

    An ArrayHashMap object have essentially the exact same methods from the HashMap struct. So you can insert new values into the hashtable by using the put() method, and you can look (or get) a value from the hashtable by using the get() method. But the remove() method is not available in this specific type of hashtable.

    -

    In order to delete values from the hashtable, you would use the same methods that you find in an ArrayList object, i.e. a dynamic array. I presented these methods at Section 11.1.4, which are the swapRemove() and orderedRemove() methods. These methods have the same meaning here, or, the same effect that they have in an ArrayList object.

    +

    In order to delete values from the hashtable, you would use the same methods that you find in an ArrayList object, i.e., a dynamic array. I presented these methods in Section 11.1.4, which are the swapRemove() and orderedRemove() methods. These methods have the same meaning here, or, the same effect that they have in an ArrayList object.

    This means that, with swapRemove() you remove the value from the hashtable, but you do not preserve the order in which the values were inserted into the structure. While orderedRemove() is able to retain the order in which these values were inserted.

    -

    But instead of providing an index as input to swapRemove() or orderedRemove(), like I described at Section 11.1.4, these methods here in an ArrayHashMap take a key as input, like the remove() method from a HashMap object. If you want to provide an index as input, instead of a key, you should use the swapRemoveAt() and orderedRemoveAt() methods.

    +

    But instead of providing an index as input to swapRemove() or orderedRemove(), like I described in Section 11.1.4, these methods here in an ArrayHashMap take a key as input, like the remove() method from a HashMap object. If you want to provide an index as input, instead of a key, you should use the swapRemoveAt() and orderedRemoveAt() methods.

    var hash_table = AutoArrayHashMap(u32, u16)
         .init(allocator);
    @@ -638,7 +638,7 @@ 

    11.2.5 The StringHashMap hashtable

    One thing that you will notice in the other two types of hashtables that I have presented over the last sections, is that neither of them accepts a slice data type in their keys. What this means is that you cannot use a slice value to represent a key in these types of hashtable.

    -

    The most obvious consequence of this, is that you cannot use strings as keys in these hashtables. But it is extremely common to use strings as keys in hashtables.

    +

    The most obvious consequence of this, is that you cannot use strings as keys in these hashtables. But it’s extremely common to use strings as keys in hashtables.

    Take this very simple Javascript code snippet as an example. We are creating a simple hashtable object named people. Then, we add a new entry to this hashtable, which is identified by the string 'Pedro'. This string is the key in this case, while the object containing different personal information such as age, height and city, is the value to be stored in the hashtable.

    var people = new Object();
     people['Pedro'] = {
    @@ -675,9 +675,9 @@ 

    <

    11.2.6 The StringArrayHashMap hashtable

    The Zig Standard Library also provides a type of hashtable that mix the cons and pros of the StringHashMap and ArrayHashMap together. That is, a hashtable that uses strings as keys, but also have the advantages from ArrayHashMap. In other words, you can have a hashtable that is fast to iterate over, that preserves insertion order, and also, that uses strings as keys.

    -

    You can create such type of hashtable by using the StringArrayHashMap() function. This function accepts a data type as input, which is the data type of the values that are going to be stored inside this hashtable, in the same style as the function presented at Section 11.2.5.

    -

    You can insert new values into this hashtable by using the same put() method that we have discussed at Section 11.2.5. And you can also get values from the hashtable by using the same get() method. Like its ArrayHashMap brother, to delete values from this specific type of hashtable, we also use the orderedRemove() and swapRemove() methods, with the same effects that I have described at Section 11.2.4.

    -

    If we take the code example that was exposed at Section 11.2.5, we can achieve the exact same result with StringArrayHashMap():

    +

    You can create such type of hashtable by using the StringArrayHashMap() function. This function accepts a data type as input, which is the data type of the values that are going to be stored inside this hashtable, in the same style as the function presented in Section 11.2.5.

    +

    You can insert new values into this hashtable by using the same put() method that we have discussed in Section 11.2.5. And you can also get values from the hashtable by using the same get() method. Like its ArrayHashMap brother, to delete values from this specific type of hashtable, we also use the orderedRemove() and swapRemove() methods, with the same effects that I have described in Section 11.2.4.

    +

    If we take the code example that was exposed in Section 11.2.5, we can achieve the exact same result with StringArrayHashMap():

    var ages = std.StringArrayHashMap(u8).init(allocator);
    @@ -687,7 +687,7 @@

    11.3 Linked lists

    The Zig Standard Library provides an implementation for both singly and doubly linked lists. A linked list is a linear data structure that looks like a chain, or, a rope. The main advantage of this data structure is that you normally have very fast insertion and deletion operations. But, as a disadvantage, iterating through this data structure is usually not so fast as iterating through an array.

    The idea behind a linked list is to build a structure that consists of a sequence of nodes connected to each other by pointers. This means that linked lists are usually not contiguous in memory, because each node might be anywhere in memory. They do not need to be close to one another.

    -

    At Figure 11.3 we can see a diagram of a singly linked list. We begin at the first node (which is usually called “the head of the linked list”). Then, from this first node we uncover the remaining nodes in the structure, by following the locations pointed by the pointers found in each node.

    +

    In Figure 11.3 we can see a diagram of a singly linked list. We begin at the first node (which is usually called “the head of the linked list”). Then, from this first node we uncover the remaining nodes in the structure, by following the locations pointed by the pointers found in each node.

    Each node has two things in it. It has the value that is stored in the current node , and also, a pointer. This pointer points to the next node in the list. If this pointer is null, then, it means that we have reached the end of our linked list.

    @@ -699,7 +699,7 @@

    -

    At Figure 11.4 we can see a diagram of a doubly linked list. The only thing that really changes now is that every node in the linked list has both a pointer to the previous node, and, a pointer to the next node. So every node in a doubly linked list has two pointers in it. These are usually called the prev (for “previous”) and the next (for “next”) pointers of the node.

    +

    In Figure 11.4 we can see a diagram of a doubly linked list. The only thing that really changes now is that every node in the linked list has both a pointer to the previous node, and, a pointer to the next node. So every node in a doubly linked list has two pointers in it. These are usually called the prev (for “previous”) and the next (for “next”) pointers of the node.

    In the singly linked list example, we had only one single pointer in each node, and this singular pointer was always pointing to the next node in the sequence. This means that singly linked lists normally have only the next pointer in them.

    @@ -711,14 +711,14 @@

    -

    Linked lists are available in Zig through the functions SinglyLinkedList() and DoublyLinkedList(), for “singly linked lists” and “doubly linked lists”, respectively. These functions are actually generic functions, which we are going to talk more about at Section 12.2.1.

    +

    Linked lists are available in Zig through the functions SinglyLinkedList() and DoublyLinkedList(), for “singly linked lists” and “doubly linked lists”, respectively. These functions are actually generic functions, which we are going to talk more about in Section 12.2.1.

    For now, just understand that, in order to create a linked list object, we begin by providing a data type to these functions. This data type defines the type of data that each node in this linked list will store. In the example below, we are creating a singly linked list of u32 values. So each node in this linked list will store a u32 value.

    -

    Both the SinglyLinkedList() and DoublyLinkedList() functions returns a type, i.e. a struct definition, as output. Therefore, the object Lu32 is actually a struct definition. It defines the type “singly linked list of u32 values”.

    +

    Both the SinglyLinkedList() and DoublyLinkedList() functions returns a type, i.e., a struct definition, as output. Therefore, the object Lu32 is actually a struct definition. It defines the type “singly linked list of u32 values”.

    Now that we have the definition of the struct, we need to instantiate a Lu32 object. We normally instantiate struct objects in Zig by using an init() method. But in this case, we are instantiating the struct directly, by using an empty struct literal, in the expression Lu32{}.

    In this example, we first create multiple node objects, and after we create them, we start to insert and connect these nodes to build the linked list, using the prepend() and insertAfter() methods. Notice that the prepend() method is a method from the linked list object, while the insertAfter() is a method present in the node objects.

    In essence, the prepend() method inserts a node at the beginning of the linked list. In other words, the node that you provide to this method, becomes the new “head node” of the linked list. It becomes the first node in the list (see Figure 11.3).

    On the other side, the insertAfter() method is used to basically connect two nodes together. When you provide a node to this method, it creates a pointer to this input node, and stores this pointer in the next attribute of the current node, from which the method was called from.

    -

    Because doubly linked lists have both a next and a prev attributes in each node (as described at Figure 11.4), a node object created from a DoublyLinkedList object have both an insertBefore() (for prev) and an insertAfter() (for next) methods available.

    +

    Because doubly linked lists have both a next and a prev attributes in each node (as described in Figure 11.4), a node object created from a DoublyLinkedList object have both an insertBefore() (for prev) and an insertAfter() (for next) methods available.

    Thus, if we have used a doubly linked list, we can use the insertBefore() method to store the pointer to the input node in the prev attribute. This would put the input node as the “previous node”, or, the node before the current node. In contrast, the insertAfter() method puts the pointer created to the input node in the next attribute of the current node, and as result, the input node becomes the “next node” of the current node.

    Since we are using a singly linked list in this example, we have only the insertAfter() method available in the node objects that we create from our Lu32 type.

    @@ -746,14 +746,14 @@

    remove() to remove a specific node from the linked list.
  • if singly linked list, len() to count how many nodes there is in the linked list.
  • if doubly linked list, checkout the len attribute to see how many nodes there is in the linked list.
  • -
  • if singly linked list, popFirst() to remove the first node (i.e. the “head”) from the linked list.
  • +
  • if singly linked list, popFirst() to remove the first node (i.e., the “head”) from the linked list.
  • if doubly linked list, pop() and popFirst() to remove the last and first nodes from the linked list, respectively.
  • -
  • if doubly linked list, append() to add a new node to end of the linked list (i.e. inverse of prepend()).
  • +
  • if doubly linked list, append() to add a new node to end of the linked list (i.e., inverse of prepend()).
  • 11.4 Multi array structure

    -

    Zig introduces a new data structure called MultiArrayList(). It is a different version of the dynamic array that we have introduced at Section 11.1. The difference between this structure and the ArrayList() that we know from Section 11.1, is that MultiArrayList() creates a separate dynamic array for each field of the struct that you provide as input.

    +

    Zig introduces a new data structure called MultiArrayList(). It’s a different version of the dynamic array that we have introduced in Section 11.1. The difference between this structure and the ArrayList() that we know from Section 11.1, is that MultiArrayList() creates a separate dynamic array for each field of the struct that you provide as input.

    Consider the following code example. We create a new custom struct called Person. This struct contains three different data members, or, three different fields. As consequence, when we provide this Person data type as input to MultiArrayList(), this creates a “struct of three different arrays” called PersonArray. In other words, this PersonArray is a struct that contains three internal dynamic arrays in it. One array for each field found in the Person struct definition.

    const std = @import("std");
    @@ -803,8 +803,8 @@ 

    < Age: 26 Age: 64

    In the above example, we are iterating over the values of the .age array, or, the internal array of the PersonArray object that contains the values of the age data member from the Person values that were added to the multi array struct.

    -

    In this example we are calling the items() method directly from the PersonArray object. However, it is recommended on most situations to call this items() method from a “slice object”, which you can create from the slice() method. The reason for this is that calling items() multiple times have better performance if you use a slice object.

    -

    Therefore, if you are planning to access only one of the internal arrays from your “multi array struct”, it is fine to call items() directly from the multi array object. But if you need to access many of the internal arrays from your “multi array struct”, then, you will likely need to call items() more than once, and, in such circumstance, is better to call items() through a slice object. The example below demonstrates the use of such object:

    +

    In this example we are calling the items() method directly from the PersonArray object. However, in most situations it’s recommened to call this items() method from a “slice object”, which you can create from the slice() method. The reason for this is that calling items() multiple times have better performance if you use a slice object.

    +

    Therefore, if you are planning to access only one of the internal arrays from your “multi array struct”, it’s fine to call items() directly from the multi array object. But if you need to access many of the internal arrays from your “multi array struct”, then, you will likely need to call items() more than once, and, in such circumstance, is better to call items() through a slice object. The example below demonstrates the use of such object:

    var slice = people.slice();
     for (slice.items(.age)) |*age| {
    diff --git a/docs/Chapters/09-error-handling.html b/docs/Chapters/09-error-handling.html
    index e026d192..e621d0b4 100644
    --- a/docs/Chapters/09-error-handling.html
    +++ b/docs/Chapters/09-error-handling.html
    @@ -366,7 +366,7 @@ 

    Section 1.2.3. But we still haven’t learned about the other methods, such as the catch keyword. I also want to discuss in this chapter how union types are created in Zig.

    +

    In this chapter, I want to discuss how error handling is done in Zig. We already briefly learned about one of the available strategies to handle errors in Zig, which is the try keyword presented in Section 1.2.3. But we still haven’t learned about the other methods, such as the catch keyword. I also want to discuss in this chapter how union types are created in Zig.

    10.1 Learning more about errors in Zig

    Before we get into how error handling is done, we need to learn more about what errors are in Zig. An error is actually a value in Zig (Zig Software Foundation 2024a). In other words, when an error occurs inside your Zig program, it means that somewhere in your Zig codebase, an error value is being generated. An error value is similar to any integer value that you create in your Zig code. You can take an error value and pass it as input to a function, and you can also cast (or coerce) it into a different type of an error value.

    @@ -382,7 +382,7 @@

    10.1.1 Returning errors from functions

    -

    As we described at Section 1.2.3, when we have a function that might return an error value, this function normally includes an exclamation mark (!) in its return type annotation. The presence of this exclamation mark indicates that this function might return an error value as result, and, the zig compiler forces you to always handle explicitly the case of this function returning an error value.

    +

    As we described in Section 1.2.3, when we have a function that might return an error value, this function normally includes an exclamation mark (!) in its return type annotation. The presence of this exclamation mark indicates that this function might return an error value as result, and, the zig compiler forces you to always handle explicitly the case of this function returning an error value.

    Take a look at the print_name() function below. This function might return an error in the stdout.print() function call, and, as a consequence, its return type (!void) includes an exclamation mark in it.

    fn print_name() !void {
    @@ -390,22 +390,22 @@ 

    try stdout.print("My name is Pedro!", .{}); }

    -

    In the example above, we are using the exclamation mark to tell the zig compiler that this function might return some error. But which error exactly is returned from this function? For now, we are not specifying a specific error value. We only known for now that some error value (whatever it is) might be returned.

    +

    In the example above, we are using the exclamation mark to tell the zig compiler that this function might return some error. But which error exactly is returned from this function? For now, we are not specifying a specific error value. For now, we only know that some error value (whatever it is) might be returned.

    But in fact, you can (if you want to) specify clearly which exact error values might be returned from this function. There are lot of examples of this in the Zig Standard Library. Take this fill() function from the http.Client module as an example. This function returns either a error value of type ReadError, or void.

    pub fn fill(conn: *Connection) ReadError!void {
         // The body of this function ...
     }
    -

    This idea of specifying the exact error values that you expect to be returned from the function is interesting. Because they automatically become some sort of documentation of your function, and also, it allows the zig compiler to perform some extra checks over your code. Because it can check if there is any other type of error value that is being generated inside your function, and, that it is not being accounted for in this return type annotation.

    +

    This idea of specifying the exact error values that you expect to be returned from the function is interesting. Because they automatically become some sort of documentation of your function, and also, this allows the zig compiler to perform some extra checks over your code. Because the compiler can check if there is any other type of error value that is being generated inside your function, and, that it’s not being accounted for in this return type annotation.

    Anyway, you can list the types of errors that can be returned from the function by listing them on the left side of the exclamation mark. While the valid values stay on the right side of the exclamation mark. So the syntax format become:

    <error-value>!<valid-value>

    10.1.2 Error sets

    But what about when we have a single function that might return different types of errors? When you have such a function, you can list all of these different types of errors that can be returned from this function, through a structure in Zig that we call of an error set.

    -

    An error set is a special case of an union type. It is an union that contains error values in it. Not all programming languages have a notion of an “union object”. But in summary, an union is just a set of data types. Unions are used to allow an object to have multiple data types. For example, a union of x, y and z, means that an object can be either of type x, or type y or type z.

    -

    We are going to talk in more depth about unions at Section 10.3. But you can write an error set by writing the keyword error before a pair of curly braces, then you list the error values that can be returned from the function inside this pair of curly braces.

    +

    An error set is a special case of a union type. It’s a union that contains error values in it. Not all programming languages have a notion of a “union object”. But in summary, a union is just a set of data types. Unions are used to allow an object to have multiple data types. For example, a union of x, y and z, means that an object can be either of type x, or type y or type z.

    +

    We are going to talk in more depth about unions in Section 10.3. But you can write an error set by writing the keyword error before a pair of curly braces, then you list the error values that can be returned from the function inside this pair of curly braces.

    Take the resolvePath() function below as an example, which comes from the introspect.zig module of the Zig Standard Library. We can see in its return type annotation, that this function return either: 1) a valid slice of u8 values ([]u8); or, 2) one of the three different types of error values listed inside the error set (OutOfMemory, Unexpected, etc.). This is an usage example of an error set.

    pub fn resolvePath(
    @@ -420,7 +420,7 @@ 

    }

    This is a valid way of annotating the return value of a Zig function. But, if you navigate through the modules that composes the Zig Standard Library, you will notice that, for the majority of cases, the programmers prefer to give a descriptive name to this error set, and then, use this name (or this “label”) of the error set in the return type annotation, instead of using the error set directly.

    -

    We can see that in the ReadError error set that we showed earlier in the fill() function, which is defined in the http.Client module. So yes, I presented the ReadError as if it was just a standard and single error value, but in fact, it is an error set defined in the http.Client module, and therefore, it actually represents a set of different error values that might happen inside the fill() function.

    +

    We can see that in the ReadError error set that we showed earlier in the fill() function, which is defined in the http.Client module. So yes, I presented the ReadError as if it was just a standard and single error value, but in fact, it’s an error set defined in the http.Client module, and therefore, it actually represents a set of different error values that might happen inside the fill() function.

    Take a look at the ReadError definition reproduced below. Notice that we are grouping all of these different error values into a single object, and then, we use this object into the return type annotation of the function. Like the fill() function that we showed earlier, or, the readvDirect() function from the same module, which is reproduced below.

    pub const ReadError = error{
    @@ -469,7 +469,7 @@ 

    ); }

    -
    1/1 filea64e1da1167c.test.coerce error value...OKA
    +
    1/1 file826379a872a1.test.coerce error value...OKA
       All 1 tests passed.
    @@ -487,7 +487,7 @@

    10.2.1 What try means?

    As I described over the previous sections, when we say that an expression might return an error, we are basically referring to an expression that have a return type in the format !T. The ! indicates that this expression returns either an error value, or a value of type T.

    -

    At Section 1.2.3, I presented the try keyword and where to use it. But I did not talked about what exactly this keyword does to your code, or, in other words, I have not explained yet what try means in your code.

    +

    In Section 1.2.3, I presented the try keyword and where to use it. But I did not talked about what exactly this keyword does to your code, or, in other words, I have not explained yet what try means in your code.

    In essence, when you use the try keyword in an expression, you are telling the zig compiler the following: “Hey! Execute this expression for me, and, if this expression return an error, please, return this error for me and stop the execution of my program. But if this expression return a valid value, then, return this value, and move on”.

    In other words, the try keyword is essentially, a strategy to enter in panic mode, and stop the execution of your program in case an error occurs. With the try keyword, you are telling the zig compiler, that stopping the execution of your program is the most reasonable strategy to take if an error occurs in that particular expression.

    @@ -511,7 +511,7 @@

    Therefore, we use catch to create a block of expressions that will handle the error. I can return the error value from this block of expressions, like I did in the above example, which, will make the program enter in panic mode, and, stop the execution. But I could also, return a valid value from this block of code, which would be stored in the file object.

    Notice that, instead of writing the keyword before the expression that might return the error, like we do with try, we write catch after the expression. We can open the pair of pipes (|), which captures the error value returned by the expression, and makes this error value available in the scope of the catch block as the object named err. In other words, because I wrote |err| in the code, I can access the error value returned by the expression, by using the err object.

    Although this being the most common use of catch, you can also use this keyword to handle the error in a “default value” style. That is, if the expression returns an error, we use the default value instead. Otherwise, we use the valid value returned by the expression.

    -

    The Zig official language reference, provides a great example of this “default value” strategy with catch. This example is reproduced below. Notice that we are trying to parse some unsigned integer from a string object named str. In other words, this function is trying to transform an object of type []const u8 (i.e. an array of characters, a string, etc.) into an object of type u64.

    +

    The Zig official language reference, provides a great example of this “default value” strategy with catch. This example is reproduced below. Notice that we are trying to parse some unsigned integer from a string object named str. In other words, this function is trying to transform an object of type []const u8 (i.e., an array of characters, a string, etc.) into an object of type u64.

    But this parsing process done by the function parseU64() may fail, resulting in a runtime error. The catch keyword used in this example provides an alternative value (13) to be used in case this parseU64() function raises an error. So, the expression below essentially means: “Hey! Please, parse this string into a u64 for me, and store the results into the object number. But, if an error occurs, then, use the value 13 instead”.

    const number = parseU64(str, 10) catch 13;
    @@ -522,7 +522,7 @@

    10.2.3 Using if statements

    Now, you can also use if statements to handle errors in your Zig code. In the example below, I’m reproducing the previous example, where we try to parse an integer value from an input string with a function named parseU64().

    We execute the expression inside the “if”. If this expression returns an error value, the “if branch” (or, the “true branch”) of the if statement is not executed. But if this expression returns a valid value instead, then, this value is unwrapped into the number object.

    -

    This means that, if the parseU64() expression returns a valid value, this value becomes available inside the scope of this “if branch” (i.e. the “true branch”) through the object that we listed inside the pair of pipe character (|), which is the object number.

    +

    This means that, if the parseU64() expression returns a valid value, this value becomes available inside the scope of this “if branch” (i.e., the “true branch”) through the object that we listed inside the pair of pipe character (|), which is the object number.

    If an error occurs, we can use an “else branch” (or the “false branch”) of the if statement to handle the error. In the example below, we are using the else in the if statement to unwrap the error value (that was returned by parseU64()) into the err object, and handle the error.

    if (parseU64(str, 10)) |number| {
    @@ -554,9 +554,9 @@ 

    <

    10.2.4 The errdefer keyword

    A common pattern in C programs in general, is to clean resources when an error occurs during the execution of the program. In other words, one common way to handle errors, is to perform “cleanup actions” before we exit our program. This guarantees that a runtime error does not make our program to leak resources of the system.

    -

    The errdefer keyword is a tool to perform such “cleanup actions” in hostile situations. This keyword is commonly used to clean (or to free) allocated resources, before the execution of our program get’s stopped because of an error value being generated.

    -

    The basic idea is to provide an expression to the errdefer keyword. Then, errdefer executes this expression if, and only if, an error occurs during the execution of the current scope. In the example below, we are using an allocator object (that we have presented at Section 3.3) to create a new User object. If we are successful in creating and registering this new user, this create_user() function will return this new User object as its return value.

    -

    However, if for some reason, an error value is generated by some expression that is after the errdefer line, for example, in the db.add(user) expression, the expression registered by errdefer get’s executed before the error value is returned from the function, and before the program enters in panic mode and stops the current execution.

    +

    The errdefer keyword is a tool to perform such “cleanup actions” in hostile situations. This keyword is commonly used to clean (or to free) allocated resources, before the execution of our program gets stopped because of an error value being generated.

    +

    The basic idea is to provide an expression to the errdefer keyword. Then, errdefer executes this expression if, and only if, an error occurs during the execution of the current scope. In the example below, we are using an allocator object (that we have presented in Section 3.3) to create a new User object. If we are successful in creating and registering this new user, this create_user() function will return this new User object as its return value.

    +

    However, if for some reason, an error value is generated by some expression that is after the errdefer line, for example, in the db.add(user) expression, the expression registered by errdefer gets executed before the error value is returned from the function, and before the program enters in panic mode and stops the current execution.

    fn create_user(db: Database, allocator: Allocator) !User {
         const user = try allocator.create(User);
    @@ -567,19 +567,19 @@ 

    return user; }

    -

    By using errdefer to destroy the user object that we have just created, we guarantee that the memory allocated for this user object get’s freed, before the execution of the program stops. Because if the expression try db.add(user) returns an error value, the execution of our program stops, and we lose all references and control over the memory that we have allocated for the user object. As a result, if we do not free the memory associated with the user object before the program stops, we cannot free this memory anymore. We simply lose our chance to do the right thing. That is why errdefer is essential in this situation.

    -

    Just to state clearly the differences between defer and errdefer (which I described at Section 2.1.3 and Section 2.1.4), it might be worth to discuss the subject a bit further. You might still have the question “why use errdefer if we can use defer instead?” in your mind.

    -

    Although being similar, the key difference between errdefer and defer keyword is when the provided expression get’s executed. The defer keyword always execute the provided expression at the end of the current scope, no matter how your code exits this scope. In contrast, errdefer executes the provided expression only when an error occurs in the current scope.

    -

    This becomes important if a resource that you allocate in the current scope get’s freed later in your code, in a different scope. The create_user() functions is an example of this. If you think closely about this function, you will notice that this function returns the user object as the result.

    +

    By using errdefer to destroy the user object that we have just created, we guarantee that the memory allocated for this user object gets freed, before the execution of the program stops. Because if the expression try db.add(user) returns an error value, the execution of our program stops, and we lose all references and control over the memory that we have allocated for the user object. As a result, if we do not free the memory associated with the user object before the program stops, we cannot free this memory anymore. We simply lose our chance to do the right thing. That is why errdefer is essential in this situation.

    +

    Just to state clearly the differences between defer and errdefer (which I described in Section 2.1.3 and Section 2.1.4), it might be worth to discuss the subject a bit further. You might still have the question “why use errdefer if we can use defer instead?” in your mind.

    +

    Although being similar, the key difference between errdefer and defer keyword is when the provided expression gets executed. The defer keyword always execute the provided expression at the end of the current scope, no matter how your code exits this scope. In contrast, errdefer executes the provided expression only when an error occurs in the current scope.

    +

    This becomes important if a resource that you allocate in the current scope gets freed later in your code, in a different scope. The create_user() functions is an example of this. If you think closely about this function, you will notice that this function returns the user object as the result.

    In other words, the allocated memory for the user object does not get freed inside the create_user() function, if it returns successfully. So, if an error does not occur inside this function, the user object is returned from the function, and probably, the code that runs after this create_user() function will be responsible for freeing the memory of the user object.

    But what if an error occurs inside the create_user() function? What happens then? This would mean that the execution of your code would stop in this create_user() function, and, as a consequence, the code that runs after this create_user() function would simply not run, and, as a result, the memory of the user object would not be freed before your program stops.

    This is the perfect scenario for errdefer. We use this keyword to guarantee that our program will free the allocated memory for the user object, even if an error occurs inside the create_user() function.

    -

    If you allocate and free some memory for an object inside the same scope, then, just use defer and be happy, i.e. errdefer have no use for you in such situation. But if you allocate some memory in a scope A, but you only free this memory later, in a scope B for example, then, errdefer becomes useful to avoid leaking memory in sketchy situations.

    +

    If you allocate and free some memory for an object inside the same scope, then, just use defer and be happy, i.e., errdefer have no use for you in such situation. But if you allocate some memory in a scope A, but you only free this memory later, in a scope B for example, then, errdefer becomes useful to avoid leaking memory in sketchy situations.

    10.3 Union type in Zig

    -

    An union type defines a set of types that an object can be. It is like a list of options. Each option is a type that an object can assume. Therefore, unions in Zig have the same meaning, or, the same role as unions in C. They are used for the same purpose. You could also say that unions in Zig produces a similar effect to using typing.Union in Python1.

    +

    A union type defines a set of types that an object can be. It’s like a list of options. Each option is a type that an object can assume. Therefore, unions in Zig have the same meaning, or, the same role as unions in C. They are used for the same purpose. You could also say that unions in Zig produces a similar effect to using typing.Union in Python1.

    For example, you might be creating an API that sends data to a data lake, hosted in some private cloud infrastructure. Suppose you have created different structs in your codebase, to store the necessary information that you need, in order to connect to the services of each mainstream data lake service (Amazon S3, Azure Blob, etc.).

    Now, suppose you also have a function named send_event() that receives an event as input, and, a target data lake, and it sends the input event to the data lake specified in the target data lake argument. But this target data lake could be any of the three mainstream data lakes services (Amazon S3, Azure Blob, etc.). Here is where an union can help you.

    The union LakeTarget defined below allows the lake_target argument of send_event() to be either an object of type AzureBlob, or type AmazonS3, or type GoogleGCP. This union allows the send_event() function to receive an object of any of these three types as input in the lake_target argument.

    @@ -599,7 +599,7 @@

    }

    An union definition is composed by a list of data members. Each data member is of a specific data type. In the example above, the LakeTarget union have three data members (azure, amazon, google). When you instantiate an object that uses an union type, you can only use one of its data members in this instantiation.

    -

    You could also interpret this as: only one data member of an union type can be activated at a time, the other data members remain deactivated and unaccessible. For example, if you create a LakeTarget object that uses the azure data member, you can no longer use or access the data members google or amazon. It is like if these other data members didn’t exist at all in the LakeTarget type.

    +

    You could also interpret this as: only one data member of an union type can be activated at a time, the other data members remain deactivated and unaccessible. For example, if you create a LakeTarget object that uses the azure data member, you can no longer use or access the data members google or amazon. It’s like if these other data members didn’t exist at all in the LakeTarget type.

    You can see this logic in the example below. Notice that, we first instantiate the union object using the azure data member. As a result, this target object contains only the azure data member inside of it. Only this data member is active in this object. That is why the last line in this code example is invalid. Because we are trying to instantiate the data member google, which is currently inactive for this target object, and as a result, the program enters in panic mode warning us about this mistake through a loud error message.

    var target = LakeTarget {
    @@ -624,7 +624,7 @@ 

    .google = GoogleGCP.init() };

    -

    A curious fact about union types, is that, at first, you cannot use them in switch statements (which were presented at Section 2.1.2). In other words, if you have an object of type LakeTarget for example, you cannot give this object as input to a switch statement.

    +

    A curious fact about union types, is that, at first, you cannot use them in switch statements (which were presented in Section 2.1.2). In other words, if you have an object of type LakeTarget for example, you cannot give this object as input to a switch statement.

    But what if you really need to do so? What if you actually need to provide an “union object” to a switch statement? The answer to this question relies on another special type in Zig, which are the tagged unions. To create a tagged union, all you have to do is to add an enum type into your union declaration.

    As an example of a tagged union in Zig, take the Registry type exposed below. This type comes from the grammar.zig module2 from the Zig repository. This union type lists different types of registries. But notice this time, the use of (enum) after the union keyword. This is what makes this union type a tagged union. By being a tagged union, an object of this Registry type can be used as input in a switch statement. This is all you have to do. Just add (enum) to your union declaration, and you can use it in switch statements.

    diff --git a/docs/Chapters/10-stack-project.html b/docs/Chapters/10-stack-project.html index bd3e9cbb..5476994b 100644 --- a/docs/Chapters/10-stack-project.html +++ b/docs/Chapters/10-stack-project.html @@ -348,8 +348,8 @@

    12 

    12.1 Understanding comptime in Zig

    -

    One of the key features of Zig is comptime. This keyword introduces a whole new concept and paradigm, that is tightly connected with the compilation process. At Section 3.1.1 we have described the importance and the role that “compile-time versus runtime” plays into Zig. At that section, we learned that the rules applied to a value/object change a lot depending on whether this value is known at compile-time, or just at runtime.

    -

    The comptime keyword is strongly related to these two spaces in time (compile-time and runtime). Let’s quickly recap the differences. Compile-time is the period of time when your Zig source code is being compiled by the zig compiler, while the runtime is the period of time when your Zig program is being executed, i.e. when we execute the binary files that were generated by the zig compiler.

    +

    One of the key features of Zig is comptime. This keyword introduces a whole new concept and paradigm, that is tightly connected with the compilation process. In Section 3.1.1 we have described the importance and the role that “compile-time versus runtime” plays into Zig. In that section, we learned that the rules applied to a value/object change a lot depending on whether this value is known at compile-time, or just at runtime.

    +

    The comptime keyword is strongly related to these two spaces in time (compile-time and runtime). Let’s quickly recap the differences. Compile-time is the period of time when your Zig source code is being compiled by the zig compiler, while the runtime is the period of time when your Zig program is being executed, i.e., when we execute the binary files that were generated by the zig compiler.

    There are three ways in which you can apply the comptime keyword, which are:

    • apply comptime on a function argument.
    • @@ -358,7 +358,7 @@

      12.1.1 Applying over a function argument

      -

      When you apply the comptime keyword on a function argument, you are saying to the zig compiler that the value assigned to that particular function argument must be known at compile-time. We explained in details at Section 3.1.1 what exactly “value known at compile-time” means, so, in case you have doubts about this idea, come back to that section.

      +

      When you apply the comptime keyword on a function argument, you are saying to the zig compiler that the value assigned to that particular function argument must be known at compile-time. We explained in detail in Section 3.1.1 what exactly “value known at compile-time” means. So if you have any doubts about this idea, refer back to that section.

      Now let’s think about the consequences of this idea. First of all, we are imposing a limit, or, a requirement to that particular function argument. If the programmer accidentally tries to give a value to this function argument that is not known at compile time, the zig compiler will notice this problem, and as a consequence, it will raise a compilation error saying that it cannot compile your program. Because you are providing a value that is “runtime known” to a function argument that must be “compile-time known”.

      Take a look at this very simple example below, where we define a twice() function, that simply doubles the input value named num. Notice that we use the comptime keyword before the name of the function argument. This keyword is marking the function argument num as a “comptime argument”.

      That is a function argument whose value must be compile-time known. This is why the expression twice(5678) is valid, and no compilation errors are raised. Because the value 5678 is compile-time known, so this is the expected behaviour for this function.

      @@ -370,7 +370,7 @@

      _ = twice(5678); }

    -
    1/1 filea72d248f97f8.test.test comptime...OKAll 1 
    +
    1/1 file833f3ad20be9.test.test comptime...OKAll 1 
        tests passed.
    @@ -391,26 +391,26 @@

    _ = twice(n); }

    -
    t.zig:12:16: error: runtime-known argument passed to comptime parameter 
    -

    Comptime arguments are frequently used on functions that return some sort of generic structure. In fact, comptime is the essence (or the basis) to make generics in Zig. We are going to talk more about generics at Section 12.2.

    -

    For now, let’s take a look at this code example from Seguin (2024). You can see that this IntArray() function have one argument named length. This argument is marked as comptime, and receives a value of type usize as input. So the value given to this argument must be compile-time known. We can also see that this function returns an array of i64 values as output.

    +
    t.zig:12:16: error: runtime-known argument passed to comptime parameter
    +

    Comptime arguments are frequently used on functions that return some sort of generic structure. In fact, comptime is the essence (or the basis) to make generics in Zig. We are going to talk more about generics in Section 12.2.

    +

    For now, let’s take a look at this code example from Seguin (2024). You can see that this IntArray() function has one argument named length. This argument is marked as comptime, and receives a value of type usize as input. So the value given to this argument must be compile-time known. We can also see that this function returns an array of i64 values as output.

    fn IntArray(comptime length: usize) type {
         return [length]i64;
     }

    Now, the key component of this function is the length argument. This argument is used to determine the size of the array that is produced by the function. Let’s think about the consequences of that. If the size of the array is dependent on the value assigned to the length argument, this means that the data type of the output of the function depends on the value of this length argument.

    -

    Let this statement sink for a bit in your mind. As I described at Section 1.2.2, Zig is a strongly-typed language, especially on function declarations. So every time we write a function in Zig, we have to annotate the data type of the value returned by the function. But how can we do that, if this data type depends on the value given to the argument of the function?

    +

    Let this statement sink for a bit in your mind. As I described in Section 1.2.2, Zig is a strongly-typed language, especially on function declarations. So every time we write a function in Zig, we have to annotate the data type of the value returned by the function. But how can we do that, if this data type depends on the value given to the argument of the function?

    Think about this for a second. If length is equal to 3 for example, then, the return type of the function is [3]i64. But if length is equal to 40, then, the return type becomes [40]i64. At this point the zig compiler would be confused, and raise a compilation error, saying something like this:

    Hey! You have annotated that this function should return a [3]i64 value, but I got a [40]i64 value instead! This doesn’t look right!

    -

    So how can you solve this problem? How do we overcome this barrier? This is when the type keyword comes in. This type keyword is basically saying to the zig compiler that this function will return some data type as output, but it doesn’t know yet what exactly data type that is. We will talk more about this at Section 12.2.

    +

    So how can you solve this problem? How do we overcome this barrier? This is when the type keyword comes in. This type keyword is basically saying to the zig compiler that this function will return some data type as output, but it doesn’t know yet what exactly data type that is. We will talk more about this in Section 12.2.

    12.1.2 Applying over an expression

    When you apply the comptime keyword over an expression, then, it is guaranteed that the zig compiler will execute this expression at compile-time. If for some reason, this expression cannot be executed at compile-time (e.g. for example, maybe this expression depends on a value that is only known at runtime), then, the zig compiler will raise a compilation error.

    -

    Take this example from the official documentation of Zig (Zig Software Foundation 2024). We are executing the same fibonacci() function both at runtime, and, at compile-time. The function is by default executed at runtime, but because we use the comptime keyword at the second “try expression”, this expression is executed at compile-time.

    +

    Take this example from the official documentation of Zig (Zig Software Foundation 2024). We are executing the same fibonacci() function both at runtime, and, at compile-time. The function is executed by default at runtime, but because we use the comptime keyword in the second “try expression”, this expression is executed at compile-time.

    This might be a bit confusing for some people. Yes! When I say that this expression is executed at compile-time, I mean that this expression is compiled and executed while the zig compiler is compiling your Zig source code.

    const expect = @import("std").testing.expect;
    @@ -426,16 +426,16 @@ 

    try comptime expect(fibonacci(7) == 13); }

    -
    1/1 filea72d3cf7abe2.test.fibonacci...OKAll 1 test
    +
    1/1 file833f119d55a3.test.fibonacci...OKAll 1 test
       ts passed.
    -

    A lot of your Zig source code might be potentially executed at compile-time, because the zig compiler can figure it out the output of some expressions. Especially if these expressions depends only at compile-time known values. We have talked about this at Section 3.1.1.

    +

    A lot of your Zig source code might be potentially executed at compile-time, because the zig compiler can figure out the output of some expressions. Especially if these expressions depend only on compile-time known values. We have talked about this in Section 3.1.1.

    But when you use the comptime keyword on an expression, there is no “it might be executed at compile-time” anymore. With the comptime keyword you are ordering the zig compiler to execute this expression at compile-time. You are imposing this rule, it is guaranteed that the compiler will always execute it at compile-time. Or, at least, the compiler will try to execute it. If the compiler cannot execute the expression for whatever reason, the compiler will raise a compilation error.

    12.1.3 Applying over a block

    -

    Blocks were described at Section 1.7. When you apply the comptime keyword over a block of expressions, you get essentially the same effect when you apply this keyword to a single expression. That is, the entire block of expressions is executed at compile-time by the zig compiler.

    +

    Blocks were described in Section 1.7. When you apply the comptime keyword to a block of expressions, you get essentially the same effect as when you apply this keyword to a single expression. That is, the entire block of expressions is executed at compile-time by the zig compiler.

    In the example below, we mark the block labeled of blk as a comptime block, and, therefore, the expressions inside this block are executed at compile-time.

    const expect = @import("std").testing.expect;
    @@ -455,7 +455,7 @@ 

    _ = x; }

    -
    1/1 filea72d6353d586.test.fibonacci in a block...O
    +
    1/1 file833f6ccf145c.test.fibonacci in a block...O
       OKAll 1 tests passed.
    @@ -463,13 +463,13 @@

    12.2 Introducing Generics

    -

    First of all, what is a generic? Generic is the idea to allow a type (f64, u8, u32, bool, and also, user-defined types, like the User struct that we defined at Section 2.3) to be a parameter to methods, classes and interfaces (Geeks for Geeks 2024). In other words, a “generic” is a class (or a method) that can work with multiple data types.

    +

    First of all, what is a generic? Generic is the idea to allow a type (f64, u8, u32, bool, and also, user-defined types, like the User struct that we defined in Section 2.3) to be a parameter to methods, classes and interfaces (Geeks for Geeks 2024). In other words, a “generic” is a class (or a method) that can work with multiple data types.

    For example, in Java, generics are created through the operator <>. With this operator, a Java class is capable of receiving a data type as input, and therefore, the class can fit its features according to this input data type. As another example, generics in C++ are supported through the concept of templates. Class templates in C++ are generics.

    In Zig, generics are implemented through comptime. The comptime keyword allows us to collect a data type at compile time, and pass this data type as input to a piece of code.

    12.2.1 A generic function

    -

    Take the max() function exposed below as a first example. This function is essentially a “generic function”. In this function, we have a comptime function argument named T. Notice that this T argument have a data type of type. Weird right? This type keyword is the “father of all types”, or, “the type of types” in Zig.

    -

    Because we have used this type keyword in the T argument, we are telling the zig compiler that this T argument will receive some data type as input. Also notice the use of the comptime keyword in this argument. As I described at Section 12.1, every time you use this keyword in a function argument, this means that the value of this argument must be known at compile-time. This makes sense, right? Because there is no data type that is not known at compile-time.

    +

    Take the max() function exposed below as a first example. This function is essentially a “generic function”. In this function, we have a comptime function argument named T. Notice that this T argument has a data type of type. Weird right? This type keyword is the “father of all types”, or, “the type of types” in Zig.

    +

    Because we have used this type keyword in the T argument, we are telling the zig compiler that this T argument will receive some data type as input. Also notice the use of the comptime keyword in this argument. As I described in Section 12.1, every time you use this keyword in a function argument, this means that the value of this argument must be known at compile-time. This makes sense, right? Because there is no data type that is not known at compile-time.

    Think about this. Every data type that you will ever write is always known at compile-time. Especially because data types are an essential information for the compiler to actually compile your source code. Having this in mind, makes sense to mark this argument as a comptime argument.

    fn max(comptime T: type, a: T, b: T) T {
    @@ -477,7 +477,7 @@ 

    }

    Also notice that the value of the T argument is actually used to define the data type of the other arguments in the function, a and b, and also at the return type annotation of the function. That is, the data type of these arguments (a and b), and, the return data type of the function itself, are determined by the input value given to the T argument.

    -

    As a result, we have a generic function that works with different data types. For example, I can provide u8 values to this max() function, and it will work as expected. But if I provide f64 values instead, it will also work as expected. Without a generic function, I would have to write a different max() function for each one of the data types that I wanted to use. This generic function provides a very useful shortcut for us.

    +

    As a result, we have a generic function that works with different data types. For example, I can provide u8 values to this max() function, and it will work as expected. But if I provide f64 values instead, it will also work as expected. Without a generic function, I would have to write a different max() function for each data type I wanted to use. This generic function provides a very useful shortcut for us.

    const std = @import("std");
     fn max(comptime T: type, a: T, b: T) T {
    @@ -496,9 +496,9 @@ 

    12.2.2 A generic data structure

    Every data structure that you find in the Zig Standard Library (e.g. ArrayList, HashMap, etc.) is essentially a generic data structure. These data structures are generic in the sense that they work with any data type you want. You just say which is the data type of the values that are going to be stored in this data structure, and they just work as expected.

    -

    A generic data structure in Zig is how you replicate a generic class from Java, or, a class template from C++. But you may quest yourself: how do we build a generic data structure in Zig?

    +

    A generic data structure in Zig is how you replicate a generic class from Java, or, a class template from C++. But you may ask yourself: how do we build a generic data structure in Zig?

    The basic idea is to write a generic function that creates the data structure definition for the specific type we want. In other words, this generic function behaves as a “factory of data structures”. The generic function outputs the struct definition that defines this data structure for a specific data type.

    -

    To create such function, we need to add a comptime argument to this function that receives a data type as input. We already learned how to do this at the previous section (Section 12.2.1). I think the best way to demonstrate how to create a generic data structure is to actually write one. This where we go into our next small project in this book. This one is a very small project, which is to write a generic stack data structure.

    +

    To create such function, we need to add a comptime argument to this function that receives a data type as input. We already learned how to do this in the previous section (Section 12.2.1). I think the best way to demonstrate how to create a generic data structure is to actually write one. This where we go into our next small project in this book. This one is a very small project, which is to write a generic stack data structure.

    @@ -522,7 +522,7 @@

    12.4 Writing the stack data structure

    We are going to write the stack data structure in two steps. First, we are going to implement a stack that can only store u32 values. Then, after that, we are going to extend our implementation to make it generic, so that it works with any data type we want.

    -

    First, we need to decide how the values will be stored inside the stack. There are multiple ways to implement the storage behind a stack structure. Some people prefer to use a doubly linked list, some others prefer to use a dynamic array, etc. In this example we are going to use an array behind the hood, to store the values in the stack, which is the items data member of our Stack struct definition.

    +

    First, we need to decide how the values will be stored inside the stack. There are multiple ways to implement the storage behind a stack structure. Some people prefer to use a doubly linked list, others prefer to use a dynamic array, etc. In this example we are going to use an array behind the hood, to store the values in the stack, which is the items data member of our Stack struct definition.

    Also notice in our Stack struct that we have three other data members: capacity, length and allocator. The capacity member contains the capacity of the underlying array that stores the values in the stack. The length contains the number of values that are currently being stored in the stack. And the allocator contains the allocator object that will be used by the stack structure whenever it needs to allocate more space for the values that are being stored.

    We begin by defining an init() method of this struct, which is going to be responsible for instantiating a Stack object. Notice that, inside this init() method, we start by allocating an array with the capacity specified in the capacity argument.

    @@ -548,10 +548,10 @@

    12.4.1 Implementing the push operation

    Now that we have written the basic logic to create a new Stack object, we can start writing the logic responsible for performing a push operation. Remember, a push operation in a stack data structure is the operation responsible for adding a new value to the stack.

    -

    So how can we add a new value to the Stack object that we have? The push() function exposed below is a possible answer to this question. Remember from what we discussed at Section 12.3 that values are always added to the top of the stack. This means that this push() function must always find the element in the underlying array that currently represents the top position of the stack, and then, add the input value there.

    +

    So how can we add a new value to the Stack object that we have? The push() function exposed below is a possible answer to this question. Remember from what we discussed in Section 12.3 that values are always added to the top of the stack. This means that this push() function must always find the element in the underlying array that currently represents the top position of the stack, and then, add the input value there.

    First, we have an if statement in this function. This if statement is checking whether we need to expand the underlying array to store this new value that we are adding to the stack. In other words, maybe the underlying array does not have enough capacity to store this new value, and, in this case, we need to expand our array to get the capacity that we need.

    So, if the logical test in this if statement returns true, it means that the array does not have enough capacity, and we need to expand it before we store this new value. So inside this if statement we are executing the necessary expressions to expand the underlying array. Notice that we use the allocator object to allocate a new array that is twice as bigger than the current array (self.capacity * 2).

    -

    After that, we use a different built-in function named @memcpy(). This built-in function is equivalent to the memcpy() function from the C Standard Library1. It is used to copy the values from one block of memory to another block of memory. In other words, you can use this function to copy the values from one array into another array.

    +

    After that, we use a different built-in function named @memcpy(). This built-in function is equivalent to the memcpy() function from the C Standard Library1. It’s used to copy the values from one block of memory to another block of memory. In other words, you can use this function to copy the values from one array into another array.

    We are using this @memcpy() built-in function to copy the values that are currently stored in the underlying array of the stack object (self.items) into our new and bigger array that we have allocated (new_buf). After we execute this function, the new_buf contains a copy of the values that are present at self.items.

    Now that we have secured a copy of our current values in the new_buf object, we can now free the memory currently allocated at self.items. After that, we just need to assign our new and bigger array to self.items. This is the sequence of steps necessary to expand our array.

    @@ -602,11 +602,11 @@

    12.5 Making it generic

    -

    Now that we have implemented the basic skeleton of our stack data structure, we can now focus on discussing how can we make it generic. How can we make this basic skeleton to work not only with u32 values, but also, with any other data type we want? For example, we might need to create a stack object to store User values in it. How can we make this possible? The answer lies on the use of generics and comptime.

    -

    As I described at Section 12.2.2, the basic idea is to write a generic function that returns a struct definition as output. In theory, we do not need much to transform our Stack struct into a generic data structure. All that we need to do is to transform the underlying array of the stack into a generic array.

    -

    In other words, this underlying array needs to be a “chameleon”. It needs to adapt, and transform it into an array of any data type that we want. For example, if we need to create a stack that will store u8 values, then, this underlying array needs to be a u8 array (i.e. []u8). But if we need to store User values instead, then, this array needs to be a User array (i.e. []User). Etc.

    +

    Now that we have implemented the basic skeleton of our stack data structure, we can now focus on discussing how we can make it generic. How can we make this basic skeleton to work not only with u32 values, but also with any other data type we want? For example, we might need to create a stack object to store User values in it. How can we make this possible? The answer lies in the use of generics and comptime.

    +

    As I described in Section 12.2.2, the basic idea is to write a generic function that returns a struct definition as output. In theory, we do not need much to transform our Stack struct into a generic data structure. All that we need to do is to transform the underlying array of the stack into a generic array.

    +

    In other words, this underlying array needs to be a “chameleon”. It needs to adapt, and transform it into an array of any data type that we want. For example, if we need to create a stack that will store u8 values, then this underlying array needs to be a u8 array (i.e., []u8). But if we need to store User values instead, then, this array needs to be a User array (i.e., []User). Etc.

    We do that by using a generic function. Because a generic function can receive a data type as input, and we can pass this data type to the struct definition of our Stack object. Therefore, we can use the generic function to create a Stack object that can store the data type we want. If we want to create a stack structure that stores User values, we pass the User data type to this generic function, and it will create for us the struct definition that describes a Stack object that can store User values in it.

    -

    Look at the code example below. I have omitted some parts of the Stack struct definition for brevity reasons. However, if a specific part of our Stack struct is not exposed here in this example, then it is because this part did not change from the previous example. It remains the same.

    +

    Look at the code example below. I have omitted some parts of the Stack struct definition for brevity. However, if a specific part of our Stack struct is not exposed here in this example, then it’s because this part did not change from the previous example. It remains the same.

    fn Stack(comptime T: type) type {
         return struct {
    @@ -633,7 +633,7 @@ 

    }

    Notice that we have created a function in this example named Stack(). This function takes a type as input, and passes this type to the struct definition of our Stack object. The data member items is now, an array of type T, which is the data type that we have provided as input to the function. The function argument val in the push() function is now a value of type T too.

    -

    We can just provide a data type to this function, and it will create a definition of a Stack object that can store values of the data type that we have provided. In the example below, we are creating the definition of a Stack object that can store u8 values in it. This definition is stored at the Stacku8 object. This Stacku8 object becomes our new struct, it is the struct that we are going to use to create our Stack object.

    +

    We can just provide a data type to this function, and it will create a definition of a Stack object that can store values of the data type that we have provided. In the example below, we are creating the definition of a Stack object that can store u8 values in it. This definition is stored at the Stacku8 object. This Stacku8 object becomes our new struct, that we are going to use to create our Stack object.

    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
     const allocator = gpa.allocator();
    @@ -668,7 +668,7 @@ 

    12.6 Conclusion

    -

    The full source code of the stack structure discussed in this chapter is freely available at the official repository of this book. Just checkout the stack.zig2 for the u32 version of our stack, and the generic_stack.zig3 for the generic version, available inside the ZigExamples folder of the repository.

    +

    The full source code of the stack structure discussed in this chapter is freely available in the official repository of this book. Just checkout the stack.zig2 for the u32 version of our stack, and the generic_stack.zig3 for the generic version, available inside the ZigExamples folder of the repository.

    13.1.2 Introducing file descriptors

    @@ -425,7 +425,7 @@

    <

    From the bullet points listed above, we know that although the term “file” is present, a “file descriptor” might describe something more than just a file. This concept of a “file descriptor” comes from the Portable Operating System Interface (POSIX) API, which is a set of standards that guide how operating systems across the world should be implemented, to maintain compatibility between them.

    A file descriptor not only identifies the input/output resource that you are using to receive or send some data, but it also describes where this resource is, and also, which IO mode this resource is currently using. For example, this IO resource might be using only the “read” IO mode, which means that this resource is open to “read operations”, while “write operations” are not authorized. These IO modes are essentially the modes that you provide to the argument mode from the fopen() C function, and also, from the open() Python built-in function.

    In C, a “file descriptor” is a FILE pointer, but, in Zig, a file descriptor is a File object. This data type (File) is described in the std.fs module of the Zig Standard Library. We normally don’t create a File object directly in our Zig code. Instead, we normally get such object as result when we open an IO resource. In other words, we normally ask our OS to open a particular IO resource for us, and, if the OS do open successfully this IO resource, the OS normally handles back to us a file descriptor to this particular IO resource.

    -

    So you usually get a File object by using functions and methods from the Zig Standard Library that asks the OS to open some IO resource, like the openFile() method that opens a file in the filesystem. The net.Stream object that we have created at Section 7.4.1 is also a type of file descriptor object.

    +

    So you usually get a File object by using functions and methods from the Zig Standard Library that asks the OS to open some IO resource, like the openFile() method that opens a file in the filesystem. The net.Stream object that we have created in Section 7.4.1 is also a type of file descriptor object.

    13.1.3 The standard output

    @@ -449,7 +449,7 @@

    <

    13.1.4 The standard input

    -

    You can access the standard input (i.e. stdin) in Zig by using the getStdIn() function from the std.io module. Like its brother (getStdOut()), this function also returns a file descriptor object that describes the stdin channel of your OS.

    +

    You can access the standard input (i.e., stdin) in Zig by using the getStdIn() function from the std.io module. Like its brother (getStdOut()), this function also returns a file descriptor object that describes the stdin channel of your OS.

    Because we want to receive some input from the user, the key verb here becomes receive, and, as consequence, we usually want to read data from the stdin channel, instead of writing data into it. So, we normally use the reader() method of the file descriptor object returned by getStdIn(), to get access to a GenericReader object that we can use to read data from stdin.

    In the example below, we are creating a small buffer capable of holding 20 characters. Then, we try to read the data from the stdin with the readUntilDelimiterOrEof() method, and save this data into the buffer object. Also notice that we are reading the data from the stdin until we hit a new line character ('\n').

    If you execute this program, you will notice that it stops the execution, ands start to wait indefinitely for some input from the user. In other words, you need to type your name into the terminal, and then, you press Enter to send your name to stdin. After you send your name to stdin, the program reads this input, and continues with the execution, by printing the given name to stdout. In the example below, I typed my name (Pedro) into the terminal, and then, pressed Enter.

    @@ -476,14 +476,14 @@

    13.2 Buffered IO

    -

    As we described at Section 13.1, input/output (IO) operations are made directly by the operating system. It is the OS that manages the IO resource that you want to use for your IO operations. The consequence of this fact is that IO operations are heavily based on system calls (i.e. calling the operating system directly).

    +

    As we described in Section 13.1, input/output (IO) operations are made directly by the operating system. It’s the OS that manages the IO resource that you want to use for your IO operations. The consequence of this fact is that IO operations are heavily based on system calls (i.e., calling the operating system directly).

    Just to be clear, there is nothing particularly wrong with system calls. We use them all the time on any serious codebase written in any low-level programming language. However, system calls are always orders of magnitude slower than many different types of operations.

    -

    So is perfectly fine to use a system call once in a while. But when these system calls are used often, you can clearly notice most of the time the loss of performance in your application. So, the good rule of thumbs is to use a system call only when it is needed, and also, only in infrequent situations, to reduce the number of system calls performed to a minimum.

    +

    So is perfectly fine to use a system call once in a while. But when these system calls are used often, you can clearly notice most of the time the loss of performance in your application. So, the good rule of thumb is to use a system call only when it’s needed, and also, only in infrequent situations, to reduce the number of system calls performed to a minimum.

    13.2.1 Understanding how buffered IO works

    -

    Buffered IO is a strategy to achieve better performance. It is used to reduce the number of system calls made by IO operations, and, as consequence, achieve a much higher performance. At Figure 13.1 and Figure 13.2 you can find two different diagrams which presents the difference between read operations performed in an unbuffered IO environment versus a buffered IO environment.

    -

    To give a better context to these diagrams, let’s suppose that we have a text file that contains the famous Lorem ipsum text8 in our filesystem. Let’s also suppose that these diagrams at Figure 13.1 and Figure 13.2 are showing the read operations that we are performing to read the Lorem ipsum text from this text file. The first thing you will notice when looking at these diagrams, is that in an unbuffered environment the read operations leads to many system calls. More precisely, in the diagram exposed at Figure 13.1 we get one system call per each byte that we read from the text file. On the other hand, at Figure 13.2 we have only one system call at the very beginning.

    -

    When we use a buffered IO system, at the first read operation we perform, instead of sending one single byte directly to our program, the OS first sends a chunk of bytes from the file to a buffer object (i.e. an array). This chunk of bytes are cached/stored inside this buffer object.

    +

    Buffered IO is a strategy to achieve better performance. It’s used to reduce the number of system calls made by IO operations, and, as consequence, achieve a much higher performance. In Figure 13.1 and Figure 13.2 you can find two different diagrams which presents the difference between read operations performed in an unbuffered IO environment versus a buffered IO environment.

    +

    To give a better context to these diagrams, let’s suppose that we have a text file that contains the famous Lorem ipsum text8 in our filesystem. Let’s also suppose that these diagrams in Figure 13.1 and Figure 13.2 are showing the read operations that we are performing to read the Lorem ipsum text from this text file. The first thing you will notice when looking at these diagrams, is that in an unbuffered environment the read operations leads to many system calls. More precisely, in the diagram exposed in Figure 13.1 we get one system call per each byte that we read from the text file. On the other hand, in Figure 13.2 we have only one system call at the very beginning.

    +

    When we use a buffered IO system, at the first read operation we perform, instead of sending one single byte directly to our program, the OS first sends a chunk of bytes from the file to a buffer object (i.e., an array). This chunk of bytes are cached/stored inside this buffer object.

    Therefore, from now on, for every new read operation that you perform, instead of making a new system call to ask for the next byte in the file to the OS, this read operation is redirected to the buffer object, that have this next byte already cached and ready to go.

    @@ -505,20 +505,20 @@

    13.2.2 Buffered IO across different languages

    IO operations made through a FILE pointer in C are buffered by default, so, at least in C, you don’t need to worry about this subject. But in contrast, IO operations in both Rust and Zig are not buffered depending on which functions from the standard libraries that you are using.

    -

    For example, in Rust, buffered IO is implemented through the BufReader and BufWriter structs, while in Zig, it is implemented through the BufferedReader and BufferedWriter structs. So any IO operation that you perform through the GenericWriter and GenericReader objects that I presented at Section 13.1.1 are not buffered, which means that these objects might create a lot of system calls depending on the situation.

    +

    For example, in Rust, buffered IO is implemented through the BufReader and BufWriter structs, while in Zig, it’s implemented through the BufferedReader and BufferedWriter structs. So any IO operation that you perform through the GenericWriter and GenericReader objects that I presented in Section 13.1.1 are not buffered, which means that these objects might create a lot of system calls depending on the situation.

    13.2.3 Using buffered IO in Zig

    Using buffered IO in Zig is actually very easy. All you have to do is to just give the GenericWriter object to the bufferedWriter() function, or, to give the GenericReader object to the bufferedReader() function. These functions come from the std.io module, and they will construct the BufferedWriter or BufferedReader object for you.

    After you create this new BufferedWriter or BufferedReader object, you can call the writer() or reader() method of this new object, to get access to a new (and buffered) generic reader or generic writer.

    Let’s describe the process once again. Every time that you have a file descriptor object, you first get the generic writer or generic reader object from it, by calling the writer() or reader() methods of this file descriptor object. Then, you provide this generic writer or generic reader to the bufferedWriter() or bufferedReader() function, which creates a new BufferedWriter or BufferedReader object. Then, you call the writer() or reader() methods of this buffered writer or buffered reader object, which gives you access to a generic writer or a generic reader object that is buffered.

    -

    Take this program as an example. This program is demonstrating the process exposed at Figure 13.2. We are simply opening a text file that contains the Lorem ipsum text, and then, we create a buffered IO reader object at bufreader, and we use this bufreader object to read the contents of this file into a buffer object, then, we end the program by printing this buffer to stdout.

    +

    Take this program as an example. This program is demonstrating the process exposed in Figure 13.2. We are simply opening a text file that contains the Lorem ipsum text, and then, we create a buffered IO reader object at bufreader, and we use this bufreader object to read the contents of this file into a buffer object, then, we end the program by printing this buffer to stdout.

    var file = try std.fs.cwd().openFile(
         "ZigExamples/file-io/lorem.txt", .{}
    @@ -549,7 +549,7 @@ 

    Section 13.1.1.

    +

    Despite being a buffered IO reader, this bufreader object is similar to any other GenericReader object, and have the exact same methods. So, although these two types of objects perform very different IO operations, they have the same interface, so you, the programmer, can interchangeably use them without the need to change anything in your source code. So a buffered IO reader or a buffered IO writer objects have the same methods than its generic and unbuffered brothers, i.e., the generic reader and generic writer objects that I presented in Section 13.1.1.

    @@ -567,12 +567,12 @@

    13.3 Filesystem basics

    -

    Now that we have discussed the basics around Input/Output operations in Zig, we need to talk about the basics around filesystems, which is another core part of any operating system. Also, filesystems are related to input/output, because the files that we store and create in our computer are considered an IO resource, as we described at Section 13.1.2.

    +

    Now that we have discussed the basics around Input/Output operations in Zig, we need to talk about the basics around filesystems, which is another core part of any operating system. Also, filesystems are related to input/output, because the files that we store and create in our computer are considered an IO resource, as we described in Section 13.1.2.

    13.3.1 The concept of current working directory (CWD)

    -

    The working directory is the folder on your computer where you are currently rooted at. In other words, it is the folder that your program is currently looking at. Therefore, whenever you are executing a program, this program is always working with a specific folder on your computer. It is always in this folder that the program will initially look for the files you require, and it is also in this folder that the program will initially save all the files you ask it to save.

    -

    The working directory is determined by the folder from which you invoke your program in the terminal. In other words, if you are in the terminal of your OS, and you execute a binary file (i.e. a program) from this terminal, the folder to which your terminal is pointing at is the current working directory of your program that is being executed.

    -

    At Figure 13.3 we have an example of me executing a program from the terminal. We are executing the program outputted by the zig compiler by compiling the Zig module named hello.zig. The CWD in this case is the zig-book folder. In other words, while the hello.zig program is executing, it will be looking at the zig-book folder, and any file operation that we perform inside this program, will be using this zig-book folder as the “starting point”, or, as the “central focus”.

    +

    The working directory is the folder on your computer where you are currently rooted at. In other words, it’s the folder that your program is currently looking at. Therefore, whenever you are executing a program, this program is always working with a specific folder on your computer. It’s always in this folder that the program will initially look for the files you require, and it’s also in this folder that the program will initially save all the files you ask it to save.

    +

    The working directory is determined by the folder from which you invoke your program in the terminal. In other words, if you are in the terminal of your OS, and you execute a binary file (i.e., a program) from this terminal, the folder to which your terminal is pointing at is the current working directory of your program that is being executed.

    +

    In Figure 13.3 we have an example of me executing a program from the terminal. We are executing the program outputted by the zig compiler by compiling the Zig module named hello.zig. The CWD in this case is the zig-book folder. In other words, while the hello.zig program is executing, it will be looking at the zig-book folder, and any file operation that we perform inside this program, will be using this zig-book folder as the “starting point”, or, as the “central focus”.

    @@ -587,10 +587,10 @@

    13.3.2 The concept of paths

    -

    A path is essentially a location. It points to a location in your filesystem. We use paths to describe the location of files and folders in our computer. One important aspect about paths is that they are always written inside strings, i.e. they are always provided as text values.

    -

    There are two types of paths that you can provide to any program in any OS: a relative path, or an absolute path. Absolute paths are paths that start at the root of your filesystem, and go all the way to the file name or the specific folder that you are referring to. This type of path is called absolute, because it points to an unique and absolute location on your computer. That is, there is no other existing location on your computer that corresponds to this path. It is an unique identifier.

    +

    A path is essentially a location. It points to a location in your filesystem. We use paths to describe the location of files and folders in our computer. One important aspect about paths is that they are always written inside strings, i.e., they are always provided as text values.

    +

    There are two types of paths that you can provide to any program in any OS: a relative path, or an absolute path. Absolute paths are paths that start at the root of your filesystem, and go all the way to the file name or the specific folder that you are referring to. This type of path is called absolute, because it points to an unique and absolute location on your computer. That is, there is no other existing location on your computer that corresponds to this path. It’s an unique identifier.

    In Windows, an absolute path is a path that starts with a hard disk identifier (e.g. C:/Users/pedro). On the other hand, absolute paths in Linux and macOS, are paths that start with a forward slash character (e.g. /usr/local/bin). Notice that a path is composed by “segments”. Each segment is connected to each other by a slash character (\ or /). On Windows, the backward slash (\) is normally used to connect the path segments. While on Linux and macOS, the forward slash (/) is the character used to connect path segments.

    -

    A relative path is a path that start at the CWD. In other words, a relative path is “relative to the CWD”. The path used to access the hello.zig file at Figure 13.3 is an example of a relative path. This path is reproduced below. This path begins at the CWD, which in the context of Figure 13.3, is the zig-book folder, then, it goes to the ZigExamples folder, then, into zig-basics, then, to the hello.zig file.

    +

    A relative path is a path that start at the CWD. In other words, a relative path is “relative to the CWD”. The path used to access the hello.zig file in Figure 13.3 is an example of a relative path. This path is reproduced below. This path begins at the CWD, which in the context of Figure 13.3, is the zig-book folder, then, it goes to the ZigExamples folder, then, into zig-basics, then, to the hello.zig file.

    ZigExamples/zig-basics/hello_world.zig
    @@ -614,7 +614,7 @@

    13.5.1 Creating files

    We create new files by using the createFile() method from the Dir object. Just provide the name of the file that you want to create, and this function will do the necessary steps to create such file. You can also provide a relative path to this function, and it will create the file by following this path, which is relative to the CWD.

    -

    This function might return an error, so, you should use try, catch, or any of the other methods presented at Chapter 10 to handle the possible error. But if everything goes well, this createFile() method returns a file descriptor object (i.e. a File object) as result, through which you can add content to the file with the IO operations that I presented before.

    +

    This function might return an error, so, you should use try, catch, or any of the other methods presented in Chapter 10 to handle the possible error. But if everything goes well, this createFile() method returns a file descriptor object (i.e., a File object) as result, through which you can add content to the file with the IO operations that I presented before.

    Take this code example below. In this example, we are creating a new text file named foo.txt. If the function createFile() succeeds, the object named file will contain a file descriptor object, which we can use to write (or add) new content to the file, like we do in this example, by using a buffered writer object to write a new line of text to the file.

    Now, a quick note, when we create a file descriptor object in C, by using a C function like fopen(), we must always close the file at the end of our program, or, as soon as we complete all operations that we wanted to perform on the file. In Zig, this is no different. So everytime we create a new file, this file remains “open”, waiting for some operation to be performed. As soon as we are done with it, we always have to close this file, to free the resources associated with it. In Zig, we do this by calling the method close() from the file descriptor object.

    @@ -629,9 +629,9 @@

    );

    So, in this example we not only have created a file into the filesystem, but we also wrote some data into this file, using the file descriptor object returned by createFile(). If the file that you are trying to create already exists in your filesystem, this createFile() call will overwrite the contents of the file, or, in other words, it will in erase all the contents of the existing file.

    -

    If you don’t want this to happen, meaning, that you don’t want to overwrite the contents of the existing file, but you want to write data to this file anyway (i.e. you want to append data to the file), you should use the openFile() method from the Dir object.

    +

    If you don’t want this to happen, meaning, that you don’t want to overwrite the contents of the existing file, but you want to write data to this file anyway (i.e., you want to append data to the file), you should use the openFile() method from the Dir object.

    Another important aspect about createFile() is that this method creates a file that is not open to read operations by default. It means that you cannot read this file. You are not allowed to. So for example, you might want to write some stuff into this file at the beginning of the execution of your program. Then, at a future point in your program you might need to read what you wrote in this file. If you try to read data from this file, you will likely get a NotOpenForReading error as result.

    -

    But how can you overcome this barrier? How can you create a file that is open to read operations? All you have to do, is to set the read flag to true in the second argument of createFile(). When you set this flag to true, then the file get’s create with “read permissions”, and, as consequence, a program like this one below becomes valid:

    +

    But how can you overcome this barrier? How can you create a file that is open to read operations? All you have to do, is to set the read flag to true in the second argument of createFile(). When you set this flag to true, then the file gets create with “read permissions”, and, as consequence, a program like this one below becomes valid:

    const cwd = std.fs.cwd();
     const file = try cwd.createFile(
    @@ -651,18 +651,18 @@ 

    try stdout.print("{s}\n", .{buffer});

    We are going to read this line
    -

    If you are not familiar with position indicators, you might not recognize the method seekTo(). If that is your case, do not worry, we are going to talk more about this method at Section 13.6. But essentially this method is moving the position indicator back to the beginning of the file, so that we can read the contents of the file from the beginning.

    +

    If you are not familiar with position indicators, you might not recognize the method seekTo(). If that is your case, do not worry, we are going to talk more about this method in Section 13.6. But essentially this method is moving the position indicator back to the beginning of the file, so that we can read the contents of the file from the beginning.

    13.5.2 Opening files and appending data to it

    Opening files is easy. Just use the openFile() method instead of createFile(). In the first argument of openFile() you provide the path to the file that you want to open. Then, on the second argument you provide the flags (or, the options) that dictates how the file is opened.

    -

    You can see the full list of options for openFile() by visiting the documentation for OpenFlags9. But the main flag that you will most certainly use is the mode flag. This flag specifies the IO mode that the file will be using when it get’s opened. There are three IO modes, or, three values that you can provide to this flag, which are:

    +

    You can see the full list of options for openFile() by visiting the documentation for OpenFlags9. But the main flag that you will most certainly use is the mode flag. This flag specifies the IO mode that the file will be using when it gets opened. There are three IO modes, or, three values that you can provide to this flag, which are:

    • read_only, allows only read operations on the file. All write operations are blocked.
    • write_only, allows only write operations on the file. All read operations are blocked.
    • read_write, allows both write and read operations on the file.
    -

    These modes are similar to the modes that you provide to the mode argument of the open() Python built-in function10, or, the mode argument of the fopen() C function11. In the code example below, we are opening the foo.txt text file with a write_only mode, and appending a new line of text to the end of the file. We use seekFromEnd() this time to guarantee that we are going to append the text to the end of the file. Once again, methods such as seekFromEnd() are described in more depth at Section 13.6.

    +

    These modes are similar to the modes that you provide to the mode argument of the open() Python built-in function10, or, the mode argument of the fopen() C function11. In the code example below, we are opening the foo.txt text file with a write_only mode, and appending a new line of text to the end of the file. We use seekFromEnd() this time to guarantee that we are going to append the text to the end of the file. Once again, methods such as seekFromEnd() are described in more depth in Section 13.6.

    const cwd = std.fs.cwd();
     const file = try cwd.openFile(
    @@ -684,7 +684,7 @@ 

    13.5.4 Copying files

    -

    To copy existing files, we use the copyFile() method. The first argument in this method is the path to the file that you want to copy. The second argument is a Dir object, i.e. a directory handler, more specifically, a Dir object that points to the folder in your computer where you want to copy the file to. The third argument is the new path of the file, or, in other words, the new location of the file. The fourth argument is the options (or flags) to be used in the copy operation.

    +

    To copy existing files, we use the copyFile() method. The first argument in this method is the path to the file that you want to copy. The second argument is a Dir object, i.e., a directory handler, more specifically, a Dir object that points to the folder in your computer where you want to copy the file to. The third argument is the new path of the file, or, in other words, the new location of the file. The fourth argument is the options (or flags) to be used in the copy operation.

    The Dir object that you provide as input to this method will be used to copy the file to the new location. You may create this Dir object before calling the copyFile() method. Maybe you are planning to copy the file to a completely different location in your computer, so it might be worth to create a directory handler to that location. But if you are copying the file to a subfolder of your CWD, then, you can just simply pass the CWD handler to this argument.

    const cwd = std.fs.cwd();
    @@ -705,7 +705,7 @@ 

    13.6 Position indicators

    A position indicator is like a type of cursor, or, an index. This “index” identifies the current location in the file (or, in the data stream) that the file descriptor object that you have is currently looking at. When you create a file descriptor, the position indicator starts at the beginning of the file, or, at the beginning of the stream. When you read from or write into the file (or socket, or data stream, etc.) described by this file descriptor object, you end up moving the position indicator.

    In other words, any IO operation have a common side effect, which is to move the position indicator. For example, suppose that we have a file of 300 bytes total in size. If you read 100 bytes from the file, then, the position indicator moves 100 bytes forward. If you try to write 50 bytes into this same file, these 50 bytes will be written from the current position indicated by the position indicator. Since the indicator is at a 100 bytes forward from the beginning of the file, these 50 bytes would be written in the middle of the file.

    -

    This is why we have used the seekTo() method at the last code example presented at Section 13.5.1. We have used this method to move the position indicator back to the beginning of the file, which would make sure that we would write the text that we wanted to write from the beginning of the file, instead of writing it from the middle of the file. Because before the write operation, we had performed a read operation, which means that the position indicator was moved in this read operation.

    +

    This is why we have used the seekTo() method at the last code example presented in Section 13.5.1. We have used this method to move the position indicator back to the beginning of the file, which would make sure that we would write the text that we wanted to write from the beginning of the file, instead of writing it from the middle of the file. Because before the write operation, we had performed a read operation, which means that the position indicator was moved in this read operation.

    The position indicators of a file descriptor object can be changed (or altered) by using the “seek” methods from this file descriptor, which are: seekTo(), seekFromEnd() and seekBy(). These methods have the same effect, or, the same responsibility that the fseek()13 C function.

    Considering that offset refers to the index that you provide as input to these “seek” methods, the bullet points below summarises what is the effect of each of these methods. As a quick note, in the case of seekFromEnd() and seekBy(), the offset provided can be either a positive or a negative index.

      @@ -781,7 +781,7 @@

      1. Previously, these objects were known as the Reader and Writer objects.↩︎

      2. -
      3. The socket objects that we have created at Section 7.4.1, are examples of network sockets.↩︎

      4. +
      5. The socket objects that we have created in Section 7.4.1, are examples of network sockets.↩︎

      6. https://ziglang.org/documentation/master/std/#std.io.GenericWriter.↩︎

      7. https://ziglang.org/documentation/master/std/#std.io.GenericReader.↩︎

      8. https://github.com/ziglang/zig/blob/master/lib/std/io/Reader.zig.↩︎

      9. diff --git a/docs/Chapters/13-image-filter.html b/docs/Chapters/13-image-filter.html index 58efbfaa..8c893a3c 100644 --- a/docs/Chapters/13-image-filter.html +++ b/docs/Chapters/13-image-filter.html @@ -370,7 +370,7 @@

        15  Figure 15.1 in this project. In other words, we want to transform this colored image into a grayscale image, by using our “image filter program” written in Zig.

        +

        We are going to use the image displayed in Figure 15.1 in this project. In other words, we want to transform this colored image into a grayscale image, by using our “image filter program” written in Zig.

        @@ -382,7 +382,7 @@

        15  Figure 15.1 as input, and writes a new image to the current working directory that is the grayscale version of this input image. This grayscale version of Figure 15.1 is exposed at Figure 15.2. You can find the full source code of this small project at the ZigExamples/image_filter folder at the official repository of this book1.

        +

        At the end of this chapter, we should have a full example of a program that takes the PNG image displayed in Figure 15.1 as input, and writes a new image to the current working directory that is the grayscale version of this input image. This grayscale version of Figure 15.1 is exposed in Figure 15.2. You can find the full source code of this small project at the ZigExamples/image_filter folder at the official repository of this book1.

        @@ -429,9 +429,9 @@

        Most digital images we see in our modern world uses the RGB color model. RGB stands for (red, green and blue). So the color of each pixel in these raster images are usually represented as a mixture of red, green and blue, just like in our eyes. That is, the color of each pixel is identified by a set of three different integer values. Each integer value identifies the “amount” of each color (red, green and blue). For example, the set (199, 78, 70) identifies a color that is more close to red. We have 199 of red, 78 of green, and 70 of blue. In contrast, the set (129, 77, 250) describes a color that is more close to purple. Et cetera.

        15.2.1 Images are displayed from top to bottom

        -

        This is not a rule written in stone, but the big majority of digital images are displayed from top to bottom and left to right. Most computers screens also follow this pattern. So, the first pixels in the image are the ones that are at the top and left corner of the image. You can find a visual representation of this logic at Figure 15.4.

        +

        This is not a rule written in stone, but the big majority of digital images are displayed from top to bottom and left to right. Most computers screens also follow this pattern. So, the first pixels in the image are the ones that are at the top and left corner of the image. You can find a visual representation of this logic in Figure 15.4.

        Also notice in Figure 15.4 that, because a raster image is essentially a 2D matrix of pixels, the image is organized into rows and columns of pixels. The columns are defined by the horizontal x axis, while the rows are defined by the vertical y axis.

        -

        Each pixel (i.e. the gray rectangles) exposed at Figure 15.4 contains a number inside of it. These numbers are the indexes of the pixels. You can notice that the first pixels are in the top and left corner, and also, that the indexes of these pixels “grow to the sides”, or, in other words, they grow in the direction of the horizontal x axis. Most raster images are organized as rows of pixels. Thus, when these digital images are displayed, the screen display the first row of pixels, then, the second row, then, the third row, etc.

        +

        Each pixel (i.e., the gray rectangles) exposed in Figure 15.4 contains a number inside of it. These numbers are the indexes of the pixels. You can notice that the first pixels are in the top and left corner, and also, that the indexes of these pixels “grow to the sides”, or, in other words, they grow in the direction of the horizontal x axis. Most raster images are organized as rows of pixels. Thus, when these digital images are displayed, the screen display the first row of pixels, then, the second row, then, the third row, etc.

        @@ -447,7 +447,7 @@

        15.2.2 Representing the matrix of pixels in code

        Ok, we know already that raster images are represented as 2D matrices of pixels. But we do not have a notion of a 2D matrix in Zig. Actually, most low-level languages in general (Zig, C, Rust, etc.) do not have such notion. So how can we represent such matrix of pixels in Zig, or any other low-level language? The strategy that most programmers choose in this situation is to just use a normal 1D array to store the values of this 2D matrix. In other words, you just create an normal 1D array, and store all values from both dimensions into this 1D array.

        As an example, suppose we have a very small image of dimensions 4x3. Since a raster image is represented as a 2D matrix of pixels, and each pixel is represented by 3 “unsigned 8-bit” integer values, we have 12 pixels in total in this image, which are represented by \(3 \times 12 = 36\) integer values. Therefore, we need to create an array of 36 u8 values to store this small image.

        -

        The reason why unsigned 8-bit integer (u8) values are used to represent the amounts of each color, instead of any other integer type, is because they take the minimum amount of space as possible, or, the minimum amount of bits as possible. Which helps to reduces the binary size of the image, i.e. the 2D matrix. Also, they convey a good amount of precision and detail about the colors, even though they can represent a relatively small range (from 0 to 255) of “color amounts”.

        +

        The reason why unsigned 8-bit integer (u8) values are used to represent the amounts of each color, instead of any other integer type, is because they take the minimum amount of space as possible, or, the minimum amount of bits as possible. Which helps to reduces the binary size of the image, i.e., the 2D matrix. Also, they convey a good amount of precision and detail about the colors, even though they can represent a relatively small range (from 0 to 255) of “color amounts”.

        Coming back to our initial example of a 4x3 image, the matrix object exposed below could be an example of an 1D array that stores the data that represents this 4x3 image.

        const matrix = [_]u8{
        @@ -467,16 +467,16 @@ 

        15.3 The PNG library that we are going to use

        -

        Let’s begin our project by focusing on writing the necessary Zig code to read the data from the PNG file. In other words, we want to read the PNG file exposed at Figure 15.1, and parse its data to extract the 2D matrix of pixels that represents the image.

        -

        As we have discussed at Section 15.2.2, the image that we are using as example here is a PNG file that uses the RGBA color model, and, therefore, each pixel of the image is represented by 4 integer values. You can download this image by visiting the ZigExamples/image_filter folder at the official repository of this book3. You can also find in this folder the complete source code of this small project that we are developing here.

        -

        There are some C libraries available that we can use to read and parse PNG files. The most famous and used of all is libpng, which is the “official library” for reading and writing PNG files. Although this library is available on most operating system, it is well known for being complex and hard to use.

        -

        That is why, I’m going to use a more modern alternative here in this project, which is the libspng library. I choose to use this C library here, because it is much, much simpler to use than libpng, and it also offers very good performance for all operations. You can checkout the official website of the library4 to know more about it. You will also find there some documentation that might help you to understand and follow the code examples exposed here.

        +

        Let’s begin our project by focusing on writing the necessary Zig code to read the data from the PNG file. In other words, we want to read the PNG file exposed in Figure 15.1, and parse its data to extract the 2D matrix of pixels that represents the image.

        +

        As we have discussed in Section 15.2.2, the image that we are using as example here is a PNG file that uses the RGBA color model, and, therefore, each pixel of the image is represented by 4 integer values. You can download this image by visiting the ZigExamples/image_filter folder at the official repository of this book3. You can also find in this folder the complete source code of this small project that we are developing here.

        +

        There are some C libraries available that we can use to read and parse PNG files. The most famous and used of all is libpng, which is the “official library” for reading and writing PNG files. Although this library is available on most operating system, it’s well known for being complex and hard to use.

        +

        That is why, I’m going to use a more modern alternative here in this project, which is the libspng library. I choose to use this C library here, because it’s much, much simpler to use than libpng, and it also offers very good performance for all operations. You can checkout the official website of the library4 to know more about it. You will also find there some documentation that might help you to understand and follow the code examples exposed here.

        First of all, remember to build and install this libspng into your system. Because if you don’t do this step, the zig compiler will not be able to find the files and resources of this library in your computer, and link them with the Zig source code that we are writing together here. There is good information about how to build and install the library at the build section of the library documentation5.

        15.4 Reading the PNG file

        In order to extract the pixel data from the PNG file, we need to read and decode the file. A PNG file is just a binary file written in the “PNG format”. Luckily, the libspng library offers a function called spng_decode_image() that does all this heavy work for us.

        -

        Now, since libspng is a C library, most of the file and I/O operations in this library are made by using a FILE C pointer. Because of that, is probably a better idea to use the fopen() C function to open our PNG file, instead of using the openFile() method that I introduced at Chapter 13. That is why I’m importing the stdio.h C header in this project, and using the fopen() C function to open the file.

        +

        Now, since libspng is a C library, most of the file and I/O operations in this library are made by using a FILE C pointer. Because of that, is probably a better idea to use the fopen() C function to open our PNG file, instead of using the openFile() method that I introduced in Chapter 13. That is why I’m importing the stdio.h C header in this project, and using the fopen() C function to open the file.

        If you look at the snippet below, you can see that we are:

        1. opening the PNG file with fopen().
        2. @@ -511,7 +511,7 @@

          15.4.1 Reading the image header section

          Now, the context object ctx is aware of our PNG file pedro_pascal.png, because it has access to a file descriptor object to this file. The first thing that we are going to do is to read the “image header section” of the PNG file. This “image header section” is the section of the file that contains some basic information about the PNG file, like, the bit depth of the pixel data of the image, the color model used in the file, the dimensions of the image (height and width in number of pixels), etc.

          To make things easier, I will encapsulate this “read image header” operation into a nice and small function called get_image_header(). All that this function needs to do is to call the spng_get_ihdr() function. This function from libspng is responsible for reading the image header data, and storing it into a C struct named spng_ihdr. Thus, an object of type spng_ihdr is a C struct that contains the data from the image header section of the PNG file.

          -

          Since this Zig function is receiving a C object (the libspng context object) as input, I marked the function argument ctx as “a pointer to the context object” (*c.spng_ctx), following the recommendations that we have discussed at Section 14.5.

          +

          Since this Zig function is receiving a C object (the libspng context object) as input, I marked the function argument ctx as “a pointer to the context object” (*c.spng_ctx), following the recommendations that we have discussed in Section 14.5.

          fn get_image_header(ctx: *c.spng_ctx) !c.spng_ihdr {
               var image_header: c.spng_ihdr = undefined;
          @@ -579,7 +579,7 @@ 

          Section 15.2.2, I have described in that section that our pedro_pascal.png PNG file uses the RGBA color model, which adds an alpha (or transparency) byte to each pixel in the image. As consequence, each pixel in the image is represented by 4 bytes. Since we are looking here are the first 12 bytes in the image, it means that we are looking at the data from the first \(12 / 4 = 3\) pixels in the image.

          -

          So, based on how these first 12 bytes (or these 3 pixels) look, with these 255 values at every 4 bytes, we can say that is likely that every pixel in the image have alpha (or transparency) setted to 100%. This might not be true, but, is the most likely possibility. Also, if we look at the image itself, which if your recall is exposed at Figure 15.1, we can see that the transparency does not change across the image, which enforces this theory.

          +

          So, based on how these first 12 bytes (or these 3 pixels) look, with these 255 values at every 4 bytes, we can say that is likely that every pixel in the image have alpha (or transparency) setted to 100%. This might not be true, but, is the most likely possibility. Also, if we look at the image itself, which if your recall is exposed in Figure 15.1, we can see that the transparency does not change across the image, which enforces this theory.

          try stdout.print("{any}\n", .{buffer[0..12]});
          @@ -597,7 +597,7 @@

          \[ p' = (0.2126 \times r) + (0.7152 \times g) + (0.0722 \times b) \tag{15.1}\]

          -

          This Equation 15.1 is the formula to calculate the linear luminance of a pixel. Is worth noting that this formula works only for images whose pixels are using the sRGB color space, which is the standard color space for the web. Thus, ideally, all images on the web should use this color space. Luckily, this is our case here, i.e. the pedro_pascal.png image is using this sRGB color space, and, as consequence, we can use the Equation 15.1. You can read more about this formula at the Wikipedia page for grayscale (Wikipedia 2024).

          +

          This Equation 15.1 is the formula to calculate the linear luminance of a pixel. It’s worth noting that this formula works only for images whose pixels are using the sRGB color space, which is the standard color space for the web. Thus, ideally, all images on the web should use this color space. Luckily, this is our case here, i.e., the pedro_pascal.png image is using this sRGB color space, and, as consequence, we can use the Equation 15.1. You can read more about this formula at the Wikipedia page for grayscale (Wikipedia 2024).

          The apply_image_filter() function exposed below summarises the necessary steps to apply Equation 15.1 over the pixels in the image. We just apply this function over our buffer object that contains our pixel data, and, as result, the pixel data stored in this buffer object should now represent the grayscale version of our image.

          fn apply_image_filter(buffer:[]u8) !void {
          @@ -663,7 +663,7 @@ 

          try save_png(&image_header, buffer[0..]);

          -

          After we execute this save_png() function, we should have a new PNG file inside our CWD, named pedro_pascal_filter.png. If we open this PNG file, we will see the same image exposed at Figure 15.2.

          +

          After we execute this save_png() function, we should have a new PNG file inside our CWD, named pedro_pascal_filter.png. If we open this PNG file, we will see the same image exposed in Figure 15.2.

        15.7 Building our project

        diff --git a/docs/Chapters/14-threads.html b/docs/Chapters/14-threads.html index 9dac90fb..6bfb842d 100644 --- a/docs/Chapters/14-threads.html +++ b/docs/Chapters/14-threads.html @@ -385,10 +385,10 @@

        16.1 What are threads?

        A thread is basically a separate context of execution. We use threads to introduce parallelism into our program, which in most cases, makes the program run faster, because we have multiple tasks being performed at the same time, parallel to each other.

        Programs are normally single-threaded by default. Which means that each program usually runs on a single thread, or, a single context of execution. When we have only one thread running, we have no parallelism. And when we don’t have parallelism, the commands are executed sequentially, that is, only one command is executed at a time, one after another. By creating multiple threads inside our program, we start to execute multiple commands at the same time.

        -

        Programs that create multiple threads are very common on the wild. Because many different types of applications are well suited for parallelism. Good examples are video and photo-editing applications (e.g. Adobe Photoshop or DaVinci Resolve), games (e.g. The Witcher 3), and also web browsers (e.g. Google Chrome, Firefox, Microsoft Edge, etc). For example, in web browsers, threads are normally used to implement tabs. The tabs in a web browsers usually run as separate threads in the main process of the web browser. That is, each new tab that you open in your web browser, usually runs on a separate thread of execution.

        -

        By running each tab in a separate thread, we allow all open tabs in the browser to run at the same time, and independently from each other. For example, you might have YouTube, or Spotify, currently opened in a tab, and you are listening to some podcast in that tab, while, at the same time, you are working in another tab, writing an essay on Google Docs. Even if you are not looking into the YouTube tab, you can still hear the podcast only because this YouTube tab is running in parallel with the other tab where Google Docs is running.

        -

        Without threads, the other alternative would be to run each tab as a completely separate process in your computer. But that would be a bad choice, because just a few tabs would already consume too much power and resources from your computer. In other words, is very expensive to create a completely new process, compared to creating a new thread of execution. Also, the chances of you experiencing lag and overhead while using the browser would be significant. Threads are faster to create, and they also consume much, much less resources from the computer, especially because they share some resources with the main process.

        -

        Therefore, is the use of threads in modern web browsers that allows you to hear the podcast at the same time while you are writing something on Google Docs. Without threads, a web browser would probably be limited to just one single tab.

        +

        Programs that create multiple threads are very common in the wild. Because many different types of applications are well suited for parallelism. Good examples are video and photo-editing applications (e.g. Adobe Photoshop or DaVinci Resolve), games (e.g. The Witcher 3), and also web browsers (e.g. Google Chrome, Firefox, Microsoft Edge, etc). For example, in web browsers, threads are normally used to implement tabs. The tabs in a web browsers usually run as separate threads in the main process of the web browser. That is, each new tab that you open in your web browser usually runs on a separate thread of execution.

        +

        By running each tab in a separate thread, we allow all open tabs in the browser to run at the same time, and independently from each other. For example, you might have YouTube or Spotify currently open in a tab, and you are listening to some podcast in that tab while at the same time working in another tab, writing an essay on Google Docs. Even if you are not looking into the YouTube tab, you can still hear the podcast only because this YouTube tab is running in parallel with the other tab where Google Docs is running.

        +

        Without threads, the other alternative would be to run each tab as a completely separate process in your computer. But that would be a bad choice because just a few tabs would already consume too much power and resources from your computer. In other words, it’s very expensive to create a completely new process, compared to creating a new thread of execution. Also, the chances of you experiencing lag and overhead while using the browser would be significant. Threads are faster to create, and they also consume much, much less resources from the computer, especially because they share some resources with the main process.

        +

        Therefore, it’s the use of threads in modern web browsers that allow you to hear the podcast at the same time while you are writing something on Google Docs. Without threads, a web browser would probably be limited to just one single tab.

        Threads are also well-suited for anything that involves serving requests or orders. Because serving a request takes time, and usually involves a lot of “waiting time”. In other words, we spend a lot of time in idle, waiting for something to complete. For example, consider a restaurant. Serving orders in a restaurant usually involves the following steps:

        1. receive order from the client.
        2. @@ -396,8 +396,8 @@

          start cooking the food in the kitchen.
        3. when the food is fully cooked deliver this food to the client.
        -

        If you think about the bullet points above, you will notice that one big moment of waiting time is present in this whole process, which is while the food is being cooked inside the kitchen. While the food is being prepped, both the waiter and the client itself are waiting for the food to be ready and delivered.

        -

        If we write a program to represent this restaurant, more specifically, a single-threaded program, then, this program would be very inefficient. Because the program would stay in idle, waiting for a considerable amount of time on the “check if food is ready” step. Consider the code snippet exposed below that could potentially represent such program.

        +

        If you think about the bullet points above, you will notice that one big moment of waiting time is present in this whole process, which is while the food is being cooked inside the kitchen. While the food is being prepped, both the waiter and the client themselves are waiting for the food to be ready and delivered.

        +

        If we write a program to represent this restaurant, more specifically, a single-threaded program, then this program would be very inefficient. Because the program would stay in idle, waiting for a considerable amount of time on the “check if food is ready” step. Consider the code snippet exposed below that could potentially represent such program.

        The problem with this program is the while loop. This program will spend a lot of time waiting on the while loop, doing nothing more than just checking if the food is ready. This is a waste of time. Instead of waiting for something to happen, the waiter could just send the order to the kitchen, and just move on, and continue with receiving more orders from other clients, and sending more orders to the kitchen, instead of doing nothing and waiting for the food to be ready.

        const order = Order.init("Pizza Margherita", n = 1);
        @@ -413,7 +413,7 @@ 

        This is why threads would be a great fit for this program. We could use threads to free the waiters from their “waiting duties”, so they can go on with their other tasks, and receive more orders. Take a look at the next example, where I have re-written the above program into a different program that uses threads to cook and deliver the orders.

        You can see in this program that when a waiter receives a new order from a client, this waiter executes the send_order() function. The only thing that this function does is to create a new thread and detaches it. Since creating a thread is a very fast operation, this send_order() function returns almost immediately, so the waiter spends almost no time worrying about the order, and just move on and tries to get the next order from the clients.

        -

        Inside the new thread created, the order get’s cooked by a chef, and when the food is ready, it is delivered to the client’s table.

        +

        Inside the new thread created, the order gets cooked by a chef, and when the food is ready, it’s delivered to the client’s table.

        fn cook_and_deliver_order(order: *Order) void {
             const chef = Chef.init();
        @@ -442,27 +442,27 @@ 

        16.3 Creating a thread

        -

        We create new threads in Zig, by first, importing the Thread struct into our current Zig module, and then, calling the spawn() method of this struct, which creates (or, “spawns”) a new thread of execution from our current process. This method have three arguments, which are, respectively:

        +

        We create new threads in Zig by first importing the Thread struct into our current Zig module and then calling the spawn() method of this struct, which creates (or “spawns”) a new thread of execution from our current process. This method has three arguments, which are, respectively:

        1. a SpawnConfig object, which contains configurations for the spawn process.
        2. -
        3. the name of the function that is going to be executed (or, that is going to be “called”) inside this new thread.
        4. +
        5. the name of the function that is going to be executed (or that is going to be “called”) inside this new thread.
        6. a list of arguments (or inputs) to be passed to the function provided in the second argument.
        -

        With these three arguments, you can control how the thread get’s created, and also, specify which work (or “tasks”) will be performed inside this new thread. A thread is just a separate context of execution, and we usually create new threads in our code, because we want to perform some work inside this new context of execution. And we specify which exact work, or, which exact steps that are going to be performed inside this context, by providing the name of a function on the second argument of the spawn() method.

        -

        Thus, when this new thread get’s created, this function that you provided as input to the spawn() method get’s called, or, get’s executed inside this new thread. You can control the arguments, or, the inputs that are passed to this function when it get’s called, by providing a list of arguments (or a list of inputs) on the third argument of the spawn() method. These arguments are passed to the function in the same order that they are provided to spawn().

        +

        With these three arguments, you can control how the thread gets created, and also, specify which work (or “tasks”) will be performed inside this new thread. A thread is just a separate context of execution, and we usually create new threads in our code because we want to perform some work inside this new context of execution. And we specify which exact work, or which exact steps that are going to be performed inside this context by providing the name of a function as the second argument of the spawn() method.

        +

        Thus, when this new thread gets created, this function that you provided as input to the spawn() method gets called, or gets executed inside this new thread. You can control the arguments, or the inputs that are passed to this function when it gets called by providing a list of arguments (or a list of inputs) in the third argument of the spawn() method. These arguments are passed to the function in the same order that they are provided to spawn().

        Furthermore, the SpawnConfig is a struct object with only two possible fields, or, two possible members, that you can set to tailor the spawn behaviour. These fields are:

          -
        • stack_size: you can provide an usize value to specify the size (in bytes) of the thread’s stack frame. By default, this value is: \(16 \times 1024 \times 1024\).
        • +
        • stack_size: you can provide a usize value to specify the size (in bytes) of the thread’s stack frame. By default, this value is: \(16 \times 1024 \times 1024\).
        • allocator: you can provide an allocator object to be used when allocating memory for the thread.
        -

        To use one of these two fields (or, “configs”) you just have to create a new object of type SpawnConfig, and provide this object as input to the spawn() method. But, if you are not interested in using one of these configs, and you are ok with using just the defaults, you can just provide an anonymous struct literal (.{}) in the place of this SpawnConfig argument.

        +

        To use one of these two fields (or “configs”), you just have to create a new object of type SpawnConfig, and provide this object as input to the spawn() method. But, if you are not interested in using one of these configs, and you are ok with using just the defaults, you can just provide an anonymous struct literal (.{}) in place of this SpawnConfig argument.

        As our first, and very simple example, consider the code exposed below. Inside the same program, you can create multiple threads of execution if you want to. But, in this first example, we are creating just a single thread of execution, because we call spawn() only once.

        -

        Also, notice in this example that we are executing the function do_some_work() inside the new thread. Since this function receives no inputs, because it has no arguments, we have passed an empty list in this instance, or, more precisely, an empty and anonymous struct (.{}) in the third argument of spawn().

        +

        Also, notice in this example that we are executing the function do_some_work() inside the new thread. Since this function receives no inputs, because it has no arguments, we have passed an empty list in this instance, or more precisely, an empty, anonymous struct (.{}) in the third argument of spawn().

        const std = @import("std");
         const stdout = std.io.getStdOut().writer();
        @@ -481,30 +481,30 @@ 

        Starting the work.Finishing the work.

        -

        Notice the use of try when calling the spawn() method. This means that this method can return an error in some circumstances. One circumstance in particular is when you attempt to create a new thread, when you have already created too much (i.e. you have exceeded the quota of concurrent threads in your system).

        +

        Notice the use of try when calling the spawn() method. This means that this method can return an error in some circumstances. One circumstance in particular is when you attempt to create a new thread, when you have already created too much (i.e., you have exceeded the quota of concurrent threads in your system).

        But, if the new thread is successfully created, the spawn() method returns a handler object (which is just an object of type Thread) to this new thread. You can use this handler object to effectively control all aspects of the thread.

        -

        When the thread get’s created, the function that you provided as input to spawn() get’s invoked (i.e. get’s called) to start the execution on this new thread. In other words, everytime you call spawn(), not only a new thread get’s created, but also, the “start work button” of this thread get’s automatically pressed. So the work being performed in this thread starts at the moment that the thread is created. This is similar to how pthread_create() from the pthreads library in C works, which also starts the execution at the moment that the thread get’s created.

        +

        When the thread gets created, the function that you provided as input to spawn() gets invoked (i.e., gets called) to start the execution on this new thread. In other words, every time you call spawn(), not only is a new thread created, but the “start work button” of this thread is also automatically pressed. So the work being performed in this thread starts as soon as the thread is created. This is similar to how pthread_create() from the pthreads library in C works, which also starts the execution as soon as the thread is created.

        16.4 Returning from a thread

        -

        We have learned on the previous section that the execution of the thread starts at the moment that the thread get’s created. Now, we will learn how to “join” or “detach” a thread in Zig. “Join” and “detach” are operations that control how the thread returns to the main thread, or, to the main process in our program.

        -

        We perform these operations by using the methods join() and detach() from the thread handler object. Every thread that you create can be marked as either joinable or detached (Linux man-pages 2024). You can turn a thread into a detached thread by calling the detach() method from the thread handler object. But if you call the join() method instead, then, this thread becomes a joinable thread.

        -

        A thread cannot be both joinable and detached. Which in general means that you cannot call both join() and detach() on the same thread. But a thread must be one of the two, meaning that, you should always call either join() or detach() over a thread. If you don’t call one of these two methods over your thread, you introduce undefined behaviour into your program, which is described at Section 16.9.2.

        +

        We have learned in the previous section that the execution of the thread starts as soon as the thread is created. Now, we will learn how to “join” or “detach” a thread in Zig. “Join” and “detach” are operations that control how the thread returns to the main thread, or to the main process in our program.

        +

        We perform these operations by using the methods join() and detach() from the thread handler object. Every thread that you create can be marked as either joinable or detached (Linux man-pages 2024). You can turn a thread into a detached thread by calling the detach() method from the thread handler object. But if you call the join() method instead, then this thread becomes a joinable thread.

        +

        A thread cannot be both joinable and detached. Which in general means that you cannot call both join() and detach() on the same thread. But a thread must be one of the two, meaning that, you should always call either join() or detach() over a thread. If you don’t call one of these two methods over your thread, you introduce undefined behaviour into your program, which is described in Section 16.9.2.

        Now, let’s describe what each of these two methods do to your thread.

        16.4.1 Joining a thread

        -

        When you join a thread, you are essentially saying: “Hey! Could you please wait for the thread to finish, before you continue with your execution?”. For example, if we comeback to our first and simpliest example of a thread in Zig, in that example we have created a single thread inside the main() function of our program, and just called join() over this thread at the end. This section of the code example is reproduced below.

        -

        Because we are joining this new thread inside the main()’s scope, it means that the execution of the main() function is temporarily stopped, to wait for the execution of the thread to finish. That is, the execution of main() stops temporarily at the line where join() get’s called, and it will continue only after the thread has finished its tasks.

        +

        When you join a thread, you are essentially saying: “Hey! Could you please wait for the thread to finish, before you continue with your execution?”. For example, if we come back to our first and simplest example of a thread in Zig, we created a single thread inside the main() function of our program and just called join() on this thread at the end. This section of the code example is reproduced below.

        +

        Because we are joining this new thread inside the main()’s scope, it means that the execution of the main() function is temporarily stopped, to wait for the execution of the thread to finish. That is, the execution of main() stops temporarily at the line where join() gets called, and it will continue only after the thread has finished its tasks.

        pub fn main() !void {
             const thread = try Thread.spawn(.{}, do_some_work, .{});
             thread.join();
         }
        -

        Because we have joined this new thread inside the main() scope, we have a guarantee that this new thread will finish before the end of the execution of main(). Because it is guaranteed that main() will wait for the thread to finish its tasks.

        +

        Because we have joined this new thread inside the main() scope, we have a guarantee that this new thread will finish before the end of the execution of main(). Because it’s guaranteed that main() will wait for the thread to finish its tasks.

        In the example above, there are no more expressions after the join() call. We just have the end of the main()’s scope, and, therefore, the execution of our program just ends after the thread finishes its tasks, since there is nothing more to do. But what if we had more stuff to do after the join call?

        To demonstrate this other possibility, consider the next example exposed below. Here, we create a print_id() function, that just receives an id as input, and prints it to stdout. In this example, we are creating two new threads, one after another. Then, we join the first thread, then, we wait for two whole seconds, then, at last, we join the second thread.

        -

        The idea behind this example is that the last join() call is executed only after the first thread finishes its task (i.e. the first join() call), and also, after the two seconds of delay. If you compile and run this example, you will notice that most messages are quickly printed to stdout, i.e. they appear almost instantly on your screen. However, the last message (“Joining thread 2”) takes around 2 seconds to appear in the screen.

        +

        The idea behind this example is that the last join() call is executed only after the first thread finishes its task (i.e., the first join() call), and the two-second delay. If you compile and run this example, you will notice that most messages are quickly printed to stdout, i.e., they appear almost instantly on your screen. However, the last message (“Joining thread 2”) takes around 2 seconds to appear on the screen.

        fn print_id(id: *const u8) !void {
             try stdout.print("Thread ID: {d}\n", .{id.*});
        @@ -527,18 +527,18 @@ 

        -

        This demonstrates that both threads finish their work (i.e. printing the IDs) very fast, before the two seconds of delay end. Because of that, the last join() call returns pretty much instantly. Because when this last join() call happens, the second thread have already finished its task.

        +

        This demonstrates that both threads finish their work (i.e., printing the IDs) very fast, before the two seconds of delay end. Because of that, the last join() call returns pretty much instantly. Because when this last join() call happens, the second thread has already finished its task.

        Now, if you compile and run this example, you will also notice that, in some cases, the messages intertwine with each other. In other words, you might see the message “Joining thread 1” inserted in the middle of the message “Thread 1”, or vice-versa. This happens because:

          -
        • the threads are executing basically at the same time as the main process of the program (i.e. the main() function).
        • +
        • the threads are executing basically at the same time as the main process of the program (i.e., the main() function).
        • the threads share the same stdout from the main process of the program, which means that the messages that the threads produce are sent to exact same place as the messages produced by the main process.
        -

        Both of these points were described previously at Section 16.1. So the messages might get intertwined because they are being produced and sent to the same stdout roughly at the same time. Anyway, when you call join() over a thread, the current process will wait for the thread to finish before it continues, and, when the thread does finishes its task, the resources associated with this thread are automatically freed, and, the current process continues with its execution.

        +

        Both of these points were described previously in Section 16.1. So the messages might get intertwined because they are being produced and sent to the same stdout roughly at the same time. Anyway, when you call join() over a thread, the current process will wait for the thread to finish before it continues, and, when the thread finishes its task, the resources associated with this thread are automatically freed, and the current process continues with its execution.

        16.4.2 Detaching a thread

        When you detach a thread, the resources associated with this thread are automatically released back to the system, without the need for another thread to join with this terminated thread.

        -

        In other words, when you call detach() over a thread it’s like when your children becomes adults, i.e. they become independent from you. A detached thread frees itself, and when this thread finishes its tasks, it does not report the results back to you. Thus, you normally mark a thread as detached when you don’t need to use the return value of the thread, or, when you don’t care about when exactly the thread finishes its job, i.e. the thread solves everything by itself.

        +

        In other words, when you call detach() on a thread it’s like when your children become adults, i.e., they become independent from you. A detached thread frees itself, and when this thread finishes its tasks, it does not report the results back to you. Thus, you normally mark a thread as detached when you don’t need to use the return value of the thread, or when you don’t care about when exactly the thread finishes its job, i.e., the thread solves everything by itself.

        Take the code example below. We create a new thread, detach it, and then, we just print a final message before we end our program. We use the same print_id() function that we have used over the previous examples.

        fn print_id(id: *const u8) !void {
        @@ -553,15 +553,15 @@ 

        }

        Finish main
        -

        Now, if you look closely at the output of this code example, you will notice that only the final message in main was printed to the console. The message that was supposed to be printed by print_id() did not appear in the console. Why? Is because the main process of our program has finished first, before the thread was able to say anything.

        -

        And that is perfectly ok behaviour, because the thread was detached, so, it was able to free itself, without the need to wait for the main process. If you ask main to sleep (or “wait”) for some extra nanoseconds, before it ends, you will likely see the message printed by print_id(), because you give enough time for the thread to finish before the main process ends.

        +

        Now, if you look closely at the output of this code example, you will notice that only the final message in main was printed to the console. The message that was supposed to be printed by print_id() did not appear in the console. Why? It’s because the main process of our program has finished first, before the thread was able to say anything.

        +

        And that is perfectly ok behaviour, because the thread was detached, so it was able to free itself, without the need to wait for the main process. If you ask main to sleep (or “wait”) for some extra nanoseconds, before it ends, you will likely see the message printed by print_id(), because you give enough time for the thread to finish before the main process ends.

        16.5 Thread pools

        -

        Thread pools is a very popular programming pattern, which is used especially on servers and daemons processes. A thread pool is just a set of threads, or, a “pool” of threads. Many programmers like to use this pattern, because it makes easier to manage and use multiple threads in your program, instead of manually creating the threads when you need them.

        +

        Thread pools is a very popular programming pattern, which is used especially on servers and daemons processes. A thread pool is just a set of threads, or a “pool” of threads. Many programmers like to use this pattern because it makes it easier to manage and use multiple threads in your program, instead of manually creating the threads when you need them.

        Also, using thread pools might increase performance as well in your program, especially if your program is constantly creating threads to perform short-lived tasks. In such instance, a thread pool might cause an increase in performance because you do not have be constantly creating and destroying threads all the time, so you don’t face a lot of the overhead involved in this constant process of creating and destroying threads.

        -

        The main idea behind a thread pool is to have a set of threads already created and ready to perform tasks at all times. You create a set of threads at the moment that your program starts, and keep these threads alive while your program runs. Each of these threads will be either performing a task, or, waiting for a task to be assigned. Every time a new task emerges in your program, this task is added to a “queue of tasks”, and the moment that a thread becomes available and ready to perform a new task, this thread takes the next task from the “queue of tasks”, and it simply performs the task.

        +

        The main idea behind a thread pool is to have a set of threads already created and ready to perform tasks at all times. You create a set of threads at the moment that your program starts, and keep these threads alive while your program runs. Each of these threads will be either performing a task, or waiting for a task to be assigned. Every time a new task emerges in your program, this task is added to a “queue of tasks”, and the moment that a thread becomes available and ready to perform a new task, this thread takes the next task from the “queue of tasks”, and it simply performs the task.

        The Zig Standard Library offers a thread pool implementation on the std.Thread.Pool struct. You create a new instance of a Pool object by providing a Pool.Options object as input to the init() method of this struct. A Pool.Options object, is a struct object that contains configurations for the pool of threads. The most important settings in this struct object are the members n_jobs and allocator. As the name suggests, the member allocator should receive an allocator object, while the member n_jobs specifies the number of threads to be created and maintained in this pool.

        Consider the example exposed below, that demonstrates how can we create a new thread pool object. Here, we create a Pool.Options object that contains a general purpose allocator object, and also, the n_jobs member was set to 4, which means that the thread pool will create and use 4 threads.

        Also notice that the pool object was initially set to undefined. This allow us to initially declare the thread pool object, but not properly instantiate the underlying memory of the object. You have to initially declare your thread pool object by using undefined like this, because the init() method of Pool needs to have an initial pointer to properly instantiate the object.

        @@ -577,13 +577,13 @@

        .allocator = allocator, }; var pool: Pool = undefined; - _ = try pool.init(opt); + try pool.init(opt); defer pool.deinit(); }

        Now that we know how to create Pool objects, we have to understand how to assign tasks to be executed by the threads in this pool object. To assign a task to be performed by a thread, we need to call the spawn() method from the thread pool object.

        -

        This spawn() method works identical to the spawn() method from the Thread object. The method have almost the same arguments as the previous one, more precisely, we don’t have to provide a SpawnConfig object in this case. But instead of creating a new thread, this spawn() method from the thread pool object just register a new task in the internal “queue of tasks” to be performed, and any available thread in the pool will get this task, and it will simply perform the task.

        -

        In the example below, we are using our previous print_id() function once again. But you may notice that the print_id() function is a little different this time, because now we are using catch instead of try in the print() call. Currently, the Pool struct only supports functions that don’t return errors as tasks. Thus, when assigning tasks to threads in a thread pool, is essential to use functions that don’t return errors. That is why we are using catch here, so that the print_id() function don’t return an error.

        +

        This spawn() method works identical to the spawn() method from the Thread object. The method has almost the same arguments as the previous one, more precisely, we don’t have to provide a SpawnConfig object in this case. But instead of creating a new thread, this spawn() method from the thread pool object just registers a new task in the internal “queue of tasks” to be performed, and any available thread in the pool will get this task, and it will simply perform the task.

        +

        In the example below, we are using our previous print_id() function once again. But you may notice that the print_id() function is a little different this time, because now we are using catch instead of try in the print() call. Currently, the Pool struct only supports functions that don’t return errors as tasks. Thus, when assigning tasks to threads in a thread pool, it is essential to use functions that don’t return errors. That is why we are using catch here, so that the print_id() function don’t return an error.

        fn print_id(id: *const u8) void {
             _ = stdout.print("Thread ID: {d}\n", .{id.*})
        @@ -594,7 +594,7 @@ 

        try pool.spawn(print_id, .{&id1}); try pool.spawn(print_id, .{&id2});

        -

        This limitation should probably not exist, and, in fact, it is already on the radar of the Zig team to fix this issue, and it is being tracked on an open issue1. So, if you do need to provide a function that might return an error as the task to be performed by the threads in the thread pool, then, you are either limited to:

        +

        This limitation should probably not exist, and, in fact, it’s already on the radar of the Zig team to fix this issue, and it’s being tracked in an open issue1. So, if you do need to provide a function that might return an error as the task to be performed by the threads in the thread pool, then, you are either limited to:

        • implementing your own thread pool that does not have this limitation.
        • wait for the Zig team to actually fix this issue.
        • @@ -603,14 +603,14 @@

          16.6 Mutexes

          Mutexes are a classic component of every thread library. In essence, a mutex is a Mutually Exclusive Flag, and this flag acts like a type of “lock”, or as a gate keeper to a particular section of your code. Mutexes are related to thread synchronization, more specifically, they prevent you from having some classic race conditions in your program, and, therefore, major bugs and undefined behaviour that are usually difficult to track and understand.

          -

          The main idea behind a mutex is to help us to control the execution of a particular section of the code, and to prevent two or more threads from executing this particular section of the code at the same time. Many programmers like to compare a mutex to a bathroom door (which usually have a lock). When a thread locks its own mutex object, it is like if the bathroom door was locked, and, therefore, the other people (in this case, the other threads) that wants to use the same bathroom at the same time have to be patient, and simply wait for the other person (or the other thread) to unlock the door and get out of the bathroom.

          -

          Some other programmers also like to explain mutexes by using the analogy of “each person will have their turn to speak”. This is the analogy used on the Multithreading Code video from the Computerphile project2. Imagine if you are in a conversation circle. There is a moderator in this circle, which is the person that decides who have the right to speak at that particular moment. The moderator gives a green card (or some sort of an authorization card) to the person that is going to speak, and, as a result, everyone else must be silent and hear this person that has the green card. When the person finishes talking, it gives the green card back to the moderator, and the moderator decides who is going to talk next, and delivers the green card to that person. And the cycle goes on like this.

          -

          A mutex acts like the moderator in this conversation circle. The mutex authorizes one single thread to execute a specific section of the code, and it also blocks the other threads from executing this same section of the code. If these other threads want to execute this same piece of the code, they are forced to wait for the the authorized thread to finish first. When the authorized thread finishes executing this code, the mutex authorizes the next thread to execute this code, and the other threads are still blocked. Therefore, a mutex is like a moderator that does a “each thread will have their turn to execute this section of the code” type of control.

          +

          The main idea behind a mutex is to help us to control the execution of a particular section of the code, and to prevent two or more threads from executing this particular section of the code at the same time. Many programmers like to compare a mutex to a bathroom door (which typically has a lock). When a thread locks its own mutex object, it’s like if the bathroom door was locked. Therefore, other people (in this case, other threads) who want to use the same bathroom at the same time must be patient and simply wait for the current occupant (or thread) to unlock the door and get out of the bathroom.

          +

          Some other programmers also like to explain mutexes by using the analogy of “each person will have their turn to speak”. This is the analogy used in the Multithreading Code video from the Computerphile project2. Imagine if you are in a conversation circle. There is a moderator in this circle, which is the person that decides who has the right to speak at that particular moment. The moderator gives a green card (or some sort of an authorization card) to the person that is going to speak, and, as a result, everyone else must be silent and hear this person that has the green card. When the person finishes talking, they give the green card back to the moderator, and the moderator decides who is going to talk next, and delivers the green card to that person. And the cycle goes on like this.

          +

          A mutex acts like the moderator in this conversation circle. The mutex authorizes one single thread to execute a specific section of the code, and it also blocks the other threads from executing this same section of the code. If these other threads want to execute this same piece of the code, they are forced to wait for the the authorized thread to finish first. When the authorized thread finishes executing this code, the mutex authorizes the next thread to execute this code, while the remaining threads remain blocked. Therefore, a mutex is like a moderator that does a “each thread will have their turn to execute this section of the code” type of control.

          Mutexes are especially used to prevent data race problems from happening. A data race problem happens when two or more threads are trying to read from or write to the same shared object at the same time. So, when you have an object that is shared will all threads, and, you want to avoid two or more threads from accessing this same object at the same time, you can use a mutex to lock the part of the code that access this specific object. When a thread tries to run this code that is locked by a mutex, this thread stops its execution, and patiently waits for this section of the codebase to be unlocked to continue.

          -

          Notice that mutexes are normally used to lock areas of the codebase that access/modify data that is shared with all threads, i.e. objects that are either stored in the global data section, or, in the heap space of your program. So mutexes are not normally used on areas of the codebase that access/modify objects that are local to the thread.

          +

          Notice that mutexes are normally used to lock areas of the codebase that access/modify data that is shared with all threads, i.e., objects that are either stored in the global data section, or in the heap space of your program. So mutexes are not normally used on areas of the codebase that access/modify objects that are local to the thread.

          16.6.1 Critical section

          -

          Critical section is a concept commonly associated with mutexes and thread synchronization. In essence, a critical section is the section of the program that a thread access/modify a shared resource (i.e. an object, a file descriptor, something that all threads have access to). In other words, a critical section is the section of the program where race conditions might happen, and, therefore, where undefined behaviour can be introduced into the program.

          +

          Critical section is a concept commonly associated with mutexes and thread synchronization. In essence, a critical section is the section of the program that a thread access/modify a shared resource (i.e., an object, a file descriptor, something that all threads have access to). In other words, a critical section is the section of the program where race conditions might happen, and, therefore, where undefined behaviour can be introduced into the program.

          When we use mutexes in our program, the critical section defines the area of the codebase that we want to lock. So we normally lock the mutex object at the beginning of the critical section, and then, we unlock it at the end of the critical section. The two bullet points exposed below comes from the “Critical Section” article from GeekFromGeeks, and they summarise well the role that a critical section plays in the thread synchronization problem (Geeks for Geeks 2024).

          1. The critical section must be executed as an atomic operation, which means that once one thread or process has entered the critical section, all other threads or processes must wait until the executing thread or process exits the critical section. The purpose of synchronization mechanisms is to ensure that only one thread or process can execute the critical section at a time.
          2. @@ -619,19 +619,19 @@

          16.6.2 Atomic operations

          -

          You will also see the term “atomic operation” a lot when reading about threads, race conditions and mutexes. In summary, an operation is categorized as “atomic”, when there is no way to happen a context switch in the middle of this operation. In other words, this operation is always done from beginning to end, without interruptions of another process or operation in the middle of its execution phase.

          -

          Not many operations today are atomic. But why atomic operations matters here? Is because data races (which is a type of a race condition) cannot happen on operations that are atomic. So if a particular line in your code performs an atomic operation, then, this line will never suffer from a data race problem. Therefore, programmers sometimes use an atomic operation to protect themselves from data race problems in their code.

          -

          When you have an operation that is compiled into just one single assembly instruction, this operation might be atomic, because it is just one assembly instruction. But this is not guaranteed. This is usually true for old CPU architectures (such as x86). But nowadays, most assembly instructions in modern CPU architectures turn into multiple micro-tasks, which inherently makes the operation not atomic anymore, even though it has just one single assembly instruction.

          -

          The Zig Standard Library offers some atomic functionality at the std.atomic module. In this module, you will find a public and generic function called Value(). With this function we create an “atomic object”, which is a value that contains some native atomic operations, most notably, a load() and a fetchAdd() operation. If you have experience with multithreading in C++, you probably have recognized this pattern. So yes, this generic “atomic object” in Zig is essentially identical to the template struct std::atomic from the C++ Standard Library. Is important to emphasize that only primitive data types (i.e. the types presented at Section 1.5) are supported by these atomic operations in Zig.

          +

          You will also see the term “atomic operation” a lot when reading about threads, race conditions and mutexes. In summary, an operation is categorized as “atomic” when a context switch cannot occur in the middle of the operation. In other words, this operation is always done from beginning to end, without interruptions of another process or operation in the middle of its execution phase.

          +

          Not many operations today are atomic. But why do atomic operations matter here? It’s because data races (which is a type of a race condition) cannot happen on operations that are atomic. So if a particular line in your code performs an atomic operation, then this line will never suffer from a data race problem. Therefore, programmers sometimes use an atomic operation to protect themselves from data race problems in their code.

          +

          When you have an operation that is compiled into just one single assembly instruction, this operation might be atomic, because it’s just one assembly instruction. But this is not guaranteed. This is usually true for old CPU architectures (such as x86). But nowadays, most assembly instructions in modern CPU architectures are broken down into multiple micro-tasks, which inherently makes the operation non-atomic, even if it consists of a single assembly instruction.

          +

          The Zig Standard Library offers some atomic functionality in the std.atomic module. In this module, you will find a public and generic function called Value(). With this function we create an “atomic object”, which is a value that contains some native atomic operations, most notably, a load() and a fetchAdd() operation. If you have experience with multithreading in C++, you probably have recognized this pattern. So yes, this generic “atomic object” in Zig is essentially identical to the template struct std::atomic from the C++ Standard Library. It’s important to emphasize that only primitive data types (i.e., the types presented in Section 1.5) are supported by these atomic operations in Zig.

          16.6.3 Data races and race conditions

          -

          To understand why mutexes are used, we need to understand better the problem that they seek to solve, which can be summarized into data races problems. A data race problem is a type of a race condition, which happens when one thread is accessing a particular memory location (i.e. a particular shared object) at the same time that another thread is trying to write/save new data into this same memory location (i.e. the same shared object).

          -

          We can simply define a race condition as any type of bug in your program that is based on a “who get’s there first” problem. A data race problem is a type of a race condition, because it occurs when two or more parties are trying to read and write into the same memory location at the same time, and, therefore, the end result of this operation depends completely on who get’s to this memory location first. As consequence, a program that have a data race problem will likely produce a different result each time that we execute it.

          -

          Thus, race conditions produce undefined behaviour and unpredictability because the program produces a different answer in each time that a different person get’s to the target location first than the others. And we have no easy way to either predict or control who is getting to this target location first. In other words, in each execution of your program, you get a different answer, because a different person, or, a different function, or, a different part of the code is finishing its tasks first than the others.

          +

          To understand why mutexes are used, we need to understand better the problem that they seek to solve, which can be summarized into data race problems. A data race problem is a type of a race condition, which happens when one thread is accessing a particular memory location (i.e., a particular shared object) at the same time that another thread is trying to write/save new data into this same memory location (i.e., the same shared object).

          +

          We can simply define a race condition as any type of bug in your program that is based on a “who gets there first” problem. A data race problem is a type of a race condition, because it occurs when two or more parties are trying to read and write into the same memory location at the same time, and, therefore, the end result of this operation depends completely on who gets to this memory location first. As a consequence, a program that has a data race problem will likely produce a different result each time that we execute it.

          +

          Thus, race conditions produce undefined behaviour and unpredictability because the program produces a different answer each time a different person gets to the target location before the others. And, we have no easy way to either predict or control who is getting to this target location first. In other words, each time your program runs, you may get a different answer because a different person, function, or part of the code finishes its tasks before the others.

          As an example, consider the code snippet exposed below. In this example, we create a global counter variable, and we also create an increment() function, whose job is to just increment this global counter variable in a for loop.

          Since the for loop iterates 1 hundred thousand times, and, we create two separate threads in this code example, what number do you expect to see in the final message printed to stdout? The answer should be 2 hundred thousand. Right? Well, in theory, this program was supposed to print 2 hundred thousand at the end, but in practice, every time that I execute this program I get a different answer.

          -

          In the example exposed below, you can see that this time the end result was 117254, instead of the expected 200000. The second time I have executed this program, I got the number 108592 as result. So the end result of this program is varying, but it never gets to the expected 200000 that we want.

          +

          In the example exposed below, you can see that this time the end result was 117254, instead of the expected 200000. The second time I executed this program, I got the number 108592 as the result. So the end result of this program is varying, but it never gets to the expected 200000 that we want.

          // Global counter variable
           var counter: usize = 0;
          @@ -651,15 +651,15 @@ 

          }

          Couter value: 117254
          -

          Why this is happening? The answer is: because this program contains a data race problem. This program would print the correct number 200000, if, and only if the first thread finishes its tasks before the second thread starts to execute. But that is very unlikely to happen. Because the process of creating the thread is too fast, and therefore, both threads starts to execute roughly at the same time. If you change this code to add some nanoseconds of sleep between the first and the second calls to spawn(), you will increase the chances of the program producing the “correct result”.

          -

          So the data race problem happens, because both threads are reading and writing to the same memory location at roughly the same time. In this example, each thread is essentially performing three basic operations at each iteration of the for loop, which are:

          +

          Why this is happening? The answer is: because this program contains a data race problem. This program would print the correct number 200000 if and only if the first thread finishes its tasks before the second thread starts to execute. But that is very unlikely to happen. Because the process of creating the thread is too fast, and therefore, both threads start to execute roughly at the same time. If you change this code to add some nanoseconds of sleep between the first and the second calls to spawn(), you will increase the chances of the program producing the “correct result”.

          +

          So the data race problem happens because both threads are reading and writing to the same memory location at roughly the same time. In this example, each thread is essentially performing three basic operations at each iteration of the for loop, which are:

          1. reading the current value of count.
          2. incrementing this value by 1.
          3. writing the result back into count.
          -

          Ideally, a thread B should read the value of count, only after the other thread A has finished writing the incremented value back into the count object. Therefore, in the ideal scenario, which is demonstrated at Table 16.1, the threads should work in sync with each other. But the reality is that these threads are out of sync, and because of that, they suffer from a data race problem, which is demonstrated at Table 16.2.

          -

          Notice that, in the data race scenario (Table 16.2), the read performed by a thread B happens before the write operation of thread A, and that ultimately leads to wrong results at the end of the program. Because when the thread B reads the value from the count variable, the thread A is still processing the initial value from count, and it did not write the new and incremented value into count yet. So what happens is that thread B ends up reading the same initial value (the “old” value) from count, instead of reading the new and incremented version of this value that would be calculated by thread A.

          +

          Ideally, a thread B should read the value of count, only after the other thread A has finished writing the incremented value back into the count object. Therefore, in the ideal scenario, which is demonstrated in Table 16.1, the threads should work in sync with each other. But the reality is that these threads are out of sync, and because of that, they suffer from a data race problem, which is demonstrated in Table 16.2.

          +

          Notice that, in the data race scenario (Table 16.2), the read performed by a thread B happens before the write operation of thread A, and that ultimately leads to wrong results at the end of the program. Because when thread B reads the value of the count variable, thread A is still processing the initial value from count, and has not yet written the new, incremented value back to count. As a result, thread B ends up reading the same initial (or “old”) value from count instead of the updated, incremented value that thread A would have written.

          @@ -760,13 +760,13 @@

          Section 16.6.2. Remember, atomic operations are operations that the CPU executes from beginning to end, without interruptions from other threads or processes. So, the scenario exposed at Table 16.1 do not suffer from a data race, because the operations performed by thread A are not interrupted in the middle by the operations from thread B.

          -

          If we also think about the discussion of critical section from Section 16.6.1, we can identify the section that representes the critical section of the program, which is the section that is vulnerable to data race conditions. In this example, the critical section of the program is the line where we increment the counter variable (counter += 1). So, ideally, we want to use a mutex, and lock right before this line, and then, unlock right after this line.

          +

          If you think about these diagrams exposed in form of tables, you will notice that they relate back to our discussion of atomic operations in Section 16.6.2. Remember, atomic operations are operations that the CPU executes from beginning to end, without interruptions from other threads or processes. So, the scenario exposed in Table 16.1 does not suffer from a data race, because the operations performed by thread A are not interrupted in the middle by the operations from thread B.

          +

          If we also think about the discussion of critical section from Section 16.6.1, we can identify the section that representes the critical section of the program, which is the section that is vulnerable to data race conditions. In this example, the critical section of the program is the line where we increment the counter variable (counter += 1). So, ideally, we want to use a mutex, and lock right before this line, and then unlock right after this line.

          16.6.4 Using mutexes in Zig

          -

          Now that we know the problem that mutexes seek to solve, we can learn how to use them in Zig. Mutexes in Zig are available through the std.Thread.Mutex struct from the Zig Standard Library. If we take the same code example from the previous example, and improve it with mutexes, to solve our data race problem, we get the code example exposed below.

          -

          Notice that we had this time to alter the increment() function to receive a pointer to the Mutex object as input. All that we need to do, to make this program safe against data race problems, is to call the lock() method at the beginning of the critical section, and then, call unlock() at the end of the critical section. Notice that the output of this program is now the correct number of 200000.

          +

          Now that we know the problem that mutexes seek to solve, we can learn how to use them in Zig. Mutexes in Zig are available through the std.Thread.Mutex struct from the Zig Standard Library. If we take the same code from the previous example, and improve it with mutexes, to solve our data race problem, we get the code example below.

          +

          Notice that this time, we had to alter the increment() function to receive a pointer to the Mutex object as input. All that we need to do, to make this program safe against data race problems, is to call the lock() method at the beginning of the critical section, and then, call unlock() at the end of the critical section. Notice that the output of this program is now the correct number of 200000.

          const std = @import("std");
           const stdout = std.io.getStdOut().writer();
          @@ -797,31 +797,31 @@ 

          16.7 Read/Write locks

          -

          Mutexes are normally used when is always not safe to have two or more threads running the same piece of code at the same time. In contrast, read/write locks are normally used in situations where you have a mixture of scenarios, i.e. there are some pieces of the codebase that are safe to run in parallel, and other pieces that are not safe.

          -

          For example, suppose that you have multiple threads that uses the same shared file in the filesystem to store some configurations, or, statistics. If two or more threads try to read the data from this same file at the same time, nothing bad happens. So this part of the codebase is perfectly safe to be executed in parallel, with multiple threads reading the same file at the same time.

          -

          However, if two or more threads try to write data into this same file at the same time, then, we cause some race conditions problems. So this other part of the codebase is not safe to be executed in parallel. More specifically, a thread might end up writing data in the middle of the data written by the other thread. This process of two or more threads writing to the same location, might lead to data corruption. This specific situation is usually called of a torn write.

          -

          Thus, what we can extract from this example is that there is certain types of operations that causes a race condition, but there are also, other types of operations that do not cause a race condition problem. You could also say that, there are types of operations that are susceptible to race condition problems, and there are other types of operations that are not.

          -

          A read/write lock is a type of lock that acknowledges the existance of this specific scenario, and you can use this type of lock to control which parts of the codebase are safe to run in parallel, and which parts are not safe.

          +

          Mutexes are normally used when it’s not always safe for two or more threads running the same piece of code at the same time. In contrast, read/write locks are normally used in situations where you have a mixture of scenarios, i.e., there are some pieces of the codebase that are safe to run in parallel, and other pieces that are not safe.

          +

          For example, suppose that you have multiple threads that uses the same shared file in the filesystem to store some configurations, or statistics. If two or more threads try to read the data from this same file at the same time, nothing bad happens. So this part of the codebase is perfectly safe to be executed in parallel, with multiple threads reading the same file at the same time.

          +

          However, if two or more threads try to write data into this same file at the same time, then we cause some race condition problems. So this other part of the codebase is not safe to be executed in parallel. More specifically, a thread might end up writing data in the middle of the data written by the other thread. This process of two or more threads writing to the same location might lead to data corruption. This specific situation is usually called a torn write.

          +

          Thus, what we can extract from this example is that there are certain types of operations that cause a race condition, but there are also other types of operations that do not cause a race condition problem. You could also say that there are types of operations that are susceptible to race condition problems, and there are other types of operations that are not.

          +

          A read/write lock is a type of lock that acknowledges the existence of this specific scenario, and you can use this type of lock to control which parts of the codebase are safe to run in parallel and which parts are not.

          16.7.1 Exclusive lock vs shared lock

          -

          Therefore, a read/write lock is a little different from a mutex. Because a mutex is always an exclusive lock, meaning that, only one thread is allowed to execute at all times. With an exclusive lock, the other threads are always “excluded”, i.e. they are always blocked from executing. But in a read/write lock, the other threads might be authorized to run at the same time, depending on the type of lock that they acquire.

          +

          Therefore, a read/write lock is a little different from a mutex. Because a mutex is always an exclusive lock, meaning that, only one thread is allowed to execute at all times. With an exclusive lock, the other threads are always “excluded”, i.e., they are always blocked from executing. But in a read/write lock, the other threads might be authorized to run at the same time, depending on the type of lock that they acquire.

          We have two types of locks in a read/write lock, which are: an exclusive lock and a shared lock. An exclusive lock works exactly the same as a mutex, while a shared lock is a lock that does not block the other threads from running at the same time. In the pthreads C library, read/write locks are available through the pthread_rwlock_t C struct. With this C struct, you can create:

          • a “write lock”, which corresponds to an exclusive lock.
          • a “read lock”, which corresponds to a shared lock.

          The terminology might be a little different compared to Zig. But the meaning is still the same. Therefore, just remember this relationship, write locks are exclusive locks, while read locks are shared locks.

          -

          When a thread tries to acquire a read lock (i.e. a shared lock), this thread get’s the shared lock if, and only if another thread does not currently holds a write lock (i.e. an exclusive lock), and also, if there are no other threads that are already in the queue, waiting for their turn to acquire a write lock. In other words, the thread in the queue have attempted to get a write lock earlier, but this thread was blocked because there was another thread running that already had a write lock. As consequence, this thread is on the queue to get a write lock, and it’s currently waiting for the other thread with a write lock to finish its execution.

          -

          When a thread tries to acquire a read lock, but it fails in acquiring this read lock, either because there is a thread with a write lock already running, or, because there is a thread in the queue to get a write lock, the execution of this thread is instantly blocked, i.e. paused. This thread will indefinitely attempt to get the read lock, and its execution will be unblocked (or unpaused) only after this thread successfully acquires the read lock.

          -

          If you think deeply about this dynamic between read locks versus write locks, you might notice that a read lock is basically a safety mechanism. More specifically, it is a way for us to allow a particular thread to run together with the other threads, only when it’s safe to. In other words, if there is currently a thread with a write lock running, then, it is very likely not safe for the thread that is trying to acquire the read lock to run now. As consequence, the read lock protects this thread from running into dangerous waters, and patiently waits for the “write lock” thread to finishes its tasks before it continues.

          -

          On the other hand, if there are only “read lock” (i.e. “shared lock”) threads currently running (i.e. not a single “write lock” thread currently exists), then, is perfectly safe for this thread that is acquiring the read lock to run in parallel with the other threads. As a result, the read lock just allows for this thread to run together with the other threads.

          +

          When a thread tries to acquire a read lock (i.e., a shared lock), this thread gets the shared lock if and only if another thread does not currently hold a write lock (i.e., an exclusive lock), and also if there are no other threads already in the queue, waiting for their turn to acquire a write lock. In other words, the thread in the queue has attempted to get a write lock earlier, but this thread was blocked because there was another thread running that already had a write lock. As a consequence, this thread is in the queue to get a write lock, and it’s currently waiting for the other thread with a write lock to finish its execution.

          +

          When a thread tries to acquire a read lock, but it fails in acquiring this read lock, either because there is a thread with a write lock already running, or because there is a thread in the queue to get a write lock, the execution of this thread is instantly blocked, i.e., paused. This thread will indefinitely attempt to get the read lock, and its execution will be unblocked (or unpaused) only after this thread successfully acquires the read lock.

          +

          If you think deeply about this dynamic between read locks versus write locks, you might notice that a read lock is basically a safety mechanism. More specifically, it’s a way for us to allow a particular thread to run together with the other threads only when it’s safe to. In other words, if there is currently a thread with a write lock running, then it’s very likely not safe for the thread that is trying to acquire the read lock to run now. As a consequence, the read lock protects this thread from running into dangerous waters, and patiently waits for the “write lock” thread to finishes its tasks before it continues.

          +

          On the other hand, if there are only “read lock” (i.e., “shared lock”) threads currently running (i.e., not a single “write lock” thread currently exists), then it is perfectly safe for this thread that is acquiring the read lock to run in parallel with the other threads. As a result, the read lock just allows for this thread to run together with the other threads.

          Thus, by using read locks (shared locks) in conjunction with write locks (exclusive locks), we can control which regions or sections of our multithreaded code is safe to have parallelism, and which sections are not safe to have parallelism.

          16.7.2 Using read/write locks in Zig

          -

          The Zig Standard Library supports read/write locks through the std.Thread.RwLock module. If you want to a particular thread to acquire a shared lock (i.e. a read lock), you should call the lockShared() method from the RwLock object. But, if you want for this thread to acquire an exclusive lock (i.e. a write lock) instead, then, you should call the lock() method from the RwLock object.

          +

          The Zig Standard Library supports read/write locks through the std.Thread.RwLock module. If you want a particular thread to acquire a shared lock (i.e., a read lock), you should call the lockShared() method from the RwLock object. But, if you want this thread to acquire an exclusive lock (i.e., a write lock) instead, then you should call the lock() method from the RwLock object.

          As with mutexes, we also have to unlock the shared or exclusive locks that we acquire through a read/write lock object, once we are at the end of our “critical section”. If you have acquired an exclusive lock, then, you unlock this exclusive lock by calling the unlock() method from the read/write lock object. In contrast, if you have acquired a shared lock instead, then, call unlockShared() to unlock this shared lock.

          -

          As a simple example, the snippet exposed below creates three separate threads responsible for reading the current value in a counter object, and it also creates another thread, responsible for writing new data into the counter object (incrementing it, more specifically).

          +

          As a simple example, the snippet below creates three separate threads responsible for reading the current value in a counter object, and it also creates another thread responsible for writing new data into the counter object (incrementing it, more specifically).

          var counter: u32 = 0;
           fn reader(lock: *RwLock) !void {
          @@ -859,9 +859,9 @@ 

          16.8 Yielding a thread

          -

          The Thread struct supports yielding through the yield() method. Yielding a thread means that the execution of the thread is temporarily stopped, and the thread comes back to the end of the queue of priority of the scheduler from your operating system.

          +

          The Thread struct supports yielding through the yield() method. Yielding a thread means that the execution of the thread is temporarily stopped, and it moves to the end of the priority queue managed by the scheduler of your operating system.

          That is, when you yield a thread, you are essentially saying the following to your OS: “Hey! Could you please stop executing this thread for now, and comeback to continue it later?”. You could also interpret this yield operation as: “Could you please deprioritize this thread, to focus on doing other things instead?”. So this yield operation is also a way for you to stop a particular thread, so that you can work and prioritize other threads instead.

          -

          Is important to say that, yielding a thread is a “not so common” thread operation these days. In other words, not many programmers use yielding in production, simply because is hard to use this operation and make it work properly, and also, there are better alternatives. Most programmers prefer to use join() instead. In fact, most of the times, when you see somebody using this “yield” operation in some code example, they are mostly using it to help them debug race conditions in their applications. That is, this “yield” operation is mostly used as a debug tool nowadays.

          +

          It’s important to say that, yielding a thread is a “not so common” thread operation these days. In other words, not many programmers use yielding in production, simply because it’s hard to use this operation and make it work properly, and also, there are better alternatives. Most programmers prefer to use join() instead. In fact, most of the time, when you see someone using this “yield” operation in some code example, they are usually doing so to help debug race conditions in their applications. That is, this “yield” operation is mostly used as a debug tool nowadays.

          Anyway, if you want to yield a thread, just call the yield() method from it, like this:

          thread.yield();
          @@ -874,8 +874,8 @@

          A deadlock occurs when two or more threads are blocked forever, waiting for each other to release a resource. This usually happens when multiple locks are involved, and the order of acquiring them is not well managed.

          The code example below demonstrates a deadlock situation. We have two different threads that execute two different functions (work1() and work2()) in this example. And we also have two separate mutexes. If you compile and run this code example, you will notice that the program just runs indefinitely, without ending.

          When we look into the first thread, which executes the work1() function, we can notice that this function acquires the mut1 lock first. Because this is the first operation that is executed inside this thread, which is the first thread created in the program. After that, the function sleeps for 1 second, to simulate some type of work, and then, the function tries to acquire the mut2 lock.

          -

          On the other hand, when we look into the second thread, which executes the work2() function, we can see that this function acquires the mut2 lock first. Because when this thread get’s created and it tries to acquire this mut2 lock, the first thread is still sleeping on that “sleep 1 second” line. After acquiring mut2, the work2() function also sleeps for 1 second, to simulate some type of work, and then, the function tries to acquire the mut1 lock.

          -

          This creates a deadlock situation, because after the “sleep for 1 second” line in both threads, the thread 1 is trying to acquire the mut2 lock, but this lock is currently being used by thread 2. However, at this moment, the thread 2 is also trying to acquire the mut1 lock, which is currently being used by thread 1. Therefore, both threads end up waiting for ever. Waiting for their peer to free the lock that they want to acquire.

          +

          On the other hand, when we look into the second thread, which executes the work2() function, we can see that this function acquires the mut2 lock first. Because when this thread gets created and it tries to acquire this mut2 lock, the first thread is still sleeping on that “sleep 1 second” line. After acquiring mut2, the work2() function also sleeps for 1 second, to simulate some type of work, and then the function tries to acquire the mut1 lock.

          +

          This creates a deadlock situation, because after the “sleep for 1 second” line in both threads, thread 1 is trying to acquire the mut2 lock, but this lock is currently being used by thread 2. However, at this moment, thread 2 is also trying to acquire the mut1 lock, which is currently being used by thread 1. Therefore, both threads end up waiting for ever. Waiting for their peer to free the lock that they want to acquire.

          var mut1: Mutex = .{}; var mut2: Mutex = .{};
           fn work1() !void {
          @@ -904,14 +904,14 @@ 

          16.9.2 Not calling join() or detach()

          -

          When you do not call either join() or detach() over a thread, then, this thread becomes a “zombie thread”, because it does not have a clear “return point”. You could also interpret this as: “nobody is properly responsible for managing the thread”. When we don’t establish if a thread is either joinable or detached, nobody becomes responsible for dealing with the return value of this thread, and also, nobody becomes responsible for clearing (or freeing) the resources associated with this thread.

          -

          You don’t want to be in this situation, so remember to always use join() or detach() on the threads that you create. When you don’t use one of these methods, we lose control over the thread, and its resources are never freed (i.e. you have leaked resources in the system).

          +

          When you do not call either join() or detach() over a thread, then this thread becomes a “zombie thread”, because it does not have a clear “return point”. You could also interpret this as: “nobody is properly responsible for managing the thread”. When we don’t establish if a thread is either joinable or detached, nobody becomes responsible for dealing with the return value of this thread, and also, nobody becomes responsible for clearing (or freeing) the resources associated with this thread.

          +

          You don’t want to be in this situation, so remember to always use join() or detach() on the threads that you create. When you don’t use one of these methods, we lose control over the thread, and its resources are never freed (i.e., you have leaked resources in the system).

          16.9.3 Cancelling or killing a particular thread

          -

          When we think about the pthreads C library, there is a possible way to asynchronously kill or cancel a thread, which is by sending a SIGTERM signal to the thread through the pthread_kill() function. But canceling a thread like this is bad. Is dangerously bad. As consequence, the Zig implementation of threads does not have a similar function, or, a similar way to asynchronously cancel or kill a thread.

          -

          Therefore, if you want to cancel a thread in the middle of its execution in Zig, then, one good strategy that you can take is to use control flow in conjunction with join(). More specifically, you can design your thread around a while loop, that is constantly checking if the thread should continue running. If is time to cancel the thread, we could make the while loop break, and join the thread with the main thread by calling join().

          -

          The code example below demonstrates to some extent this strategy. Here, we are using control flow to break the while loop, and exit the thread earlier than what we have initially planned to. This example also demonstrates how can we use atomic objects in Zig with the Value() generic function that we have mentioned at Section 16.6.2.

          +

          When we think about the pthreads C library, there is a possible way to asynchronously kill or cancel a thread, which is by sending a SIGTERM signal to the thread through the pthread_kill() function. But canceling a thread like this is bad. It’s dangerously bad. As a consequence, the Zig implementation of threads does not have a similar function, or, a similar way to asynchronously cancel or kill a thread.

          +

          Therefore, if you want to cancel a thread in the middle of its execution in Zig, then one good strategy that you can take is to use control flow in conjunction with join(). More specifically, you can design your thread around a while loop that is constantly checking if the thread should continue running. If it’s time to cancel the thread, we could make the while loop break, and join the thread with the main thread by calling join().

          +

          The code example below demonstrates to some extent this strategy. Here, we are using control flow to break the while loop, and exit the thread earlier than what we have initially planned to. This example also demonstrates how can we use atomic objects in Zig with the Value() generic function that we have mentioned in Section 16.6.2.

          const std = @import("std");
           const Thread = std.Thread;
          diff --git a/docs/Chapters/14-zig-c-interop.html b/docs/Chapters/14-zig-c-interop.html
          index 50c66ae8..6cfe4421 100644
          --- a/docs/Chapters/14-zig-c-interop.html
          +++ b/docs/Chapters/14-zig-c-interop.html
          @@ -320,11 +320,11 @@ 

          14  Section 9.11 how you can use the zig compiler to build C code. But we haven’t discussed yet how to actually use C code in Zig. In other words, we haven’t discussed yet how to call and use C code from Zig.

          +

          In this chapter, we are going to discuss the interoperability of Zig with C. We have discussed in Section 9.11 how you can use the zig compiler to build C code. But we haven’t discussed yet how to actually use C code in Zig. In other words, we haven’t discussed yet how to call and use C code from Zig.

          This is the main subject of this chapter. Also, in our next small project in this book, we are going to use a C library in it. As consequence, we will put in practice a lot of the knowledge discussed here on this next project.

          14.1 How to call C code from Zig

          -

          Interoperability with C is not something new. Most high-level programming languages have FFI (foreign function interfaces), which can be used to call C code. For example, Python have Cython, R have .Call(), Javascript have ccall(), etc. But Zig integrates with C in a deeper level, which affects not only the way that C code get’s called, but also, how this C code is compiled and incorporated into your Zig project.

          +

          Interoperability with C is not something new. Most high-level programming languages have FFI (foreign function interfaces), which can be used to call C code. For example, Python have Cython, R have .Call(), Javascript have ccall(), etc. But Zig integrates with C in a deeper level, which affects not only the way that C code gets called, but also, how this C code is compiled and incorporated into your Zig project.

          In summary, Zig have great interoperability with C. If you want to call any C code from Zig, you have to perform the following steps:

          • import a C header file into your Zig code.
          • @@ -353,7 +353,7 @@

            14.2 Importing C header files

            -

            At Section 14.1.1, we have described that, currently, there are two different paths that you can take to import a C header file into your Zig modules, translate-c or @cImport(). This section describes each strategy separately in more details.

            +

            In Section 14.1.1, we have described that, currently, there are two different paths that you can take to import a C header file into your Zig modules, translate-c or @cImport(). This section describes each strategy separately in more details.

            14.2.1 Strategy 1: using translate-c

            When we choose this strategy, we first need to use the translate-c tool to translate the C header files that we want to use into Zig code. For example, suppose we wanted to use the fopen() C function from the stdio.h C header file. We can translate the stdio.h C header file through the bash command below:

            @@ -361,7 +361,7 @@

            -lc -I/usr/include \ -D_NO_CRT_STDIO_INLINE=1 > c.zig \

          Notice that, in this bash command, we are passing the necessary compiler flags (-D to define macros, -l to link libraries, -I to add an “include path”) to compile and use the stdio.h header file. Also notice that we are saving the results of the translation process inside a Zig module called c.zig.

          -

          Therefore, after running this command, all we have to do is to import this c.zig module, and start calling the C functions that you want to call from it. The example below demonstrates that. Is important to remember what we’ve discussed at Section 14.1.2. In order to compile this example you have to link this code with libc, by passing the flag -lc to the zig compiler.

          +

          Therefore, after running this command, all we have to do is to import this c.zig module, and start calling the C functions that you want to call from it. The example below demonstrates that. It’s important to remember what we’ve discussed in Section 14.1.2. In order to compile this example you have to link this code with libc, by passing the flag -lc to the zig compiler.

          const c = @import("c.zig");
           pub fn main() !void {
          @@ -395,19 +395,19 @@ 

          14.3 About passing Zig values to C functions

          -

          Zig objects have some intrinsic differences between their C equivalents. Probably the most noticeable one is the difference between C strings and Zig strings, which I described at Section 1.8. Zig strings are objects that contains both an array of arbitrary bytes and a length value. On the other hand, a C string is usually just a pointer to a null-terminated array of arbitrary bytes.

          +

          Zig objects have some intrinsic differences between their C equivalents. Probably the most noticeable one is the difference between C strings and Zig strings, which I described in Section 1.8. Zig strings are objects that contains both an array of arbitrary bytes and a length value. On the other hand, a C string is usually just a pointer to a null-terminated array of arbitrary bytes.

          Because of these intrinsic differences, in some specific cases, you cannot pass Zig objects directly as inputs to C functions before you convert them into C compatible values. However, in some other cases, you are allowed to pass Zig objects and Zig literal values directly as inputs to C functions, and everything will work just fine, because the zig compiler will handle everything for you.

          So we have two different scenarios being described here. Let’s call them “auto-conversion” and “need-conversion”. The “auto-conversion” scenario is when the zig compiler handles everything for you, and automatically convert your Zig objects/values into C compatible values. In contrast, the “need-conversion” scenario is when you, the programmer, have the responsibility of converting that Zig object into a C compatible value, before passing it to C code.

          -

          There is also a third scenario that is not being described here, which is when you create a C object, or, a C struct, or a C compatible value in your Zig code, and you pass this C object/value as input to a C function in your Zig code. This scenario will be described later at Section 14.4. In this section, we are focused on the scenarios where we are passing Zig objects/values to C code, instead of C objects/values being passed to C code.

          +

          There is also a third scenario that is not being described here, which is when you create a C object, or, a C struct, or a C compatible value in your Zig code, and you pass this C object/value as input to a C function in your Zig code. This scenario will be described later in Section 14.4. In this section, we are focused on the scenarios where we are passing Zig objects/values to C code, instead of C objects/values being passed to C code.

          14.3.1 The “auto-conversion” scenario

          An “auto-conversion” scenario is when the zig compiler automatically converts our Zig objects into C compatible values for us. This specific scenario happens mostly in two instances:

          • with string literal values;
          • -
          • with any of the primitive data types that were introduced at Section 1.5.
          • +
          • with any of the primitive data types that were introduced in Section 1.5.

          When we think about the second instance described above, the zig compiler does automatically convert any of the primitive data types into their C equivalents, because the compiler knows how to properly convert a i16 into a signed short, or, a u8 into a unsigned char, etc. Now, when we think about string literal values, they can be automatically converted into C strings as well, especially because the zig compiler does not forces a specific Zig data type into a string literal at first glance, unless you store this string literal into a Zig object, and explicitly annotate the data type of this object.

          -

          Thus, with string literal values, the zig compiler have more freedom to infer which is the appropriate data type to be used in each situation. You could say that the string literal value “inherits its data type” depending on the context that it is used. Most of the times, this data type is going to be the type that we commonly associate with Zig strings ([]const u8). But it might be a different type depending on the situation. When the zig compiler detects that you are providing a string literal value as input to some C function, the compiler automatically interprets this string literal as a C string value.

          +

          Thus, with string literal values, the zig compiler has more freedom to infer which is the appropriate data type to be used in each situation. You could say that the string literal value “inherits its data type” depending on the context that it’s used in. Most of the times, this data type is going to be the type that we commonly associate with Zig strings ([]const u8). But it might be a different type depending on the situation. When the zig compiler detects that you are providing a string literal value as input to some C function, the compiler automatically interprets this string literal as a C string value.

          As an example, look at the code exposed below. Here we are using the fopen() C function to simply open and close a file. If you do not know how this fopen() function works in C, it takes two C strings as input. But in this code example below, we are passing some string literals written in our Zig code directly as inputs to this fopen() C function.

          In other words, we are not doing any conversion from a Zig string to a C string. We are just passing the Zig string literals directly as inputs to the C function. And it works just fine! Because the compiler interprets the string "foo.txt" as a C string given the current context.

          @@ -444,7 +444,7 @@

          Therefore, when we talk exclusively about string literal values, as long as you don’t give an explicit data type to these string literal values, the zig compiler should be capable of automatically converting them into C strings as needed.

          -

          But what about using one of the primitive data types that were introduced at Section 1.5? Let’s take code exposed below as an example of that. Here, we are giving some float literal values as input to the C function powf(). Notice that this code example compiles and runs successfully.

          +

          But what about using one of the primitive data types that were introduced in Section 1.5? Let’s take code exposed below as an example of that. Here, we are giving some float literal values as input to the C function powf(). Notice that this code example compiles and runs successfully.

          const std = @import("std");
           const stdout = std.io.getStdOut().writer();
          @@ -485,8 +485,8 @@ 

          const file = c.fopen(path.ptr, "rb"); // Remainder of the program

          -

          This strategy works because this pointer to the underlying array found in the ptr property, is semantically identical to a C pointer to an array of bytes, i.e. a C object of type *unsigned char. This is why this option also solves the problem of converting the Zig string into a C string.

          -

          Another option is to explicitly convert the Zig string object into a C pointer by using the built-in function @ptrCast(). With this function we can convert an object of type []const u8 into an object of type [*c]const u8. As I described at the previous section, the [*c] portion of the type means that it is a C pointer. This strategy is not-recommended. But it is useful to demonstrate the use of @ptrCast().

          +

          This strategy works because this pointer to the underlying array found in the ptr property, is semantically identical to a C pointer to an array of bytes, i.e., a C object of type *unsigned char. This is why this option also solves the problem of converting the Zig string into a C string.

          +

          Another option is to explicitly convert the Zig string object into a C pointer by using the built-in function @ptrCast(). With this function we can convert an object of type []const u8 into an object of type [*c]const u8. As I described at the previous section, the [*c] portion of the type means that it’s a C pointer. This strategy is not-recommended. But it’s useful to demonstrate the use of @ptrCast().

          You may recall of @as() and @ptrCast() from Section 2.5. Just as a recap, the @as() built-in function is used to explicitly convert (or cast) a Zig value from a type “x” into a value of type “y”. But in our case here, we are converting a pointer object. Everytime a pointer is involved in some “type casting operation” in Zig, the @ptrCast() function is involved.

          In the example below, we are using this function to cast our path object into a C pointer to an array of bytes. Then, we pass this C pointer as input to the fopen() function. Notice that this code example compiles successfully with no errors.

          @@ -499,7 +499,7 @@

          14.4 Creating C objects in Zig

          -

          Creating C objects, or, in other words, creating instances of C structs in your Zig code is actually something quite easy to do. You first need to import the C header file (like I described at Section 14.2) that defines the C struct that you are trying to instantiate in your Zig code. After that, you can just create a new object in your Zig code, and annotate it with the data type of the C struct.

          +

          Creating C objects, or, in other words, creating instances of C structs in your Zig code is actually something quite easy to do. You first need to import the C header file (like I described in Section 14.2) that defines the C struct that you are trying to instantiate in your Zig code. After that, you can just create a new object in your Zig code, and annotate it with the data type of the C struct.

          For example, suppose we have a C header file called user.h, and that this header file is declaring a new struct named User. This C header file is exposed below:

          #include <stdint.h>
           
          @@ -508,8 +508,8 @@ 

          char* name; } User;

          This User C struct have two distinct fields, or two struct members, named id and name. The field id is an unsigned 64-bit integer value, while the field name is just a standard C string. Now, suppose that I want to create an instance of this User struct in my Zig code. I can do that by importing this user.h header file into my Zig code, and creating a new object with type User. These steps are reproduced in the code example below.

          -

          Notice that I have used the keyword undefined in this example. This allows me to create the new_user object without the need to provide an initial value to the object. As consequence, the underlying memory associated with this new_user object is uninitialized, i.e. the memory is currently populated with “garbage” values. Thus, this expression have the exact same effect of the expression User new_user; in C, which means “declare a new object named new_user of type User”.

          -

          Is our responsibility to properly initialize this memory associated with this new_user object, by assigning valid values to the members (or the fields) of the C struct. In the example below, I’m assigning the integer 1 to the member id. I am also saving the string "pedropark99" into the member name. Notice in this example that I manually add the null character (zero byte) to the end of the allocated array for this string. This null character marks the end of the array in C.

          +

          Notice that I have used the keyword undefined in this example. This allows me to create the new_user object without the need to provide an initial value to the object. As consequence, the underlying memory associated with this new_user object is uninitialized, i.e., the memory is currently populated with “garbage” values. Thus, this expression have the exact same effect of the expression User new_user; in C, which means “declare a new object named new_user of type User”.

          +

          It’s our responsibility to properly initialize this memory associated with this new_user object, by assigning valid values to the members (or the fields) of the C struct. In the example below, I’m assigning the integer 1 to the member id. I am also saving the string "pedropark99" into the member name. Notice in this example that I manually add the null character (zero byte) to the end of the allocated array for this string. This null character marks the end of the array in C.

          const std = @import("std");
           const stdout = std.io.getStdOut().writer();
          @@ -544,9 +544,9 @@ 

          14.5 Passing C structs across Zig functions

          -

          Now that we have learned how to create/declare C objects in our Zig code, we need to learn how to pass these C objects as inputs to Zig functions. As I described at Section 14.4, we can freely pass these C objects as inputs to C code that we call from our Zig code. But what about passing these C objects to Zig functions?

          +

          Now that we have learned how to create/declare C objects in our Zig code, we need to learn how to pass these C objects as inputs to Zig functions. As I described in Section 14.4, we can freely pass these C objects as inputs to C code that we call from our Zig code. But what about passing these C objects to Zig functions?

          In essence, this specific case requires one small adjustment in the Zig function declaration. All you need to do, is to make sure that you pass your C object by reference to the function, instead of passing it by value. To do that, you have to annotate the data type of the function argument that is receiving this C object as “a pointer to the C struct”, instead of annotating it as “an instance of the C struct”.

          -

          Let’s consider the C struct User from the user.h C header file that we have used at Section 14.4. Now, consider that we want to create a Zig function that sets the value of the id field in this C struct, like the set_user_id() function declared below. Notice that the user argument in this function is annotated as a pointer (*) to a c.User object.

          +

          Let’s consider the C struct User from the user.h C header file that we have used in Section 14.4. Now, consider that we want to create a Zig function that sets the value of the id field in this C struct, like the set_user_id() function declared below. Notice that the user argument in this function is annotated as a pointer (*) to a c.User object.

          Therefore, all you have to do when passing C objects to Zig functions, is to add * to the data type of the function argument that is receiving the C object. This will make sure that the C object is passed by reference to the function.

          Because we have transformed the function argument into a pointer, everytime that you have to access the value pointed by this input pointer inside the function body, for whatever reason (e.g. you want to read, update, or delete this value), you have to dereference the pointer with the .* syntax that we learned from Chapter 6. Notice that the set_user_id() function is using this syntax to alter the value in the id field of the User struct pointed by the input pointer.

          diff --git a/docs/Chapters/15-vectors.html b/docs/Chapters/15-vectors.html index 8a8d01dd..708d14bb 100644 --- a/docs/Chapters/15-vectors.html +++ b/docs/Chapters/15-vectors.html @@ -339,12 +339,12 @@

          -

          In this chapter, I want to discuss vectors in Zig, which are related to SIMD operations (i.e. they have no relationship with the std::vector class from C++).

          +

          In this chapter, I want to discuss vectors in Zig, which are related to SIMD operations (i.e., they have no relationship with the std::vector class from C++).

          17.1 What is SIMD?

          SIMD (Single Instruction/Multiple Data) is a group of operations that are widely used on video/audio editing programs, and also in graphics applications. SIMD is not a new technology, but the massive use of SIMD on normal desktop computers is somewhat recent. In the old days, SIMD was only used on “supercomputer models”.

          -

          Most modern CPU models (from AMD, Intel, etc.) these days (either in a desktop or in a notebook model) have support for SIMD operations. So, if you have a very old CPU model installed in your computer, then, is possible that you have no support for SIMD operations in your computer.

          -

          Why people have started using SIMD on their software? The answer is performance. But what SIMD precisely do to achieve better performance? Well, in essence, SIMD operations are a different strategy to get parallel computing in your program, and therefore, make faster calculations.

          +

          Most modern CPU models (from AMD, Intel, etc.) these days (either in a desktop or in a notebook model) have support for SIMD operations. So, if you have a very old CPU model installed in your computer, then, it’s possible that you have no support for SIMD operations in your computer.

          +

          Why have people started using SIMD in their software? The answer is performance. But what does SIMD precisely do to achieve better performance? Well, in essence, SIMD operations are a different strategy to get parallel computing in your program, and therefore, make faster calculations.

          The basic idea behind SIMD is to have a single instruction that operates over multiple data at the same time. When you perform a normal scalar operation, like for example, four add instructions, each addition is performed separately, one after another. But with SIMD, these four add instructions are translated into a single instruction, and, as consequence, the four additions are performed in parallel, at the same time.

          Currently, the zig compiler allows you to apply the following group of operators on vector objects. When you apply one of these operators on vector objects, SIMD is used to make the calculations, and, therefore, these operators are applied element-wise and in parallel by default.

            @@ -356,7 +356,7 @@

            17.2 Vectors

            A SIMD operation is usually performed through a SIMD intrinsic, which is just a fancy name for a function that performs a SIMD operation. These SIMD intrinsics (or “SIMD functions”) always operate over a special type of object, which are called “vectors”. So, in order to use SIMD, you have to create a “vector object”.

            -

            A vector object is usually a fixed-sized block of 128 bits (16 bytes). As consequence, most vectors that you find in the wild are essentially arrays that contains 2 values of 8 bytes each, or, 4 values of 4 bytes each, or, 8 values of 2 bytes each, etc. However, different CPU models may have different extensions (or, “implementations”) of SIMD, which may offer more types of vector objects that are bigger in size (256 bits or 512 bits) to accomodate more data into a single vector object.

            +

            A vector object is usually a fixed-sized block of 128 bits (16 bytes). As a consequence, most vectors that you find in the wild are essentially arrays that contains 2 values of 8 bytes each, or, 4 values of 4 bytes each, or, 8 values of 2 bytes each, etc. However, different CPU models may have different extensions (or, “implementations”) of SIMD, which may offer more types of vector objects that are bigger in size (256 bits or 512 bits) to accomodate more data into a single vector object.

            You can create a new vector object in Zig by using the @Vector() built-in function. Inside this function, you specify the vector length (number of elements in the vector), and the data type of the elements of the vector. Only primitive data types are supported in these vector objects. In the example below, I’m creating two vector objects (v1 and v2) of 4 elements of type u32 each.

            Also notice in the example below, that a third vector object (v3) is created from the sum of the previous two vector objects (v1 plus v2). Therefore, math operations over vector objects take place element-wise by default, because the same operation (in this case, addition) is transformed into a single instruction that is replicated in parallel, across all elements of the vectors.

            @@ -369,7 +369,7 @@

            This is how SIMD introduces more performance in your program. Instead of using a for loop to iterate through the elements of v1 and v2, and adding them together, one element at a time, we enjoy the benefits of SIMD, which performs all 4 additions in parallel, at the same time.

            -

            Therefore, the @Vector structure is essentially the Zig representation of SIMD vector objects. The elements on these vector objects will be operated in parallel, if, and only if your current CPU model supports SIMD operations. If your CPU model does not have support for SIMD, then, the @Vector structure will likely produce a similar performance from a “for loop solution”.

            +

            Therefore, the @Vector structure is essentially the Zig representation of SIMD vector objects. The elements in these vector objects will be operated in parallel, if, and only if your current CPU model supports SIMD operations. If your CPU model does not have support for SIMD, then, the @Vector structure will likely produce a similar performance from a “for loop solution”.

            17.2.1 Transforming arrays into vectors

            There are different ways to transform a normal array into a vector object. You can either use implicit conversion (which is when you assign the array to a vector object directly), or, use slices to create a vector object from a normal array.

            @@ -381,7 +381,7 @@

            const v2: @Vector(2, u32) = a1[1..3].*; _ = v1; _ = v2;

          -

          Is worth emphasizing that only arrays and slices whose sizes are compile-time known can be transformed into vectors. Vectors in general are structures that work only with compile-time known sizes. Therefore, if you have an array whose size is runtime known, then, you first need to copy it into an array with a compile-time known size, before transforming it into a vector.

          +

          It’s worth emphasizing that only arrays and slices whose sizes are compile-time known can be transformed into vectors. Vectors in general are structures that work only with compile-time known sizes. Therefore, if you have an array whose size is runtime known, then, you first need to copy it into an array with a compile-time known size, before transforming it into a vector.

          17.2.2 The @splat() function

          @@ -397,8 +397,8 @@

          17.2.3 Careful with vectors that are too big

          -

          As I described at Section 17.2, each vector object is usually a small block of 128, 256 or 512 bits. This means that a vector object is usually small in size, and when you try to go in the opposite direction, by creating a vector object that is very big in size (i.e. sizes that are close to \(2^{20}\)), you usually end up with crashes and loud errors from the compiler.

          -

          For example, if you try to compile the program below, you will likely face segmentation faults, or, LLVM errors during the build process. Just be careful to not create vector objects that are too big in size.

          +

          As I described in Section 17.2, each vector object is usually a small block of 128, 256 or 512 bits. This means that a vector object is usually small in size, and when you try to go in the opposite direction, by creating a vector object that is very big in size (i.e., sizes that are close to \(2^{20}\)), you usually end up with crashes and loud errors from the compiler.

          +

          For example, if you try to compile the program below, you will likely face segmentation faults, or LLVM errors during the build process. Just be careful to not create vector objects that are too big in size.

          const v1: @Vector(1000000, u32) = @splat(16);
           _ = v1;
          diff --git a/docs/index.html b/docs/index.html index 6012b60d..80cde802 100644 --- a/docs/index.html +++ b/docs/index.html @@ -7,7 +7,7 @@ - + Introduction to Zig \n\n\n\n \n\n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n\n- System version: Linux, 6.8.0-52-generic, NA, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion), glystik (\\@glystik), Michael Lynch (\\@mtlynch)\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy\nof the book, either at Amazon, or at Leanpub:\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.11.0-19-generic, 24.04.1-Ubuntu, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion), glystik (\\@glystik), Michael Lynch (\\@mtlynch)\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/docs/index.html b/docs/index.html index 10e83b3b..34e98809 100644 --- a/docs/index.html +++ b/docs/index.html @@ -426,7 +426,7 @@

          License

          Book compilation metadata

          This book was compiled using the following versions of Zig and Quarto:

            -
          • System version: Linux, 6.8.0-52-generic, NA, x86_64.
          • +
          • System version: Linux, 6.11.0-19-generic, 24.04.1-Ubuntu, x86_64.
          • Zig version: 0.14.0-dev.3046+08d661fcf.
          • Quarto version: 1.5.57.
          diff --git a/docs/search.json b/docs/search.json index 49383209..616ae938 100644 --- a/docs/search.json +++ b/docs/search.json @@ -54,7 +54,7 @@ "href": "index.html#book-compilation-metadata", "title": "Introduction to Zig", "section": "Book compilation metadata", - "text": "Book compilation metadata\nThis book was compiled using the following versions of Zig and Quarto:\n\nSystem version: Linux, 6.8.0-52-generic, NA, x86_64.\nZig version: 0.14.0-dev.3046+08d661fcf.\nQuarto version: 1.5.57.", + "text": "Book compilation metadata\nThis book was compiled using the following versions of Zig and Quarto:\n\nSystem version: Linux, 6.11.0-19-generic, 24.04.1-Ubuntu, x86_64.\nZig version: 0.14.0-dev.3046+08d661fcf.\nQuarto version: 1.5.57.", "crumbs": [ "Welcome" ] diff --git a/zig_engine.R b/zig_engine.R index 1f76d880..151e2168 100644 --- a/zig_engine.R +++ b/zig_engine.R @@ -2,6 +2,14 @@ library(knitr) library(readr) library(stringr) + +minimum_zig_compiler_version <- list( + maj_version = 0, + min_version = 14, + patch_version = 0 +) + + #' Find path to the Zig compiler in the current machine. #' #' This function is used to find the full path to the Zig compiler @@ -61,11 +69,113 @@ find_in_path_ <- function() { } + +#' Check Zig compiler version. +#' +#' This function will check if the Zig compiler that was found +#' in the current machine have the minimum required version to +#' compiler the book. +check_zig_compiler_version <- function() { + fv <- get_zig_compiler_version() + ev <- minimum_zig_compiler_version + if (fv$maj_version > ev$maj_version) { + return() + } + + if (fv$maj_version == ev$maj_version) { + if (fv$min_version > ev$min_version) { + return() + } + + if (fv$min_version == ev$min_version + && fv$patch_version >= ev$patch_version) { + return() + } + } + + fvmsg <- sprintf( + "compiler have a version of %d.%d.%d, ", + fv$maj_version, fv$min_version, fv$patch_version + ) + evmsg <- sprintf( + "but we expected a compiler with minimum version of %d.%d.%d ", + ev$maj_version, ev$min_version, ev$patch_version + ) + + msg <- paste( + c( + "[ERROR]: We found a Zig compiler in your computer. However, this ", + fvmsg, evmsg, + "to compile this book." + ), + sep = "", + collapse = "" + ) + + stop(msg) +} + + + + +#' Get Zig compiler version. +#' +#' This function can be used to get the version of the Zig +#' compiler that was found in the current machine. +get_zig_compiler_version <- function() { + zig_cmd_path <- getOption("zig_exe_path") + output <- system2( + zig_cmd_path, + shQuote("version"), + stdout = TRUE, + stderr = TRUE + ) + version <- parse_semantic_version(output) + return(version) +} + + + +#' Parse a semantic version value. +#' +#' This function can be used to parse a semantic version value. +#' +#' @param input A string containing the semantic version value to parse. +parse_semantic_version <- function(input) { + regex_str <- "^([0-9])[.]([0-9]+)[.]([0-9]+)" + maj_version <- str_extract(input, regex_str, group = 1) + min_version <- str_extract(input, regex_str, group = 2) + patch_version <- str_extract(input, regex_str, group = 3) + + return(list( + maj_version = as.integer(maj_version), + min_version = as.integer(min_version), + patch_version = as.integer(patch_version) + )) +} + + + + + + + + + # The full path to the Zig compiler is registered in the R process # inside the global option `zig_exe_path`. And you can retrieve the # value registered in this option with `getOption("zig_exe_path")`. options(zig_exe_path = find_zig_()) options(width = 50) +check_zig_compiler_version() + + + + + + + + From 8a8c47dda4ef3dc8da836936f068a550c3ac1718 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sat, 8 Mar 2025 12:04:23 -0300 Subject: [PATCH 116/151] Add new section to explain pub keyword --- Chapters/03-structs.qmd | 130 ++++++- .../zig-basics/import-non-pub-struct.zig | 5 + ZigExamples/zig-basics/pub-keyword.zig | 20 + .../03-structs/execute-results/html.json | 8 +- docs/Chapters/03-structs.html | 362 ++++++++++-------- docs/search.json | 6 +- 6 files changed, 359 insertions(+), 172 deletions(-) create mode 100644 ZigExamples/zig-basics/import-non-pub-struct.zig create mode 100644 ZigExamples/zig-basics/pub-keyword.zig diff --git a/Chapters/03-structs.qmd b/Chapters/03-structs.qmd index 59280306..ba5f7069 100644 --- a/Chapters/03-structs.qmd +++ b/Chapters/03-structs.qmd @@ -759,7 +759,7 @@ const User = struct { name: []const u8, email: []const u8, - pub fn init(id: u64, + fn init(id: u64, name: []const u8, email: []const u8) User { @@ -770,7 +770,7 @@ const User = struct { }; } - pub fn print_name(self: User) !void { + fn print_name(self: User) !void { try stdout.print("{s}\n", .{self.name}); } }; @@ -781,21 +781,125 @@ pub fn main() !void { } ``` + + +### The `pub` keyword + The `pub` keyword plays an important role in struct declarations, and OOP in Zig. -Every method that you declare in your struct that is marked with the keyword `pub`, -becomes a public method of this particular struct. +In essence, this keyword is short for "public", and it makes an item/component available outside of the +module where this item/component is declared. In other words, if I don't apply the `pub` keyword on +something, it means that this "something" is available to be called/used only from within the module +where this "something" is declared. + +To demonstrate the effect of this keyword let's focus again on the `User` struct that we have +declared on the previous section. For our example here, let's suppose that this `User` struct is declared inside +a Zig module named `user.zig`. If I don't use the `pub` keyword on the `User` struct, it means that I can create +an `User` object, and call it's methods (`print_name()` and `init()`) only from within the module where the `User` +struct is declared, which in this case is the `user.zig` module. + +This is why the previous code example works fine. Because we declare and also use the `User` struct +inside the same module. But problems start to arise when we try to import and call/use this struct +from another module. For example, if I create a new module called `register.zig`, and import the `user.zig` +module into it, and try to annotate any variable with the `User` type, I get an error from the compiler. + +```zig +// register.zig +const user = @import("user.zig"); +pub fn main() !void { + const u: user.User = undefined; + _ = u; +} +``` + +``` +register.zig:3:18: error: 'User' is not marked 'pub' + const u: user.User = undefined; + ~~~~^~~~~ +user.zig:3:1: note: declared here +const User = struct { +^~~~~ +``` + +Therefore, if you want to use something outside of the module where this "something" is declared, +you have to mark it with the `pub` keyword. This "something" can be a module, +a struct, a function, an object, etc. + +For our example here, if we go back to the `user.zig` module, and add the `pub` keyword +to the `User` struct declaration, then, I can successfully compile the `register.zig` module. + +```zig +// user.zig +// Added the `pub` keyword to `User` +pub const User = struct { +// ... +``` + +```zig +// register.zig +// This works fine now! +const user = @import("user.zig"); +pub fn main() !void { + const u: user.User = undefined; + _ = u; +} +``` -So every method that you create inside your struct, is, at first, a private method -of that struct. Meaning that, this method can only be called from within this -struct. But, if you mark this method as public, with the keyword `pub`, then, -you can call the method directly from an instance of the `User` struct. -In other words, the functions marked by the keyword `pub` -are members of the public API of that struct. -For example, if I did not mark the `print_name()` method as public, -then, I could not execute the line `u.print_name()`. Because I would -not be authorized to call this method directly in my code. +Now, what do you think it will happen if I try to actually call from `register.zig` any of the methods +of the `User` struct? For example, if I try to call the `init()` method? The answer is: I get a similar error message, +warning me that the `init()` method is not marked as `pub`, as you can see below: +```zig +const user = @import("user.zig"); +pub fn main() !void { + const u: user.User = user.User.init( + 1, "pedro", "email@gmail.com" + ); + _ = u; +} +``` + +``` +register.zig:3:35: error: 'init' is not marked 'pub' + const u: user.User = user.User.init( + ~~~~~~~~~^~~~~ +user.zig:8:5: note: declared here + fn init(id: u64, + ^~~~~~~ +``` + +Thus, just because we have applied the `pub` keyword on the struct declaration, +this does not make the methods of that struct public as well. If we want to use +any method from a struct (such as the `init()` method) outside of the module +where this struct is declared, we have to mark this method with the `pub` keyword +as well. + +Going back to the `user.zig` module, and marking both the `init()` and `print_name()` +methods with the `pub` keyword, makes them both available to the outside world, and, +as consequence, makes the previous code example work. + + +```zig +// user.zig +// Added the `pub` keyword to `User.init` + pub fn init( +// ... +// Added the `pub` keyword to `User.print_name` + pub fn print_name(self: User) !void { +// ... +``` + +```zig +// register.zig +// This works fine now! +const user = @import("user.zig"); +pub fn main() !void { + const u: user.User = user.User.init( + 1, "pedro", "email@gmail.com" + ); + _ = u; +} +``` ### Anonymous struct literals {#sec-anonymous-struct-literals} diff --git a/ZigExamples/zig-basics/import-non-pub-struct.zig b/ZigExamples/zig-basics/import-non-pub-struct.zig new file mode 100644 index 00000000..d327c347 --- /dev/null +++ b/ZigExamples/zig-basics/import-non-pub-struct.zig @@ -0,0 +1,5 @@ +const user = @import("pub-keyword.zig"); +pub fn main() !void { + const u: user.User = user.User.init(1, "pedro", "email@gmail.com"); + _ = u; +} diff --git a/ZigExamples/zig-basics/pub-keyword.zig b/ZigExamples/zig-basics/pub-keyword.zig new file mode 100644 index 00000000..c9a60c5b --- /dev/null +++ b/ZigExamples/zig-basics/pub-keyword.zig @@ -0,0 +1,20 @@ +const std = @import("std"); +const stdout = std.io.getStdOut().writer(); +pub const User = struct { + id: u64, + name: []const u8, + email: []const u8, + + pub fn init(id: u64, name: []const u8, email: []const u8) User { + return User{ .id = id, .name = name, .email = email }; + } + + pub fn print_name(self: User) !void { + try stdout.print("{s}\n", .{self.name}); + } +}; + +pub fn main() !void { + const u = User.init(1, "pedro", "email@gmail.com"); + try u.print_name(); +} diff --git a/_freeze/Chapters/03-structs/execute-results/html.json b/_freeze/Chapters/03-structs/execute-results/html.json index 8781660b..fbe83947 100644 --- a/_freeze/Chapters/03-structs/execute-results/html.json +++ b/_freeze/Chapters/03-structs/execute-results/html.json @@ -1,11 +1,9 @@ { - "hash": "ec9ff8aaff4376d4eab0dd3ee150d725", + "hash": "10ffcb221f40a28afe7a41688091c355", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `role`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object has type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e., four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n```\n:::\n\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It's important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n else => {\n try stdout.print(\n \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n );\n },\n}\n```\n:::\n\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n```\n:::\n\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function gets executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, it's worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression gets executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that gets printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n```\n:::\n\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n // code to execute\n}\n```\n:::\n\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It's the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e., the logical test is equal to false), the function raises an assertion error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e., constant) object\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n x = x + 2;\n return x;\n}\n\npub fn main() !void {\n const y = add2(4);\n std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n x = x + 2;\n ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e., `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n const d: u32 = 2;\n x.* = x.* + d;\n}\n\npub fn main() !void {\n var x: u32 = 4;\n add2(&x);\n std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n pub fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n pub fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nEvery method that you declare in your struct that is marked with the keyword `pub`,\nbecomes a public method of this particular struct.\n\nSo every method that you create inside your struct, is, at first, a private method\nof that struct. Meaning that, this method can only be called from within this\nstruct. But, if you mark this method as public, with the keyword `pub`, then,\nyou can call the method directly from an instance of the `User` struct.\n\nIn other words, the functions marked by the keyword `pub`\nare members of the public API of that struct.\nFor example, if I did not mark the `print_name()` method as public,\nthen, I could not execute the line `u.print_name()`. Because I would\nnot be authorized to call this method directly in my code.\n\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n```\n:::\n\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt's not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n```\n:::\n\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods are affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e., changes the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n```\n:::\n\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it's not about the input object, it's about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special part in this place. More specifically, it's\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and trying\nto infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n```\n:::\n\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e., we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it's explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file79ce58134f59.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe. There are many situations where these assumptions do not hold. For example,\n\nwhen casting an integer value into a float value, or vice-versa, it's not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file79ce286cee5b.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e., they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file79ce1e7313c8.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e., a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" gets executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object gets saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n .{ .max_threads = num_threads }\n);\n```\n:::\n", - "supporting": [ - "03-structs_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `role`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object has type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e., four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n```\n:::\n\n\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It's important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n else => {\n try stdout.print(\n \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n );\n },\n}\n```\n:::\n\n\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n```\n:::\n\n\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function gets executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, it's worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression gets executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n```\n:::\n\n\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that gets printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n```\n:::\n\n\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n // code to execute\n}\n```\n:::\n\n\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It's the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e., the logical test is equal to false), the function raises an assertion error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e., constant) object\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n x = x + 2;\n return x;\n}\n\npub fn main() !void {\n const y = add2(4);\n std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n x = x + 2;\n ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e., `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n const d: u32 = 2;\n x.* = x.* + d;\n}\n\npub fn main() !void {\n var x: u32 = 4;\n add2(&x);\n std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### The `pub` keyword\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nIn essence, this keyword is short for \"public\", and it makes an item/component available outside of the\nmodule where this item/component is declared. In other words, if I don't apply the `pub` keyword on\nsomething, it means that this \"something\" is available to be called/used only from within the module\nwhere this \"something\" is declared.\n\nTo demonstrate the effect of this keyword let's focus again on the `User` struct that we have\ndeclared on the previous section. For our example here, let's suppose that this `User` struct is declared inside\na Zig module named `user.zig`. If I don't use the `pub` keyword on the `User` struct, it means that I can create\nan `User` object, and call it's methods (`print_name()` and `init()`) only from within the module where the `User`\nstruct is declared, which in this case is the `user.zig` module.\n\nThis is why the previous code example works fine. Because we declare and also use the `User` struct\ninside the same module. But problems start to arise when we try to import and call/use this struct\nfrom another module. For example, if I create a new module called `register.zig`, and import the `user.zig`\nmodule into it, and try to annotate any variable with the `User` type, I get an error from the compiler.\n\n```zig\n// register.zig\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = undefined;\n _ = u;\n}\n```\n\n```\nregister.zig:3:18: error: 'User' is not marked 'pub'\n const u: user.User = undefined;\n ~~~~^~~~~\nuser.zig:3:1: note: declared here\nconst User = struct {\n^~~~~\n```\n\nTherefore, if you want to use something outside of the module where this \"something\" is declared,\nyou have to mark it with the `pub` keyword. This \"something\" can be a module,\na struct, a function, an object, etc.\n\nFor our example here, if we go back to the `user.zig` module, and add the `pub` keyword\nto the `User` struct declaration, then, I can successfully compile the `register.zig` module.\n\n```zig\n// user.zig\n// Added the `pub` keyword to `User`\npub const User = struct {\n// ...\n```\n\n```zig\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = undefined;\n _ = u;\n}\n```\n\n\nNow, what do you think it will happen if I try to actually call from `register.zig` any of the methods\nof the `User` struct? For example, if I try to call the `init()` method? The answer is: I get a similar error message,\nwarning me that the `init()` method is not marked as `pub`, as you can see below:\n\n```zig\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = user.User.init(\n 1, \"pedro\", \"email@gmail.com\"\n );\n _ = u;\n}\n```\n\n```\nregister.zig:3:35: error: 'init' is not marked 'pub'\n const u: user.User = user.User.init(\n ~~~~~~~~~^~~~~\nuser.zig:8:5: note: declared here\n fn init(id: u64,\n ^~~~~~~\n```\n\nThus, just because we have applied the `pub` keyword on the struct declaration,\nthis does not make the methods of that struct public as well. If we want to use\nany method from a struct (such as the `init()` method) outside of the module\nwhere this struct is declared, we have to mark this method with the `pub` keyword\nas well.\n\nGoing back to the `user.zig` module, and marking both the `init()` and `print_name()`\nmethods with the `pub` keyword, makes them both available to the outside world, and,\nas consequence, makes the previous code example work.\n\n\n```zig\n// user.zig\n// Added the `pub` keyword to `User.init`\n pub fn init(\n// ...\n// Added the `pub` keyword to `User.print_name`\n pub fn print_name(self: User) !void {\n// ...\n```\n\n```zig\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = user.User.init(\n 1, \"pedro\", \"email@gmail.com\"\n );\n _ = u;\n}\n```\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n```\n:::\n\n\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt's not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n```\n:::\n\n\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods are affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e., changes the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n```\n:::\n\n\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it's not about the input object, it's about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special part in this place. More specifically, it's\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and trying\nto infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n```\n:::\n\n\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e., we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it's explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3c448aa9d5f.test_0...OKAll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe. There are many situations where these assumptions do not hold. For example,\n\nwhen casting an integer value into a float value, or vice-versa, it's not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3c4427337b66.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e., they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3c4479f1f6f8.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e., a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" gets executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object gets saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n .{ .max_threads = num_threads }\n);\n```\n:::\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/docs/Chapters/03-structs.html b/docs/Chapters/03-structs.html index 7c8203c7..5c0fd596 100644 --- a/docs/Chapters/03-structs.html +++ b/docs/Chapters/03-structs.html @@ -295,10 +295,11 @@

          Table of contents

      10. 2.3 Structs and OOP
      11. 2.4 Type inference
      12. 2.5 Type casting
      13. @@ -702,7 +703,7 @@

        name: []const u8, email: []const u8, - pub fn init(id: u64, + fn init(id: u64, name: []const u8, email: []const u8) User { @@ -713,7 +714,7 @@

        }; } - pub fn print_name(self: User) !void { + fn print_name(self: User) !void { try stdout.print("{s}\n", .{self.name}); } }; @@ -726,129 +727,189 @@

        pedro

    -

    The pub keyword plays an important role in struct declarations, and OOP in Zig. Every method that you declare in your struct that is marked with the keyword pub, becomes a public method of this particular struct.

    -

    So every method that you create inside your struct, is, at first, a private method of that struct. Meaning that, this method can only be called from within this struct. But, if you mark this method as public, with the keyword pub, then, you can call the method directly from an instance of the User struct.

    -

    In other words, the functions marked by the keyword pub are members of the public API of that struct. For example, if I did not mark the print_name() method as public, then, I could not execute the line u.print_name(). Because I would not be authorized to call this method directly in my code.

    -
    -

    2.3.1 Anonymous struct literals

    +
    +

    2.3.1 The pub keyword

    +

    The pub keyword plays an important role in struct declarations, and OOP in Zig. In essence, this keyword is short for “public”, and it makes an item/component available outside of the module where this item/component is declared. In other words, if I don’t apply the pub keyword on something, it means that this “something” is available to be called/used only from within the module where this “something” is declared.

    +

    To demonstrate the effect of this keyword let’s focus again on the User struct that we have declared on the previous section. For our example here, let’s suppose that this User struct is declared inside a Zig module named user.zig. If I don’t use the pub keyword on the User struct, it means that I can create an User object, and call it’s methods (print_name() and init()) only from within the module where the User struct is declared, which in this case is the user.zig module.

    +

    This is why the previous code example works fine. Because we declare and also use the User struct inside the same module. But problems start to arise when we try to import and call/use this struct from another module. For example, if I create a new module called register.zig, and import the user.zig module into it, and try to annotate any variable with the User type, I get an error from the compiler.

    +
    // register.zig
    +const user = @import("user.zig");
    +pub fn main() !void {
    +    const u: user.User = undefined;
    +    _ = u;
    +}
    +
    register.zig:3:18: error: 'User' is not marked 'pub'
    +    const u: user.User = undefined;
    +             ~~~~^~~~~
    +user.zig:3:1: note: declared here
    +const User = struct {
    +^~~~~
    +

    Therefore, if you want to use something outside of the module where this “something” is declared, you have to mark it with the pub keyword. This “something” can be a module, a struct, a function, an object, etc.

    +

    For our example here, if we go back to the user.zig module, and add the pub keyword to the User struct declaration, then, I can successfully compile the register.zig module.

    +
    // user.zig
    +// Added the `pub` keyword to `User`
    +pub const User = struct {
    +// ...
    +
    // register.zig
    +// This works fine now!
    +const user = @import("user.zig");
    +pub fn main() !void {
    +    const u: user.User = undefined;
    +    _ = u;
    +}
    +

    Now, what do you think it will happen if I try to actually call from register.zig any of the methods of the User struct? For example, if I try to call the init() method? The answer is: I get a similar error message, warning me that the init() method is not marked as pub, as you can see below:

    +
    const user = @import("user.zig");
    +pub fn main() !void {
    +    const u: user.User = user.User.init(
    +        1, "pedro", "email@gmail.com"
    +    );
    +    _ = u;
    +}
    +
    register.zig:3:35: error: 'init' is not marked 'pub'
    +    const u: user.User = user.User.init(
    +                         ~~~~~~~~~^~~~~
    +user.zig:8:5: note: declared here
    +    fn init(id: u64,
    +    ^~~~~~~
    +

    Thus, just because we have applied the pub keyword on the struct declaration, this does not make the methods of that struct public as well. If we want to use any method from a struct (such as the init() method) outside of the module where this struct is declared, we have to mark this method with the pub keyword as well.

    +

    Going back to the user.zig module, and marking both the init() and print_name() methods with the pub keyword, makes them both available to the outside world, and, as consequence, makes the previous code example work.

    +
    // user.zig
    +// Added the `pub` keyword to `User.init`
    +    pub fn init(
    +// ...
    +// Added the `pub` keyword to `User.print_name`
    +    pub fn print_name(self: User) !void {
    +// ...
    +
    // register.zig
    +// This works fine now!
    +const user = @import("user.zig");
    +pub fn main() !void {
    +    const u: user.User = user.User.init(
    +        1, "pedro", "email@gmail.com"
    +    );
    +    _ = u;
    +}
    +
    +
    +

    2.3.2 Anonymous struct literals

    You can declare a struct object as a literal value. When we do that, we normally specify the data type of this struct literal by writing its data type just before the opening curly brace. For example, I could write a struct literal value of the type User that we have defined in the previous section like this:

    -
    const eu = User {
    -    .id = 1,
    -    .name = "Pedro",
    -    .email = "someemail@gmail.com"
    -};
    -_ = eu;
    +
    const eu = User {
    +    .id = 1,
    +    .name = "Pedro",
    +    .email = "someemail@gmail.com"
    +};
    +_ = eu;

    However, in Zig, we can also write an anonymous struct literal. That is, you can write a struct literal, but not specify explicitly the type of this particular struct. An anonymous struct is written by using the syntax .{}. So, we essentially replaced the explicit type of the struct literal with a dot character (.).

    As we described in Section 2.4, when you put a dot before a struct literal, the type of this struct literal is automatically inferred by the zig compiler. In essence, the zig compiler will look for some hint of what is the type of that struct. This hint can be the type annotation of a function argument, or the return type annotation of the function that you are using, or the type annotation of an existing object. If the compiler does find such type annotation, it will use this type in your literal struct.

    Anonymous structs are very commonly used as inputs to function arguments in Zig. One example that you have seen already constantly, is the print() function from the stdout object. This function takes two arguments. The first argument, is a template string, which should contain string format specifiers in it, which tells how the values provided in the second argument should be printed into the message.

    While the second argument is a struct literal that lists the values to be printed into the template message specified in the first argument. You normally want to use an anonymous struct literal here, so that the zig compiler do the job of specifying the type of this particular anonymous struct for you.

    -
    const std = @import("std");
    -pub fn main() !void {
    -    const stdout = std.io.getStdOut().writer();
    -    try stdout.print("Hello, {s}!\n", .{"world"});
    -}
    +
    const std = @import("std");
    +pub fn main() !void {
    +    const stdout = std.io.getStdOut().writer();
    +    try stdout.print("Hello, {s}!\n", .{"world"});
    +}
    Hello, world!
    -
    -

    2.3.2 Struct declarations must be constant

    +
    +

    2.3.3 Struct declarations must be constant

    Types in Zig must be const or comptime (we are going to talk more about comptime in Section 12.1). What this means is that you cannot create a new data type, and mark it as variable with the var keyword. So struct declarations are always constant. You cannot declare a new struct type using the var keyword. It must be const.

    In the Vec3 example below, this declaration is allowed because I’m using the const keyword to declare this new data type.

    -
    const Vec3 = struct {
    -    x: f64,
    -    y: f64,
    -    z: f64,
    -};
    +
    const Vec3 = struct {
    +    x: f64,
    +    y: f64,
    +    z: f64,
    +};
    -
    -

    2.3.3 The self method argument

    +
    +

    2.3.4 The self method argument

    In every language that have OOP, when we declare a method of some class or struct, we usually declare this method as a function that has a self argument. This self argument is the reference to the object itself from which the method is being called from.

    It’s not mandatory to use this self argument. But why would you not use this self argument? There is no reason to not use it. Because the only way to get access to the data stored in the data members of your struct is to access them through this self argument. If you don’t need to use the data in the data members of your struct inside your method, you very likely don’t need a method. You can just declare this logic as a simple function, outside of your struct declaration.

    Take the Vec3 struct below. Inside this Vec3 struct we declared a method named distance(). This method calculates the distance between two Vec3 objects, by following the distance formula in euclidean space. Notice that this distance() method takes two Vec3 objects as input, self and other.

    -
    const std = @import("std");
    -const m = std.math;
    -const Vec3 = struct {
    -    x: f64,
    -    y: f64,
    -    z: f64,
    -
    -    pub fn distance(self: Vec3, other: Vec3) f64 {
    -        const xd = m.pow(f64, self.x - other.x, 2.0);
    -        const yd = m.pow(f64, self.y - other.y, 2.0);
    -        const zd = m.pow(f64, self.z - other.z, 2.0);
    -        return m.sqrt(xd + yd + zd);
    -    }
    -};
    +
    const std = @import("std");
    +const m = std.math;
    +const Vec3 = struct {
    +    x: f64,
    +    y: f64,
    +    z: f64,
    +
    +    pub fn distance(self: Vec3, other: Vec3) f64 {
    +        const xd = m.pow(f64, self.x - other.x, 2.0);
    +        const yd = m.pow(f64, self.y - other.y, 2.0);
    +        const zd = m.pow(f64, self.z - other.z, 2.0);
    +        return m.sqrt(xd + yd + zd);
    +    }
    +};

    The self argument corresponds to the Vec3 object from which this distance() method is being called from. While the other is a separate Vec3 object that is given as input to this method. In the example below, the self argument corresponds to the object v1, because the distance() method is being called from the v1 object, while the other argument corresponds to the object v2.

    -
    const v1 = Vec3 {
    -    .x = 4.2, .y = 2.4, .z = 0.9
    -};
    -const v2 = Vec3 {
    -    .x = 5.1, .y = 5.6, .z = 1.6
    -};
    -
    -std.debug.print(
    -    "Distance: {d}\n",
    -    .{v1.distance(v2)}
    -);
    +
    const v1 = Vec3 {
    +    .x = 4.2, .y = 2.4, .z = 0.9
    +};
    +const v2 = Vec3 {
    +    .x = 5.1, .y = 5.6, .z = 1.6
    +};
    +
    +std.debug.print(
    +    "Distance: {d}\n",
    +    .{v1.distance(v2)}
    +);
    Distance: 3.3970575502926055
    -
    -

    2.3.4 About the struct state

    +
    +

    2.3.5 About the struct state

    Sometimes you don’t need to care about the state of your struct object. Sometimes, you just need to instantiate and use the objects, without altering their state. You can notice that when you have methods inside your struct declaration that might use the values that are present in the data members, but they do not alter the values in these data members of the struct in anyway.

    -

    The Vec3 struct that was presented in Section 2.3.3 is an example of that. This struct have a single method named distance(), and this method does use the values present in all three data members of the struct (x, y and z). But at the same time, this method does not change the values of these data members at any point.

    -

    As a result of that, when we create Vec3 objects we usually create them as constant objects, like the v1 and v2 objects presented in Section 2.3.3. We can create them as variable objects with the var keyword, if we want to. But because the methods of this Vec3 struct do not change the state of the objects in any point, it’s unnecessary to mark them as variable objects.

    +

    The Vec3 struct that was presented in Section 2.3.4 is an example of that. This struct have a single method named distance(), and this method does use the values present in all three data members of the struct (x, y and z). But at the same time, this method does not change the values of these data members at any point.

    +

    As a result of that, when we create Vec3 objects we usually create them as constant objects, like the v1 and v2 objects presented in Section 2.3.4. We can create them as variable objects with the var keyword, if we want to. But because the methods of this Vec3 struct do not change the state of the objects in any point, it’s unnecessary to mark them as variable objects.

    But why? Why am I talking about this here? It’s because the self argument in the methods are affected depending on whether the methods present in a struct change or don’t change the state of the object itself. More specifically, when you have a method in a struct that changes the state of the object (i.e., changes the value of a data member), the self argument in this method must be annotated in a different manner.

    -

    As I described in Section 2.3.3, the self argument in methods of a struct is the argument that receives as input the object from which the method was called from. We usually annotate this argument in the methods by writing self, followed by the colon character (:), and the data type of the struct to which the method belongs to (e.g. User, Vec3, etc.).

    +

    As I described in Section 2.3.4, the self argument in methods of a struct is the argument that receives as input the object from which the method was called from. We usually annotate this argument in the methods by writing self, followed by the colon character (:), and the data type of the struct to which the method belongs to (e.g. User, Vec3, etc.).

    If we take the Vec3 struct that we defined in the previous section as an example, we can see in the distance() method that this self argument is annotated as self: Vec3. Because the state of the Vec3 object is never altered by this method.

    But what if we do have a method that alters the state of the object, by altering the values of its data members, how should we annotate self in this instance? The answer is: “we should annotate self as a pointer of x, instead of just x”. In other words, you should annotate self as self: *x, instead of annotating it as self: x.

    If we create a new method inside the Vec3 object that, for example, expands the vector by multiplying its coordinates by a factor of two, then, we need to follow this rule specified in the previous paragraph. The code example below demonstrates this idea:

    -
    const std = @import("std");
    -const m = std.math;
    -const Vec3 = struct {
    -    x: f64,
    -    y: f64,
    -    z: f64,
    -
    -    pub fn distance(self: Vec3, other: Vec3) f64 {
    -        const xd = m.pow(f64, self.x - other.x, 2.0);
    -        const yd = m.pow(f64, self.y - other.y, 2.0);
    -        const zd = m.pow(f64, self.z - other.z, 2.0);
    -        return m.sqrt(xd + yd + zd);
    -    }
    -
    -    pub fn twice(self: *Vec3) void {
    -        self.x = self.x * 2.0;
    -        self.y = self.y * 2.0;
    -        self.z = self.z * 2.0;
    -    }
    -};
    +
    const std = @import("std");
    +const m = std.math;
    +const Vec3 = struct {
    +    x: f64,
    +    y: f64,
    +    z: f64,
    +
    +    pub fn distance(self: Vec3, other: Vec3) f64 {
    +        const xd = m.pow(f64, self.x - other.x, 2.0);
    +        const yd = m.pow(f64, self.y - other.y, 2.0);
    +        const zd = m.pow(f64, self.z - other.z, 2.0);
    +        return m.sqrt(xd + yd + zd);
    +    }
    +
    +    pub fn twice(self: *Vec3) void {
    +        self.x = self.x * 2.0;
    +        self.y = self.y * 2.0;
    +        self.z = self.z * 2.0;
    +    }
    +};

    Notice in the code example above that we have added a new method to our Vec3 struct named twice(). This method doubles the coordinate values of our vector object. In the case of the twice() method, we annotated the self argument as *Vec3, indicating that this argument receives a pointer (or a reference, if you prefer to call it this way) to a Vec3 object as input.

    -
    var v3 = Vec3 {
    -    .x = 4.2, .y = 2.4, .z = 0.9
    -};
    -v3.twice();
    -std.debug.print("Doubled: {d}\n", .{v3.x});
    +
    var v3 = Vec3 {
    +    .x = 4.2, .y = 2.4, .z = 0.9
    +};
    +v3.twice();
    +std.debug.print("Doubled: {d}\n", .{v3.x});
    Doubled: 8.4

    Now, if you change the self argument in this twice() method to self: Vec3, like in the distance() method, you will get the compiler error exposed below as result. Notice that this error message is showing a line from the twice() method body, indicating that you cannot alter the value of the x data member.

    -
    // If we change the function signature of double to:
    -    pub fn twice(self: Vec3) void {
    +
    // If we change the function signature of double to:
    +    pub fn twice(self: Vec3) void {
    t.zig:16:13: error: cannot assign to constant
             self.x = self.x * 2.0;
    @@ -878,38 +939,38 @@ 

    Zig is a strongly typed language. But, there are some situations where you don’t have to explicitly write the type of every single object in your source code, as you would expect from a traditional strongly typed language, such as C and C++.

    In some situations, the zig compiler can use type inference to solve the data types for you, easing some of the burden that you carry as a developer. The most common way this happens is through function arguments that receive struct objects as input.

    In general, type inference in Zig is done by using the dot character (.). Everytime you see a dot character written before a struct literal, or before an enum value, or something like that, you know that this dot character is playing a special part in this place. More specifically, it’s telling the zig compiler something along the lines of: “Hey! Can you infer the type of this value for me? Please!”. In other words, this dot character is playing a similar role as the auto keyword in C++.

    -

    I gave you some examples of this in Section 2.3.1, where we used anonymous struct literals. Anonymous struct literals are, struct literals that use type inference to infer the exact type of this particular struct literal. This type inference is done by looking for some minimal hint of the correct data type to be used. You could say that the zig compiler looks for any neighbouring type annotation that might tell it what the correct type would be.

    +

    I gave you some examples of this in Section 2.3.2, where we used anonymous struct literals. Anonymous struct literals are, struct literals that use type inference to infer the exact type of this particular struct literal. This type inference is done by looking for some minimal hint of the correct data type to be used. You could say that the zig compiler looks for any neighbouring type annotation that might tell it what the correct type would be.

    Another common place where we use type inference in Zig is at switch statements (which we talked about in Section 2.1.2). I also gave some other examples of type inference in Section 2.1.2, where we were inferring the data types of enum values listed inside of switch statements (e.g. .DE). But as another example, take a look at this fence() function reproduced below, which comes from the atomic.zig module2 of the Zig Standard Library.

    There are a lot of things in this function that we haven’t talked about yet, such as: what comptime means? inline? extern? Let’s just ignore all of these things, and focus solely on the switch statement that is inside this function.

    We can see that this switch statement uses the order object as input. This order object is one of the inputs of this fence() function, and we can see in the type annotation, that this object is of type AtomicOrder. We can also see a bunch of values inside the switch statements that begin with a dot character, such as .release and .acquire.

    Because these weird values contain a dot character before them, we are asking the zig compiler to infer the types of these values inside the switch statement. Then, the zig compiler is looking into the current context where these values are being used, and trying to infer the types of these values.

    Since they are being used inside a switch statement, the zig compiler looks into the type of the input object given to the switch statement, which is the order object in this case. Because this object have type AtomicOrder, the zig compiler infers that these values are data members from this type AtomicOrder.

    -
    pub inline fn fence(self: *Self, comptime order: AtomicOrder) void {
    -    // many lines of code ...
    -    if (builtin.sanitize_thread) {
    -        const tsan = struct {
    -            extern "c" fn __tsan_acquire(addr: *anyopaque) void;
    -            extern "c" fn __tsan_release(addr: *anyopaque) void;
    -        };
    -
    -        const addr: *anyopaque = self;
    -        return switch (order) {
    -            .unordered, .monotonic => @compileError(
    -                @tagName(order)
    -                ++ " only applies to atomic loads and stores"
    -            ),
    -            .acquire => tsan.__tsan_acquire(addr),
    -            .release => tsan.__tsan_release(addr),
    -            .acq_rel, .seq_cst => {
    -                tsan.__tsan_acquire(addr);
    -                tsan.__tsan_release(addr);
    -            },
    -        };
    -    }
    -
    -    return @fence(order);
    -}
    +
    pub inline fn fence(self: *Self, comptime order: AtomicOrder) void {
    +    // many lines of code ...
    +    if (builtin.sanitize_thread) {
    +        const tsan = struct {
    +            extern "c" fn __tsan_acquire(addr: *anyopaque) void;
    +            extern "c" fn __tsan_release(addr: *anyopaque) void;
    +        };
    +
    +        const addr: *anyopaque = self;
    +        return switch (order) {
    +            .unordered, .monotonic => @compileError(
    +                @tagName(order)
    +                ++ " only applies to atomic loads and stores"
    +            ),
    +            .acquire => tsan.__tsan_acquire(addr),
    +            .release => tsan.__tsan_release(addr),
    +            .acq_rel, .seq_cst => {
    +                tsan.__tsan_acquire(addr);
    +                tsan.__tsan_release(addr);
    +            },
    +        };
    +    }
    +
    +    return @fence(order);
    +}

    This is how basic type inference is done in Zig. If we didn’t use the dot character before the values inside this switch statement, then, we would be forced to explicitly write the data types of these values. For example, instead of writing .release we would have to write AtomicOrder.release. We would have to do this for every single value in this switch statement, and this is a lot of work. That is why type inference is commonly used on switch statements in Zig.

    @@ -919,16 +980,15 @@

    Most languages have a formal way to perform type casting. In Rust for example, we normally use the keyword as, and in C, we normally use the type casting syntax, e.g. (int) x. In Zig, we use the @as() built-in function to cast an object of type “x”, into an object of type “y”.

    This @as() function is the preferred way to perform type conversion (or type casting) in Zig. Because it’s explicit, and, it also performs the casting only if it is unambiguous and safe. To use this function, you just provide the target data type in the first argument, and, the object that you want cast as the second argument.

    -
    const std = @import("std");
    -const expect = std.testing.expect;
    -test {
    -    const x: usize = 500;
    -    const y = @as(u32, x);
    -    try expect(@TypeOf(y) == u32);
    -}
    +
    const std = @import("std");
    +const expect = std.testing.expect;
    +test {
    +    const x: usize = 500;
    +    const y = @as(u32, x);
    +    try expect(@TypeOf(y) == u32);
    +}
    -
    1/1 file79ce58134f59.test_0...OKAll 1 tests passed
    -  d.
    +
    1/1 file3c448aa9d5f.test_0...OKAll 1 tests passed.

    This is the general way to perform type casting in Zig. But remember, @as() works only when casting is unambiguous and safe. There are many situations where these assumptions do not hold. For example,

    @@ -936,32 +996,32 @@

    Therefore, we need to use specialized “casting functions” in such situations. For example, if you want to cast an integer value into a float value, then, you should use the @floatFromInt() function. In the inverse scenario, you should use the @intFromFloat() function.

    In these functions, you just provide the object that you want to cast as input. Then, the target data type of the “type casting operation” is determined by the type annotation of the object where you are saving the results. In the example below, we are casting the object x into a value of type f32, because the object y, which is where we are saving the results, is annotated as an object of type f32.

    -
    const std = @import("std");
    -const expect = std.testing.expect;
    -test {
    -    const x: usize = 565;
    -    const y: f32 = @floatFromInt(x);
    -    try expect(@TypeOf(y) == f32);
    -}
    +
    const std = @import("std");
    +const expect = std.testing.expect;
    +test {
    +    const x: usize = 565;
    +    const y: f32 = @floatFromInt(x);
    +    try expect(@TypeOf(y) == f32);
    +}
    -
    1/1 file79ce286cee5b.test_0...OKAll 1 tests passed
    +
    1/1 file3c4427337b66.test_0...OKAll 1 tests passed
       d.

    Another built-in function that is very useful when performing type casting operations is @ptrCast(). In essence, we use the @as() built-in function when we want to explicit convert (or cast) a Zig value/object from a type “x” to a type “y”, etc. However, pointers (we are going to discuss pointers in more depth in Chapter 6) are a special type of object in Zig, i.e., they are treated differently from “normal objects”.

    Everytime a pointer is involved in some “type casting operation” in Zig, the @ptrCast() function is used. This function works similarly to @floatFromInt(). You just provide the pointer object that you want to cast as input to this function, and the target data type is, once again, determined by the type annotation of the object where the results are being stored.

    -
    const std = @import("std");
    -const expect = std.testing.expect;
    -test {
    -    const bytes align(@alignOf(u32)) = [_]u8{
    -        0x12, 0x12, 0x12, 0x12
    -    };
    -    const u32_ptr: *const u32 = @ptrCast(&bytes);
    -    try expect(@TypeOf(u32_ptr) == *const u32);
    -}
    +
    const std = @import("std");
    +const expect = std.testing.expect;
    +test {
    +    const bytes align(@alignOf(u32)) = [_]u8{
    +        0x12, 0x12, 0x12, 0x12
    +    };
    +    const u32_ptr: *const u32 = @ptrCast(&bytes);
    +    try expect(@TypeOf(u32_ptr) == *const u32);
    +}
    -
    1/1 file79ce1e7313c8.test_0...OKAll 1 tests passed
    +
    1/1 file3c4479f1f6f8.test_0...OKAll 1 tests passed
       d.
    @@ -970,22 +1030,22 @@

    2.6 Modules

    We already talked about what modules are, and also, how to import other modules into your current module via import statements. Every Zig module (i.e., a .zig file) that you write in your project is internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the Zig Standard Library into our current module.

    -
    const std = @import("std");
    +
    const std = @import("std");

    When we want to access the functions and objects from the standard library, we are basically accessing the data members of the struct stored in the std object. That is why we use the same syntax that we use in normal structs, with the dot operator (.) to access the data members and methods of the struct.

    When this “import statement” gets executed, the result of this expression is a struct object that contains the Zig Standard Library modules, global variables, functions, etc. And this struct object gets saved (or stored) inside the constant object named std.

    Take the thread_pool.zig module from the project zap3 as an example. This module is written as if it was a big struct. That is why we have a top-level and public init() method written in this module. The idea is that all top-level functions written in this module are methods from the struct, and all top-level objects and struct declarations are data members of this struct. The module is the struct itself.

    So you would import and use this module by doing something like this:

    -
    const std = @import("std");
    -const ThreadPool = @import("thread_pool.zig");
    -const num_cpus = std.Thread.getCpuCount()
    -    catch @panic("failed to get cpu core count");
    -const num_threads = std.math.cast(u16, num_cpus)
    -    catch std.math.maxInt(u16);
    -const pool = ThreadPool.init(
    -    .{ .max_threads = num_threads }
    -);
    +
    const std = @import("std");
    +const ThreadPool = @import("thread_pool.zig");
    +const num_cpus = std.Thread.getCpuCount()
    +    catch @panic("failed to get cpu core count");
    +const num_threads = std.math.cast(u16, num_cpus)
    +    catch std.math.maxInt(u16);
    +const pool = ThreadPool.init(
    +    .{ .max_threads = num_threads }
    +);
    diff --git a/docs/search.json b/docs/search.json index 616ae938..2c6e11fa 100644 --- a/docs/search.json +++ b/docs/search.json @@ -254,7 +254,7 @@ "href": "Chapters/03-structs.html#sec-structs-and-oop", "title": "2  Control flow, structs, modules and types", "section": "2.3 Structs and OOP", - "text": "2.3 Structs and OOP\nZig is a language more closely related to C (which is a procedural language), than it is to C++ or Java (which are object-oriented languages). Because of that, you do not have advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or class inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C. You give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can also register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object that you create with this new type, will always have these methods available and associated with them.\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which is used to construct (or, to instantiate) every object of this particular class, and we also have a destructor method (or a destructor function), which is the function responsible for destroying every object of this class.\nIn Zig, we normally declare the constructor and the destructor methods of our structs, by declaring an init() and a deinit() methods inside the struct. This is just a naming convention that you will find across the entire Zig Standard Library. So, in Zig, the init() method of a struct is normally the constructor method of the class represented by this struct. While the deinit() method is the method used for destroying an existing instance of that struct.\nThe init() and deinit() methods are both used extensively in Zig code, and you will see both of them being used when we talk about allocators in Section 3.3. But, as another example, let’s build a simple User struct to represent a user of some sort of system.\nIf you look at the User struct below, you can see the struct keyword. Notice the data members of this struct: id, name and email. Every data member has its type explicitly annotated, with the colon character (:) syntax that we described earlier in Section 1.2.2. But also notice that every line in the struct body that describes a data member, ends with a comma character (,). So every time you declare a data member in your Zig code, always end the line with a comma character, instead of ending it with the traditional semicolon character (;).\nNext, we have registered an init() function as a method of this User struct. This init() method is the constructor method that we will use to instantiate every new User object. That is why this init() function returns a new User object as result.\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n pub fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n pub fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n\npedro\n\n\nThe pub keyword plays an important role in struct declarations, and OOP in Zig. Every method that you declare in your struct that is marked with the keyword pub, becomes a public method of this particular struct.\nSo every method that you create inside your struct, is, at first, a private method of that struct. Meaning that, this method can only be called from within this struct. But, if you mark this method as public, with the keyword pub, then, you can call the method directly from an instance of the User struct.\nIn other words, the functions marked by the keyword pub are members of the public API of that struct. For example, if I did not mark the print_name() method as public, then, I could not execute the line u.print_name(). Because I would not be authorized to call this method directly in my code.\n\n2.3.1 Anonymous struct literals\nYou can declare a struct object as a literal value. When we do that, we normally specify the data type of this struct literal by writing its data type just before the opening curly brace. For example, I could write a struct literal value of the type User that we have defined in the previous section like this:\n\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a struct literal, but not specify explicitly the type of this particular struct. An anonymous struct is written by using the syntax .{}. So, we essentially replaced the explicit type of the struct literal with a dot character (.).\nAs we described in Section 2.4, when you put a dot before a struct literal, the type of this struct literal is automatically inferred by the zig compiler. In essence, the zig compiler will look for some hint of what is the type of that struct. This hint can be the type annotation of a function argument, or the return type annotation of the function that you are using, or the type annotation of an existing object. If the compiler does find such type annotation, it will use this type in your literal struct.\nAnonymous structs are very commonly used as inputs to function arguments in Zig. One example that you have seen already constantly, is the print() function from the stdout object. This function takes two arguments. The first argument, is a template string, which should contain string format specifiers in it, which tells how the values provided in the second argument should be printed into the message.\nWhile the second argument is a struct literal that lists the values to be printed into the template message specified in the first argument. You normally want to use an anonymous struct literal here, so that the zig compiler do the job of specifying the type of this particular anonymous struct for you.\n\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n\nHello, world!\n\n\n\n\n2.3.2 Struct declarations must be constant\nTypes in Zig must be const or comptime (we are going to talk more about comptime in Section 12.1). What this means is that you cannot create a new data type, and mark it as variable with the var keyword. So struct declarations are always constant. You cannot declare a new struct type using the var keyword. It must be const.\nIn the Vec3 example below, this declaration is allowed because I’m using the const keyword to declare this new data type.\n\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n\n\n\n2.3.3 The self method argument\nIn every language that have OOP, when we declare a method of some class or struct, we usually declare this method as a function that has a self argument. This self argument is the reference to the object itself from which the method is being called from.\nIt’s not mandatory to use this self argument. But why would you not use this self argument? There is no reason to not use it. Because the only way to get access to the data stored in the data members of your struct is to access them through this self argument. If you don’t need to use the data in the data members of your struct inside your method, you very likely don’t need a method. You can just declare this logic as a simple function, outside of your struct declaration.\nTake the Vec3 struct below. Inside this Vec3 struct we declared a method named distance(). This method calculates the distance between two Vec3 objects, by following the distance formula in euclidean space. Notice that this distance() method takes two Vec3 objects as input, self and other.\n\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n\nThe self argument corresponds to the Vec3 object from which this distance() method is being called from. While the other is a separate Vec3 object that is given as input to this method. In the example below, the self argument corresponds to the object v1, because the distance() method is being called from the v1 object, while the other argument corresponds to the object v2.\n\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n\nDistance: 3.3970575502926055\n\n\n2.3.4 About the struct state\nSometimes you don’t need to care about the state of your struct object. Sometimes, you just need to instantiate and use the objects, without altering their state. You can notice that when you have methods inside your struct declaration that might use the values that are present in the data members, but they do not alter the values in these data members of the struct in anyway.\nThe Vec3 struct that was presented in Section 2.3.3 is an example of that. This struct have a single method named distance(), and this method does use the values present in all three data members of the struct (x, y and z). But at the same time, this method does not change the values of these data members at any point.\nAs a result of that, when we create Vec3 objects we usually create them as constant objects, like the v1 and v2 objects presented in Section 2.3.3. We can create them as variable objects with the var keyword, if we want to. But because the methods of this Vec3 struct do not change the state of the objects in any point, it’s unnecessary to mark them as variable objects.\nBut why? Why am I talking about this here? It’s because the self argument in the methods are affected depending on whether the methods present in a struct change or don’t change the state of the object itself. More specifically, when you have a method in a struct that changes the state of the object (i.e., changes the value of a data member), the self argument in this method must be annotated in a different manner.\nAs I described in Section 2.3.3, the self argument in methods of a struct is the argument that receives as input the object from which the method was called from. We usually annotate this argument in the methods by writing self, followed by the colon character (:), and the data type of the struct to which the method belongs to (e.g. User, Vec3, etc.).\nIf we take the Vec3 struct that we defined in the previous section as an example, we can see in the distance() method that this self argument is annotated as self: Vec3. Because the state of the Vec3 object is never altered by this method.\nBut what if we do have a method that alters the state of the object, by altering the values of its data members, how should we annotate self in this instance? The answer is: “we should annotate self as a pointer of x, instead of just x”. In other words, you should annotate self as self: *x, instead of annotating it as self: x.\nIf we create a new method inside the Vec3 object that, for example, expands the vector by multiplying its coordinates by a factor of two, then, we need to follow this rule specified in the previous paragraph. The code example below demonstrates this idea:\n\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n\nNotice in the code example above that we have added a new method to our Vec3 struct named twice(). This method doubles the coordinate values of our vector object. In the case of the twice() method, we annotated the self argument as *Vec3, indicating that this argument receives a pointer (or a reference, if you prefer to call it this way) to a Vec3 object as input.\n\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n\nDoubled: 8.4\nNow, if you change the self argument in this twice() method to self: Vec3, like in the distance() method, you will get the compiler error exposed below as result. Notice that this error message is showing a line from the twice() method body, indicating that you cannot alter the value of the x data member.\n\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\nThis error message indicates that the x data member belongs to a constant object, and, because of that, it cannot be changed. Ultimately, this error message is telling us that the self argument is constant.\nIf you take some time, and think hard about this error message, you will understand it. You already have the tools to understand why we are getting this error message. We have talked about it already in Section 2.2. So remember, every function argument is immutable in Zig, and self is no exception to this rule.\nIn this example, we marked the v3 object as a variable object. But this does not matter. Because it’s not about the input object, it’s about the function argument.\nThe problem begins when we try to alter the value of self directly, which is a function argument, and, every function argument is immutable by default. You may ask yourself how can we overcome this barrier, and once again, the solution was also discussed in Section 2.2. We overcome this barrier, by explicitly marking the self argument as a pointer.\n\n\n\n\n\n\nNote\n\n\n\nIf a method of your x struct alters the state of the object, by changing the value of any data member, then, remember to use self: *x, instead of self: x in the function signature of this method.\n\n\nYou could also interpret the content discussed in this section as: “if you need to alter the state of your x struct object in one of its methods, you must explicitly pass the x struct object by reference to the self argument of this method”.", + "text": "2.3 Structs and OOP\nZig is a language more closely related to C (which is a procedural language), than it is to C++ or Java (which are object-oriented languages). Because of that, you do not have advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or class inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C. You give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can also register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object that you create with this new type, will always have these methods available and associated with them.\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which is used to construct (or, to instantiate) every object of this particular class, and we also have a destructor method (or a destructor function), which is the function responsible for destroying every object of this class.\nIn Zig, we normally declare the constructor and the destructor methods of our structs, by declaring an init() and a deinit() methods inside the struct. This is just a naming convention that you will find across the entire Zig Standard Library. So, in Zig, the init() method of a struct is normally the constructor method of the class represented by this struct. While the deinit() method is the method used for destroying an existing instance of that struct.\nThe init() and deinit() methods are both used extensively in Zig code, and you will see both of them being used when we talk about allocators in Section 3.3. But, as another example, let’s build a simple User struct to represent a user of some sort of system.\nIf you look at the User struct below, you can see the struct keyword. Notice the data members of this struct: id, name and email. Every data member has its type explicitly annotated, with the colon character (:) syntax that we described earlier in Section 1.2.2. But also notice that every line in the struct body that describes a data member, ends with a comma character (,). So every time you declare a data member in your Zig code, always end the line with a comma character, instead of ending it with the traditional semicolon character (;).\nNext, we have registered an init() function as a method of this User struct. This init() method is the constructor method that we will use to instantiate every new User object. That is why this init() function returns a new User object as result.\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n\npedro\n\n\n\n2.3.1 The pub keyword\nThe pub keyword plays an important role in struct declarations, and OOP in Zig. In essence, this keyword is short for “public”, and it makes an item/component available outside of the module where this item/component is declared. In other words, if I don’t apply the pub keyword on something, it means that this “something” is available to be called/used only from within the module where this “something” is declared.\nTo demonstrate the effect of this keyword let’s focus again on the User struct that we have declared on the previous section. For our example here, let’s suppose that this User struct is declared inside a Zig module named user.zig. If I don’t use the pub keyword on the User struct, it means that I can create an User object, and call it’s methods (print_name() and init()) only from within the module where the User struct is declared, which in this case is the user.zig module.\nThis is why the previous code example works fine. Because we declare and also use the User struct inside the same module. But problems start to arise when we try to import and call/use this struct from another module. For example, if I create a new module called register.zig, and import the user.zig module into it, and try to annotate any variable with the User type, I get an error from the compiler.\n// register.zig\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = undefined;\n _ = u;\n}\nregister.zig:3:18: error: 'User' is not marked 'pub'\n const u: user.User = undefined;\n ~~~~^~~~~\nuser.zig:3:1: note: declared here\nconst User = struct {\n^~~~~\nTherefore, if you want to use something outside of the module where this “something” is declared, you have to mark it with the pub keyword. This “something” can be a module, a struct, a function, an object, etc.\nFor our example here, if we go back to the user.zig module, and add the pub keyword to the User struct declaration, then, I can successfully compile the register.zig module.\n// user.zig\n// Added the `pub` keyword to `User`\npub const User = struct {\n// ...\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = undefined;\n _ = u;\n}\nNow, what do you think it will happen if I try to actually call from register.zig any of the methods of the User struct? For example, if I try to call the init() method? The answer is: I get a similar error message, warning me that the init() method is not marked as pub, as you can see below:\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = user.User.init(\n 1, \"pedro\", \"email@gmail.com\"\n );\n _ = u;\n}\nregister.zig:3:35: error: 'init' is not marked 'pub'\n const u: user.User = user.User.init(\n ~~~~~~~~~^~~~~\nuser.zig:8:5: note: declared here\n fn init(id: u64,\n ^~~~~~~\nThus, just because we have applied the pub keyword on the struct declaration, this does not make the methods of that struct public as well. If we want to use any method from a struct (such as the init() method) outside of the module where this struct is declared, we have to mark this method with the pub keyword as well.\nGoing back to the user.zig module, and marking both the init() and print_name() methods with the pub keyword, makes them both available to the outside world, and, as consequence, makes the previous code example work.\n// user.zig\n// Added the `pub` keyword to `User.init`\n pub fn init(\n// ...\n// Added the `pub` keyword to `User.print_name`\n pub fn print_name(self: User) !void {\n// ...\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = user.User.init(\n 1, \"pedro\", \"email@gmail.com\"\n );\n _ = u;\n}\n\n\n2.3.2 Anonymous struct literals\nYou can declare a struct object as a literal value. When we do that, we normally specify the data type of this struct literal by writing its data type just before the opening curly brace. For example, I could write a struct literal value of the type User that we have defined in the previous section like this:\n\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a struct literal, but not specify explicitly the type of this particular struct. An anonymous struct is written by using the syntax .{}. So, we essentially replaced the explicit type of the struct literal with a dot character (.).\nAs we described in Section 2.4, when you put a dot before a struct literal, the type of this struct literal is automatically inferred by the zig compiler. In essence, the zig compiler will look for some hint of what is the type of that struct. This hint can be the type annotation of a function argument, or the return type annotation of the function that you are using, or the type annotation of an existing object. If the compiler does find such type annotation, it will use this type in your literal struct.\nAnonymous structs are very commonly used as inputs to function arguments in Zig. One example that you have seen already constantly, is the print() function from the stdout object. This function takes two arguments. The first argument, is a template string, which should contain string format specifiers in it, which tells how the values provided in the second argument should be printed into the message.\nWhile the second argument is a struct literal that lists the values to be printed into the template message specified in the first argument. You normally want to use an anonymous struct literal here, so that the zig compiler do the job of specifying the type of this particular anonymous struct for you.\n\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n\nHello, world!\n\n\n\n\n2.3.3 Struct declarations must be constant\nTypes in Zig must be const or comptime (we are going to talk more about comptime in Section 12.1). What this means is that you cannot create a new data type, and mark it as variable with the var keyword. So struct declarations are always constant. You cannot declare a new struct type using the var keyword. It must be const.\nIn the Vec3 example below, this declaration is allowed because I’m using the const keyword to declare this new data type.\n\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n\n\n\n2.3.4 The self method argument\nIn every language that have OOP, when we declare a method of some class or struct, we usually declare this method as a function that has a self argument. This self argument is the reference to the object itself from which the method is being called from.\nIt’s not mandatory to use this self argument. But why would you not use this self argument? There is no reason to not use it. Because the only way to get access to the data stored in the data members of your struct is to access them through this self argument. If you don’t need to use the data in the data members of your struct inside your method, you very likely don’t need a method. You can just declare this logic as a simple function, outside of your struct declaration.\nTake the Vec3 struct below. Inside this Vec3 struct we declared a method named distance(). This method calculates the distance between two Vec3 objects, by following the distance formula in euclidean space. Notice that this distance() method takes two Vec3 objects as input, self and other.\n\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n\nThe self argument corresponds to the Vec3 object from which this distance() method is being called from. While the other is a separate Vec3 object that is given as input to this method. In the example below, the self argument corresponds to the object v1, because the distance() method is being called from the v1 object, while the other argument corresponds to the object v2.\n\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n\nDistance: 3.3970575502926055\n\n\n2.3.5 About the struct state\nSometimes you don’t need to care about the state of your struct object. Sometimes, you just need to instantiate and use the objects, without altering their state. You can notice that when you have methods inside your struct declaration that might use the values that are present in the data members, but they do not alter the values in these data members of the struct in anyway.\nThe Vec3 struct that was presented in Section 2.3.4 is an example of that. This struct have a single method named distance(), and this method does use the values present in all three data members of the struct (x, y and z). But at the same time, this method does not change the values of these data members at any point.\nAs a result of that, when we create Vec3 objects we usually create them as constant objects, like the v1 and v2 objects presented in Section 2.3.4. We can create them as variable objects with the var keyword, if we want to. But because the methods of this Vec3 struct do not change the state of the objects in any point, it’s unnecessary to mark them as variable objects.\nBut why? Why am I talking about this here? It’s because the self argument in the methods are affected depending on whether the methods present in a struct change or don’t change the state of the object itself. More specifically, when you have a method in a struct that changes the state of the object (i.e., changes the value of a data member), the self argument in this method must be annotated in a different manner.\nAs I described in Section 2.3.4, the self argument in methods of a struct is the argument that receives as input the object from which the method was called from. We usually annotate this argument in the methods by writing self, followed by the colon character (:), and the data type of the struct to which the method belongs to (e.g. User, Vec3, etc.).\nIf we take the Vec3 struct that we defined in the previous section as an example, we can see in the distance() method that this self argument is annotated as self: Vec3. Because the state of the Vec3 object is never altered by this method.\nBut what if we do have a method that alters the state of the object, by altering the values of its data members, how should we annotate self in this instance? The answer is: “we should annotate self as a pointer of x, instead of just x”. In other words, you should annotate self as self: *x, instead of annotating it as self: x.\nIf we create a new method inside the Vec3 object that, for example, expands the vector by multiplying its coordinates by a factor of two, then, we need to follow this rule specified in the previous paragraph. The code example below demonstrates this idea:\n\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n\nNotice in the code example above that we have added a new method to our Vec3 struct named twice(). This method doubles the coordinate values of our vector object. In the case of the twice() method, we annotated the self argument as *Vec3, indicating that this argument receives a pointer (or a reference, if you prefer to call it this way) to a Vec3 object as input.\n\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n\nDoubled: 8.4\nNow, if you change the self argument in this twice() method to self: Vec3, like in the distance() method, you will get the compiler error exposed below as result. Notice that this error message is showing a line from the twice() method body, indicating that you cannot alter the value of the x data member.\n\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\nThis error message indicates that the x data member belongs to a constant object, and, because of that, it cannot be changed. Ultimately, this error message is telling us that the self argument is constant.\nIf you take some time, and think hard about this error message, you will understand it. You already have the tools to understand why we are getting this error message. We have talked about it already in Section 2.2. So remember, every function argument is immutable in Zig, and self is no exception to this rule.\nIn this example, we marked the v3 object as a variable object. But this does not matter. Because it’s not about the input object, it’s about the function argument.\nThe problem begins when we try to alter the value of self directly, which is a function argument, and, every function argument is immutable by default. You may ask yourself how can we overcome this barrier, and once again, the solution was also discussed in Section 2.2. We overcome this barrier, by explicitly marking the self argument as a pointer.\n\n\n\n\n\n\nNote\n\n\n\nIf a method of your x struct alters the state of the object, by changing the value of any data member, then, remember to use self: *x, instead of self: x in the function signature of this method.\n\n\nYou could also interpret the content discussed in this section as: “if you need to alter the state of your x struct object in one of its methods, you must explicitly pass the x struct object by reference to the self argument of this method”.", "crumbs": [ "2  Control flow, structs, modules and types" ] @@ -264,7 +264,7 @@ "href": "Chapters/03-structs.html#sec-type-inference", "title": "2  Control flow, structs, modules and types", "section": "2.4 Type inference", - "text": "2.4 Type inference\nZig is a strongly typed language. But, there are some situations where you don’t have to explicitly write the type of every single object in your source code, as you would expect from a traditional strongly typed language, such as C and C++.\nIn some situations, the zig compiler can use type inference to solve the data types for you, easing some of the burden that you carry as a developer. The most common way this happens is through function arguments that receive struct objects as input.\nIn general, type inference in Zig is done by using the dot character (.). Everytime you see a dot character written before a struct literal, or before an enum value, or something like that, you know that this dot character is playing a special part in this place. More specifically, it’s telling the zig compiler something along the lines of: “Hey! Can you infer the type of this value for me? Please!”. In other words, this dot character is playing a similar role as the auto keyword in C++.\nI gave you some examples of this in Section 2.3.1, where we used anonymous struct literals. Anonymous struct literals are, struct literals that use type inference to infer the exact type of this particular struct literal. This type inference is done by looking for some minimal hint of the correct data type to be used. You could say that the zig compiler looks for any neighbouring type annotation that might tell it what the correct type would be.\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in Section 2.1.2). I also gave some other examples of type inference in Section 2.1.2, where we were inferring the data types of enum values listed inside of switch statements (e.g. .DE). But as another example, take a look at this fence() function reproduced below, which comes from the atomic.zig module2 of the Zig Standard Library.\nThere are a lot of things in this function that we haven’t talked about yet, such as: what comptime means? inline? extern? Let’s just ignore all of these things, and focus solely on the switch statement that is inside this function.\nWe can see that this switch statement uses the order object as input. This order object is one of the inputs of this fence() function, and we can see in the type annotation, that this object is of type AtomicOrder. We can also see a bunch of values inside the switch statements that begin with a dot character, such as .release and .acquire.\nBecause these weird values contain a dot character before them, we are asking the zig compiler to infer the types of these values inside the switch statement. Then, the zig compiler is looking into the current context where these values are being used, and trying to infer the types of these values.\nSince they are being used inside a switch statement, the zig compiler looks into the type of the input object given to the switch statement, which is the order object in this case. Because this object have type AtomicOrder, the zig compiler infers that these values are data members from this type AtomicOrder.\n\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n\nThis is how basic type inference is done in Zig. If we didn’t use the dot character before the values inside this switch statement, then, we would be forced to explicitly write the data types of these values. For example, instead of writing .release we would have to write AtomicOrder.release. We would have to do this for every single value in this switch statement, and this is a lot of work. That is why type inference is commonly used on switch statements in Zig.", + "text": "2.4 Type inference\nZig is a strongly typed language. But, there are some situations where you don’t have to explicitly write the type of every single object in your source code, as you would expect from a traditional strongly typed language, such as C and C++.\nIn some situations, the zig compiler can use type inference to solve the data types for you, easing some of the burden that you carry as a developer. The most common way this happens is through function arguments that receive struct objects as input.\nIn general, type inference in Zig is done by using the dot character (.). Everytime you see a dot character written before a struct literal, or before an enum value, or something like that, you know that this dot character is playing a special part in this place. More specifically, it’s telling the zig compiler something along the lines of: “Hey! Can you infer the type of this value for me? Please!”. In other words, this dot character is playing a similar role as the auto keyword in C++.\nI gave you some examples of this in Section 2.3.2, where we used anonymous struct literals. Anonymous struct literals are, struct literals that use type inference to infer the exact type of this particular struct literal. This type inference is done by looking for some minimal hint of the correct data type to be used. You could say that the zig compiler looks for any neighbouring type annotation that might tell it what the correct type would be.\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in Section 2.1.2). I also gave some other examples of type inference in Section 2.1.2, where we were inferring the data types of enum values listed inside of switch statements (e.g. .DE). But as another example, take a look at this fence() function reproduced below, which comes from the atomic.zig module2 of the Zig Standard Library.\nThere are a lot of things in this function that we haven’t talked about yet, such as: what comptime means? inline? extern? Let’s just ignore all of these things, and focus solely on the switch statement that is inside this function.\nWe can see that this switch statement uses the order object as input. This order object is one of the inputs of this fence() function, and we can see in the type annotation, that this object is of type AtomicOrder. We can also see a bunch of values inside the switch statements that begin with a dot character, such as .release and .acquire.\nBecause these weird values contain a dot character before them, we are asking the zig compiler to infer the types of these values inside the switch statement. Then, the zig compiler is looking into the current context where these values are being used, and trying to infer the types of these values.\nSince they are being used inside a switch statement, the zig compiler looks into the type of the input object given to the switch statement, which is the order object in this case. Because this object have type AtomicOrder, the zig compiler infers that these values are data members from this type AtomicOrder.\n\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n\nThis is how basic type inference is done in Zig. If we didn’t use the dot character before the values inside this switch statement, then, we would be forced to explicitly write the data types of these values. For example, instead of writing .release we would have to write AtomicOrder.release. We would have to do this for every single value in this switch statement, and this is a lot of work. That is why type inference is commonly used on switch statements in Zig.", "crumbs": [ "2  Control flow, structs, modules and types" ] @@ -274,7 +274,7 @@ "href": "Chapters/03-structs.html#sec-type-cast", "title": "2  Control flow, structs, modules and types", "section": "2.5 Type casting", - "text": "2.5 Type casting\nIn this section, I want to discuss type casting (or, type conversion) with you. We use type casting when we have an object of type “x”, and we want to convert it into an object of type “y”, i.e., we want to change the data type of the object.\nMost languages have a formal way to perform type casting. In Rust for example, we normally use the keyword as, and in C, we normally use the type casting syntax, e.g. (int) x. In Zig, we use the @as() built-in function to cast an object of type “x”, into an object of type “y”.\nThis @as() function is the preferred way to perform type conversion (or type casting) in Zig. Because it’s explicit, and, it also performs the casting only if it is unambiguous and safe. To use this function, you just provide the target data type in the first argument, and, the object that you want cast as the second argument.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n\n1/1 file79ce58134f59.test_0...OKAll 1 tests passed\n d.\n\n\nThis is the general way to perform type casting in Zig. But remember, @as() works only when casting is unambiguous and safe. There are many situations where these assumptions do not hold. For example,\nwhen casting an integer value into a float value, or vice-versa, it’s not clear to the compiler how to perform this conversion safely.\nTherefore, we need to use specialized “casting functions” in such situations. For example, if you want to cast an integer value into a float value, then, you should use the @floatFromInt() function. In the inverse scenario, you should use the @intFromFloat() function.\nIn these functions, you just provide the object that you want to cast as input. Then, the target data type of the “type casting operation” is determined by the type annotation of the object where you are saving the results. In the example below, we are casting the object x into a value of type f32, because the object y, which is where we are saving the results, is annotated as an object of type f32.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n\n1/1 file79ce286cee5b.test_0...OKAll 1 tests passed\n d.\n\n\nAnother built-in function that is very useful when performing type casting operations is @ptrCast(). In essence, we use the @as() built-in function when we want to explicit convert (or cast) a Zig value/object from a type “x” to a type “y”, etc. However, pointers (we are going to discuss pointers in more depth in Chapter 6) are a special type of object in Zig, i.e., they are treated differently from “normal objects”.\nEverytime a pointer is involved in some “type casting operation” in Zig, the @ptrCast() function is used. This function works similarly to @floatFromInt(). You just provide the pointer object that you want to cast as input to this function, and the target data type is, once again, determined by the type annotation of the object where the results are being stored.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n\n1/1 file79ce1e7313c8.test_0...OKAll 1 tests passed\n d.", + "text": "2.5 Type casting\nIn this section, I want to discuss type casting (or, type conversion) with you. We use type casting when we have an object of type “x”, and we want to convert it into an object of type “y”, i.e., we want to change the data type of the object.\nMost languages have a formal way to perform type casting. In Rust for example, we normally use the keyword as, and in C, we normally use the type casting syntax, e.g. (int) x. In Zig, we use the @as() built-in function to cast an object of type “x”, into an object of type “y”.\nThis @as() function is the preferred way to perform type conversion (or type casting) in Zig. Because it’s explicit, and, it also performs the casting only if it is unambiguous and safe. To use this function, you just provide the target data type in the first argument, and, the object that you want cast as the second argument.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n\n1/1 file3c448aa9d5f.test_0...OKAll 1 tests passed.\n\n\nThis is the general way to perform type casting in Zig. But remember, @as() works only when casting is unambiguous and safe. There are many situations where these assumptions do not hold. For example,\nwhen casting an integer value into a float value, or vice-versa, it’s not clear to the compiler how to perform this conversion safely.\nTherefore, we need to use specialized “casting functions” in such situations. For example, if you want to cast an integer value into a float value, then, you should use the @floatFromInt() function. In the inverse scenario, you should use the @intFromFloat() function.\nIn these functions, you just provide the object that you want to cast as input. Then, the target data type of the “type casting operation” is determined by the type annotation of the object where you are saving the results. In the example below, we are casting the object x into a value of type f32, because the object y, which is where we are saving the results, is annotated as an object of type f32.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n\n1/1 file3c4427337b66.test_0...OKAll 1 tests passed\n d.\n\n\nAnother built-in function that is very useful when performing type casting operations is @ptrCast(). In essence, we use the @as() built-in function when we want to explicit convert (or cast) a Zig value/object from a type “x” to a type “y”, etc. However, pointers (we are going to discuss pointers in more depth in Chapter 6) are a special type of object in Zig, i.e., they are treated differently from “normal objects”.\nEverytime a pointer is involved in some “type casting operation” in Zig, the @ptrCast() function is used. This function works similarly to @floatFromInt(). You just provide the pointer object that you want to cast as input to this function, and the target data type is, once again, determined by the type annotation of the object where the results are being stored.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n\n1/1 file3c4479f1f6f8.test_0...OKAll 1 tests passed\n d.", "crumbs": [ "2  Control flow, structs, modules and types" ] From dc1d0863a231ba0dd2d7435d522cb1a678c34dfb Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sat, 8 Mar 2025 12:07:28 -0300 Subject: [PATCH 117/151] Fix indentation --- Chapters/03-structs.qmd | 4 ++-- _freeze/Chapters/03-structs/execute-results/html.json | 4 ++-- docs/Chapters/03-structs.html | 11 ++++++----- docs/search.json | 4 ++-- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Chapters/03-structs.qmd b/Chapters/03-structs.qmd index ba5f7069..56c67e00 100644 --- a/Chapters/03-structs.qmd +++ b/Chapters/03-structs.qmd @@ -760,8 +760,8 @@ const User = struct { email: []const u8, fn init(id: u64, - name: []const u8, - email: []const u8) User { + name: []const u8, + email: []const u8) User { return User { .id = id, diff --git a/_freeze/Chapters/03-structs/execute-results/html.json b/_freeze/Chapters/03-structs/execute-results/html.json index fbe83947..a05f2337 100644 --- a/_freeze/Chapters/03-structs/execute-results/html.json +++ b/_freeze/Chapters/03-structs/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "10ffcb221f40a28afe7a41688091c355", + "hash": "eb1d22d8dc0121e7c7768b70c606a801", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `role`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object has type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e., four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n```\n:::\n\n\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It's important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n else => {\n try stdout.print(\n \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n );\n },\n}\n```\n:::\n\n\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n```\n:::\n\n\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function gets executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, it's worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression gets executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n```\n:::\n\n\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that gets printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n```\n:::\n\n\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n // code to execute\n}\n```\n:::\n\n\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It's the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e., the logical test is equal to false), the function raises an assertion error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e., constant) object\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n x = x + 2;\n return x;\n}\n\npub fn main() !void {\n const y = add2(4);\n std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n x = x + 2;\n ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e., `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n const d: u32 = 2;\n x.* = x.* + d;\n}\n\npub fn main() !void {\n var x: u32 = 4;\n add2(&x);\n std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### The `pub` keyword\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nIn essence, this keyword is short for \"public\", and it makes an item/component available outside of the\nmodule where this item/component is declared. In other words, if I don't apply the `pub` keyword on\nsomething, it means that this \"something\" is available to be called/used only from within the module\nwhere this \"something\" is declared.\n\nTo demonstrate the effect of this keyword let's focus again on the `User` struct that we have\ndeclared on the previous section. For our example here, let's suppose that this `User` struct is declared inside\na Zig module named `user.zig`. If I don't use the `pub` keyword on the `User` struct, it means that I can create\nan `User` object, and call it's methods (`print_name()` and `init()`) only from within the module where the `User`\nstruct is declared, which in this case is the `user.zig` module.\n\nThis is why the previous code example works fine. Because we declare and also use the `User` struct\ninside the same module. But problems start to arise when we try to import and call/use this struct\nfrom another module. For example, if I create a new module called `register.zig`, and import the `user.zig`\nmodule into it, and try to annotate any variable with the `User` type, I get an error from the compiler.\n\n```zig\n// register.zig\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = undefined;\n _ = u;\n}\n```\n\n```\nregister.zig:3:18: error: 'User' is not marked 'pub'\n const u: user.User = undefined;\n ~~~~^~~~~\nuser.zig:3:1: note: declared here\nconst User = struct {\n^~~~~\n```\n\nTherefore, if you want to use something outside of the module where this \"something\" is declared,\nyou have to mark it with the `pub` keyword. This \"something\" can be a module,\na struct, a function, an object, etc.\n\nFor our example here, if we go back to the `user.zig` module, and add the `pub` keyword\nto the `User` struct declaration, then, I can successfully compile the `register.zig` module.\n\n```zig\n// user.zig\n// Added the `pub` keyword to `User`\npub const User = struct {\n// ...\n```\n\n```zig\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = undefined;\n _ = u;\n}\n```\n\n\nNow, what do you think it will happen if I try to actually call from `register.zig` any of the methods\nof the `User` struct? For example, if I try to call the `init()` method? The answer is: I get a similar error message,\nwarning me that the `init()` method is not marked as `pub`, as you can see below:\n\n```zig\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = user.User.init(\n 1, \"pedro\", \"email@gmail.com\"\n );\n _ = u;\n}\n```\n\n```\nregister.zig:3:35: error: 'init' is not marked 'pub'\n const u: user.User = user.User.init(\n ~~~~~~~~~^~~~~\nuser.zig:8:5: note: declared here\n fn init(id: u64,\n ^~~~~~~\n```\n\nThus, just because we have applied the `pub` keyword on the struct declaration,\nthis does not make the methods of that struct public as well. If we want to use\nany method from a struct (such as the `init()` method) outside of the module\nwhere this struct is declared, we have to mark this method with the `pub` keyword\nas well.\n\nGoing back to the `user.zig` module, and marking both the `init()` and `print_name()`\nmethods with the `pub` keyword, makes them both available to the outside world, and,\nas consequence, makes the previous code example work.\n\n\n```zig\n// user.zig\n// Added the `pub` keyword to `User.init`\n pub fn init(\n// ...\n// Added the `pub` keyword to `User.print_name`\n pub fn print_name(self: User) !void {\n// ...\n```\n\n```zig\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = user.User.init(\n 1, \"pedro\", \"email@gmail.com\"\n );\n _ = u;\n}\n```\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n```\n:::\n\n\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt's not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n```\n:::\n\n\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods are affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e., changes the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n```\n:::\n\n\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it's not about the input object, it's about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special part in this place. More specifically, it's\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and trying\nto infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n```\n:::\n\n\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e., we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it's explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3c448aa9d5f.test_0...OKAll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe. There are many situations where these assumptions do not hold. For example,\n\nwhen casting an integer value into a float value, or vice-versa, it's not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3c4427337b66.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e., they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3c4479f1f6f8.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e., a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" gets executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object gets saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n .{ .max_threads = num_threads }\n);\n```\n:::\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n try stdout.print(\n \"x > 10!\\n\", .{}\n );\n} else {\n try stdout.print(\n \"x <= 10!\\n\", .{}\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n var area: []const u8 = undefined;\n const role = Role.SE;\n switch (role) {\n .PM, .SE, .DPE, .PO => {\n area = \"Platform\";\n },\n .DE, .DA => {\n area = \"Data & Analytics\";\n },\n .KS => {\n area = \"Sales\";\n },\n }\n try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `role`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object has type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e., four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n // Many lines ...\n switch (byte) {\n '\\n' => try writer.writeAll(\"␊\"),\n '\\r' => try writer.writeAll(\"␍\"),\n '\\t' => try writer.writeAll(\"␉\"),\n else => try writer.writeByte('.'),\n }\n}\n```\n:::\n\n\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 1, 2 => \"beginner\",\n 3 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n @panic(\"Not supported level!\");\n ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It's important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n 0...25 => \"beginner\",\n 26...75 => \"intermediary\",\n 76...100 => \"professional\",\n else => {\n @panic(\"Not supported level!\");\n },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n 1 => {\n try stdout.print(\"First branch\\n\", .{});\n continue :xsw 2;\n },\n 2 => continue :xsw 3,\n 3 => return,\n 4 => {},\n else => {\n try stdout.print(\n \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n );\n },\n}\n```\n:::\n\n\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n defer std.debug.print(\n \"Exiting function ...\\n\", .{}\n );\n try stdout.print(\"Adding some numbers ...\\n\", .{});\n const x = 2 + 2; _ = x;\n try stdout.print(\"Multiplying ...\\n\", .{});\n const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n try foo();\n}\n```\n:::\n\n\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function gets executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, it's worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression gets executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n defer i = 2;\n try foo();\n}\n```\n:::\n\n\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that gets printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n var i: usize = 1;\n defer i = 2;\n errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n try foo();\n}\n```\n:::\n\n\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n return error.FooError;\n ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n // code to execute\n}\n```\n:::\n\n\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n try stdout.print(\"{d} | \", .{i});\n i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It's the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e., the logical test is equal to false), the function raises an assertion error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n if (i == 10) {\n break;\n }\n i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n if ((i % 2) == 0) {\n continue;\n }\n try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e., constant) object\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n x = x + 2;\n return x;\n}\n\npub fn main() !void {\n const y = add2(4);\n std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n x = x + 2;\n ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e., `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n const d: u32 = 2;\n x.* = x.* + d;\n}\n\npub fn main() !void {\n var x: u32 = 4;\n add2(&x);\n std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### The `pub` keyword\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nIn essence, this keyword is short for \"public\", and it makes an item/component available outside of the\nmodule where this item/component is declared. In other words, if I don't apply the `pub` keyword on\nsomething, it means that this \"something\" is available to be called/used only from within the module\nwhere this \"something\" is declared.\n\nTo demonstrate the effect of this keyword let's focus again on the `User` struct that we have\ndeclared on the previous section. For our example here, let's suppose that this `User` struct is declared inside\na Zig module named `user.zig`. If I don't use the `pub` keyword on the `User` struct, it means that I can create\nan `User` object, and call it's methods (`print_name()` and `init()`) only from within the module where the `User`\nstruct is declared, which in this case is the `user.zig` module.\n\nThis is why the previous code example works fine. Because we declare and also use the `User` struct\ninside the same module. But problems start to arise when we try to import and call/use this struct\nfrom another module. For example, if I create a new module called `register.zig`, and import the `user.zig`\nmodule into it, and try to annotate any variable with the `User` type, I get an error from the compiler.\n\n```zig\n// register.zig\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = undefined;\n _ = u;\n}\n```\n\n```\nregister.zig:3:18: error: 'User' is not marked 'pub'\n const u: user.User = undefined;\n ~~~~^~~~~\nuser.zig:3:1: note: declared here\nconst User = struct {\n^~~~~\n```\n\nTherefore, if you want to use something outside of the module where this \"something\" is declared,\nyou have to mark it with the `pub` keyword. This \"something\" can be a module,\na struct, a function, an object, etc.\n\nFor our example here, if we go back to the `user.zig` module, and add the `pub` keyword\nto the `User` struct declaration, then, I can successfully compile the `register.zig` module.\n\n```zig\n// user.zig\n// Added the `pub` keyword to `User`\npub const User = struct {\n// ...\n```\n\n```zig\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = undefined;\n _ = u;\n}\n```\n\n\nNow, what do you think it will happen if I try to actually call from `register.zig` any of the methods\nof the `User` struct? For example, if I try to call the `init()` method? The answer is: I get a similar error message,\nwarning me that the `init()` method is not marked as `pub`, as you can see below:\n\n```zig\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = user.User.init(\n 1, \"pedro\", \"email@gmail.com\"\n );\n _ = u;\n}\n```\n\n```\nregister.zig:3:35: error: 'init' is not marked 'pub'\n const u: user.User = user.User.init(\n ~~~~~~~~~^~~~~\nuser.zig:8:5: note: declared here\n fn init(id: u64,\n ^~~~~~~\n```\n\nThus, just because we have applied the `pub` keyword on the struct declaration,\nthis does not make the methods of that struct public as well. If we want to use\nany method from a struct (such as the `init()` method) outside of the module\nwhere this struct is declared, we have to mark this method with the `pub` keyword\nas well.\n\nGoing back to the `user.zig` module, and marking both the `init()` and `print_name()`\nmethods with the `pub` keyword, makes them both available to the outside world, and,\nas consequence, makes the previous code example work.\n\n\n```zig\n// user.zig\n// Added the `pub` keyword to `User.init`\n pub fn init(\n// ...\n// Added the `pub` keyword to `User.print_name`\n pub fn print_name(self: User) !void {\n// ...\n```\n\n```zig\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = user.User.init(\n 1, \"pedro\", \"email@gmail.com\"\n );\n _ = u;\n}\n```\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n```\n:::\n\n\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt's not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n```\n:::\n\n\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods are affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e., changes the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n```\n:::\n\n\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it's not about the input object, it's about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special part in this place. More specifically, it's\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and trying\nto infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n // many lines of code ...\n if (builtin.sanitize_thread) {\n const tsan = struct {\n extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n };\n\n const addr: *anyopaque = self;\n return switch (order) {\n .unordered, .monotonic => @compileError(\n @tagName(order)\n ++ \" only applies to atomic loads and stores\"\n ),\n .acquire => tsan.__tsan_acquire(addr),\n .release => tsan.__tsan_release(addr),\n .acq_rel, .seq_cst => {\n tsan.__tsan_acquire(addr);\n tsan.__tsan_release(addr);\n },\n };\n }\n\n return @fence(order);\n}\n```\n:::\n\n\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e., we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it's explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3fc93b4ea641.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe. There are many situations where these assumptions do not hold. For example,\n\nwhen casting an integer value into a float value, or vice-versa, it's not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3fc91795a712.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e., they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3fc945f8b4b0.test_0...OKAll 1 tests passed\n d.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e., a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" gets executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object gets saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n .{ .max_threads = num_threads }\n);\n```\n:::\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/docs/Chapters/03-structs.html b/docs/Chapters/03-structs.html index 5c0fd596..bc77ada2 100644 --- a/docs/Chapters/03-structs.html +++ b/docs/Chapters/03-structs.html @@ -704,8 +704,8 @@

    email: []const u8, fn init(id: u64, - name: []const u8, - email: []const u8) User { + name: []const u8, + email: []const u8) User { return User { .id = id, @@ -988,7 +988,8 @@

    try expect(@TypeOf(y) == u32); }

    -
    1/1 file3c448aa9d5f.test_0...OKAll 1 tests passed.
    +
    1/1 file3fc93b4ea641.test_0...OKAll 1 tests passed
    +  d.

    This is the general way to perform type casting in Zig. But remember, @as() works only when casting is unambiguous and safe. There are many situations where these assumptions do not hold. For example,

    @@ -1004,7 +1005,7 @@

    try expect(@TypeOf(y) == f32); }

    -
    1/1 file3c4427337b66.test_0...OKAll 1 tests passed
    +
    1/1 file3fc91795a712.test_0...OKAll 1 tests passed
       d.
    @@ -1021,7 +1022,7 @@

    try expect(@TypeOf(u32_ptr) == *const u32); }

    -
    1/1 file3c4479f1f6f8.test_0...OKAll 1 tests passed
    +
    1/1 file3fc945f8b4b0.test_0...OKAll 1 tests passed
       d.
    diff --git a/docs/search.json b/docs/search.json index 2c6e11fa..960167a2 100644 --- a/docs/search.json +++ b/docs/search.json @@ -254,7 +254,7 @@ "href": "Chapters/03-structs.html#sec-structs-and-oop", "title": "2  Control flow, structs, modules and types", "section": "2.3 Structs and OOP", - "text": "2.3 Structs and OOP\nZig is a language more closely related to C (which is a procedural language), than it is to C++ or Java (which are object-oriented languages). Because of that, you do not have advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or class inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C. You give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can also register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object that you create with this new type, will always have these methods available and associated with them.\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which is used to construct (or, to instantiate) every object of this particular class, and we also have a destructor method (or a destructor function), which is the function responsible for destroying every object of this class.\nIn Zig, we normally declare the constructor and the destructor methods of our structs, by declaring an init() and a deinit() methods inside the struct. This is just a naming convention that you will find across the entire Zig Standard Library. So, in Zig, the init() method of a struct is normally the constructor method of the class represented by this struct. While the deinit() method is the method used for destroying an existing instance of that struct.\nThe init() and deinit() methods are both used extensively in Zig code, and you will see both of them being used when we talk about allocators in Section 3.3. But, as another example, let’s build a simple User struct to represent a user of some sort of system.\nIf you look at the User struct below, you can see the struct keyword. Notice the data members of this struct: id, name and email. Every data member has its type explicitly annotated, with the colon character (:) syntax that we described earlier in Section 1.2.2. But also notice that every line in the struct body that describes a data member, ends with a comma character (,). So every time you declare a data member in your Zig code, always end the line with a comma character, instead of ending it with the traditional semicolon character (;).\nNext, we have registered an init() function as a method of this User struct. This init() method is the constructor method that we will use to instantiate every new User object. That is why this init() function returns a new User object as result.\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n\npedro\n\n\n\n2.3.1 The pub keyword\nThe pub keyword plays an important role in struct declarations, and OOP in Zig. In essence, this keyword is short for “public”, and it makes an item/component available outside of the module where this item/component is declared. In other words, if I don’t apply the pub keyword on something, it means that this “something” is available to be called/used only from within the module where this “something” is declared.\nTo demonstrate the effect of this keyword let’s focus again on the User struct that we have declared on the previous section. For our example here, let’s suppose that this User struct is declared inside a Zig module named user.zig. If I don’t use the pub keyword on the User struct, it means that I can create an User object, and call it’s methods (print_name() and init()) only from within the module where the User struct is declared, which in this case is the user.zig module.\nThis is why the previous code example works fine. Because we declare and also use the User struct inside the same module. But problems start to arise when we try to import and call/use this struct from another module. For example, if I create a new module called register.zig, and import the user.zig module into it, and try to annotate any variable with the User type, I get an error from the compiler.\n// register.zig\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = undefined;\n _ = u;\n}\nregister.zig:3:18: error: 'User' is not marked 'pub'\n const u: user.User = undefined;\n ~~~~^~~~~\nuser.zig:3:1: note: declared here\nconst User = struct {\n^~~~~\nTherefore, if you want to use something outside of the module where this “something” is declared, you have to mark it with the pub keyword. This “something” can be a module, a struct, a function, an object, etc.\nFor our example here, if we go back to the user.zig module, and add the pub keyword to the User struct declaration, then, I can successfully compile the register.zig module.\n// user.zig\n// Added the `pub` keyword to `User`\npub const User = struct {\n// ...\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = undefined;\n _ = u;\n}\nNow, what do you think it will happen if I try to actually call from register.zig any of the methods of the User struct? For example, if I try to call the init() method? The answer is: I get a similar error message, warning me that the init() method is not marked as pub, as you can see below:\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = user.User.init(\n 1, \"pedro\", \"email@gmail.com\"\n );\n _ = u;\n}\nregister.zig:3:35: error: 'init' is not marked 'pub'\n const u: user.User = user.User.init(\n ~~~~~~~~~^~~~~\nuser.zig:8:5: note: declared here\n fn init(id: u64,\n ^~~~~~~\nThus, just because we have applied the pub keyword on the struct declaration, this does not make the methods of that struct public as well. If we want to use any method from a struct (such as the init() method) outside of the module where this struct is declared, we have to mark this method with the pub keyword as well.\nGoing back to the user.zig module, and marking both the init() and print_name() methods with the pub keyword, makes them both available to the outside world, and, as consequence, makes the previous code example work.\n// user.zig\n// Added the `pub` keyword to `User.init`\n pub fn init(\n// ...\n// Added the `pub` keyword to `User.print_name`\n pub fn print_name(self: User) !void {\n// ...\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = user.User.init(\n 1, \"pedro\", \"email@gmail.com\"\n );\n _ = u;\n}\n\n\n2.3.2 Anonymous struct literals\nYou can declare a struct object as a literal value. When we do that, we normally specify the data type of this struct literal by writing its data type just before the opening curly brace. For example, I could write a struct literal value of the type User that we have defined in the previous section like this:\n\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a struct literal, but not specify explicitly the type of this particular struct. An anonymous struct is written by using the syntax .{}. So, we essentially replaced the explicit type of the struct literal with a dot character (.).\nAs we described in Section 2.4, when you put a dot before a struct literal, the type of this struct literal is automatically inferred by the zig compiler. In essence, the zig compiler will look for some hint of what is the type of that struct. This hint can be the type annotation of a function argument, or the return type annotation of the function that you are using, or the type annotation of an existing object. If the compiler does find such type annotation, it will use this type in your literal struct.\nAnonymous structs are very commonly used as inputs to function arguments in Zig. One example that you have seen already constantly, is the print() function from the stdout object. This function takes two arguments. The first argument, is a template string, which should contain string format specifiers in it, which tells how the values provided in the second argument should be printed into the message.\nWhile the second argument is a struct literal that lists the values to be printed into the template message specified in the first argument. You normally want to use an anonymous struct literal here, so that the zig compiler do the job of specifying the type of this particular anonymous struct for you.\n\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n\nHello, world!\n\n\n\n\n2.3.3 Struct declarations must be constant\nTypes in Zig must be const or comptime (we are going to talk more about comptime in Section 12.1). What this means is that you cannot create a new data type, and mark it as variable with the var keyword. So struct declarations are always constant. You cannot declare a new struct type using the var keyword. It must be const.\nIn the Vec3 example below, this declaration is allowed because I’m using the const keyword to declare this new data type.\n\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n\n\n\n2.3.4 The self method argument\nIn every language that have OOP, when we declare a method of some class or struct, we usually declare this method as a function that has a self argument. This self argument is the reference to the object itself from which the method is being called from.\nIt’s not mandatory to use this self argument. But why would you not use this self argument? There is no reason to not use it. Because the only way to get access to the data stored in the data members of your struct is to access them through this self argument. If you don’t need to use the data in the data members of your struct inside your method, you very likely don’t need a method. You can just declare this logic as a simple function, outside of your struct declaration.\nTake the Vec3 struct below. Inside this Vec3 struct we declared a method named distance(). This method calculates the distance between two Vec3 objects, by following the distance formula in euclidean space. Notice that this distance() method takes two Vec3 objects as input, self and other.\n\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n\nThe self argument corresponds to the Vec3 object from which this distance() method is being called from. While the other is a separate Vec3 object that is given as input to this method. In the example below, the self argument corresponds to the object v1, because the distance() method is being called from the v1 object, while the other argument corresponds to the object v2.\n\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n\nDistance: 3.3970575502926055\n\n\n2.3.5 About the struct state\nSometimes you don’t need to care about the state of your struct object. Sometimes, you just need to instantiate and use the objects, without altering their state. You can notice that when you have methods inside your struct declaration that might use the values that are present in the data members, but they do not alter the values in these data members of the struct in anyway.\nThe Vec3 struct that was presented in Section 2.3.4 is an example of that. This struct have a single method named distance(), and this method does use the values present in all three data members of the struct (x, y and z). But at the same time, this method does not change the values of these data members at any point.\nAs a result of that, when we create Vec3 objects we usually create them as constant objects, like the v1 and v2 objects presented in Section 2.3.4. We can create them as variable objects with the var keyword, if we want to. But because the methods of this Vec3 struct do not change the state of the objects in any point, it’s unnecessary to mark them as variable objects.\nBut why? Why am I talking about this here? It’s because the self argument in the methods are affected depending on whether the methods present in a struct change or don’t change the state of the object itself. More specifically, when you have a method in a struct that changes the state of the object (i.e., changes the value of a data member), the self argument in this method must be annotated in a different manner.\nAs I described in Section 2.3.4, the self argument in methods of a struct is the argument that receives as input the object from which the method was called from. We usually annotate this argument in the methods by writing self, followed by the colon character (:), and the data type of the struct to which the method belongs to (e.g. User, Vec3, etc.).\nIf we take the Vec3 struct that we defined in the previous section as an example, we can see in the distance() method that this self argument is annotated as self: Vec3. Because the state of the Vec3 object is never altered by this method.\nBut what if we do have a method that alters the state of the object, by altering the values of its data members, how should we annotate self in this instance? The answer is: “we should annotate self as a pointer of x, instead of just x”. In other words, you should annotate self as self: *x, instead of annotating it as self: x.\nIf we create a new method inside the Vec3 object that, for example, expands the vector by multiplying its coordinates by a factor of two, then, we need to follow this rule specified in the previous paragraph. The code example below demonstrates this idea:\n\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n\nNotice in the code example above that we have added a new method to our Vec3 struct named twice(). This method doubles the coordinate values of our vector object. In the case of the twice() method, we annotated the self argument as *Vec3, indicating that this argument receives a pointer (or a reference, if you prefer to call it this way) to a Vec3 object as input.\n\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n\nDoubled: 8.4\nNow, if you change the self argument in this twice() method to self: Vec3, like in the distance() method, you will get the compiler error exposed below as result. Notice that this error message is showing a line from the twice() method body, indicating that you cannot alter the value of the x data member.\n\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\nThis error message indicates that the x data member belongs to a constant object, and, because of that, it cannot be changed. Ultimately, this error message is telling us that the self argument is constant.\nIf you take some time, and think hard about this error message, you will understand it. You already have the tools to understand why we are getting this error message. We have talked about it already in Section 2.2. So remember, every function argument is immutable in Zig, and self is no exception to this rule.\nIn this example, we marked the v3 object as a variable object. But this does not matter. Because it’s not about the input object, it’s about the function argument.\nThe problem begins when we try to alter the value of self directly, which is a function argument, and, every function argument is immutable by default. You may ask yourself how can we overcome this barrier, and once again, the solution was also discussed in Section 2.2. We overcome this barrier, by explicitly marking the self argument as a pointer.\n\n\n\n\n\n\nNote\n\n\n\nIf a method of your x struct alters the state of the object, by changing the value of any data member, then, remember to use self: *x, instead of self: x in the function signature of this method.\n\n\nYou could also interpret the content discussed in this section as: “if you need to alter the state of your x struct object in one of its methods, you must explicitly pass the x struct object by reference to the self argument of this method”.", + "text": "2.3 Structs and OOP\nZig is a language more closely related to C (which is a procedural language), than it is to C++ or Java (which are object-oriented languages). Because of that, you do not have advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or class inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C. You give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can also register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object that you create with this new type, will always have these methods available and associated with them.\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which is used to construct (or, to instantiate) every object of this particular class, and we also have a destructor method (or a destructor function), which is the function responsible for destroying every object of this class.\nIn Zig, we normally declare the constructor and the destructor methods of our structs, by declaring an init() and a deinit() methods inside the struct. This is just a naming convention that you will find across the entire Zig Standard Library. So, in Zig, the init() method of a struct is normally the constructor method of the class represented by this struct. While the deinit() method is the method used for destroying an existing instance of that struct.\nThe init() and deinit() methods are both used extensively in Zig code, and you will see both of them being used when we talk about allocators in Section 3.3. But, as another example, let’s build a simple User struct to represent a user of some sort of system.\nIf you look at the User struct below, you can see the struct keyword. Notice the data members of this struct: id, name and email. Every data member has its type explicitly annotated, with the colon character (:) syntax that we described earlier in Section 1.2.2. But also notice that every line in the struct body that describes a data member, ends with a comma character (,). So every time you declare a data member in your Zig code, always end the line with a comma character, instead of ending it with the traditional semicolon character (;).\nNext, we have registered an init() function as a method of this User struct. This init() method is the constructor method that we will use to instantiate every new User object. That is why this init() function returns a new User object as result.\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n id: u64,\n name: []const u8,\n email: []const u8,\n\n fn init(id: u64,\n name: []const u8,\n email: []const u8) User {\n\n return User {\n .id = id,\n .name = name,\n .email = email\n };\n }\n\n fn print_name(self: User) !void {\n try stdout.print(\"{s}\\n\", .{self.name});\n }\n};\n\npub fn main() !void {\n const u = User.init(1, \"pedro\", \"email@gmail.com\");\n try u.print_name();\n}\n\npedro\n\n\n\n2.3.1 The pub keyword\nThe pub keyword plays an important role in struct declarations, and OOP in Zig. In essence, this keyword is short for “public”, and it makes an item/component available outside of the module where this item/component is declared. In other words, if I don’t apply the pub keyword on something, it means that this “something” is available to be called/used only from within the module where this “something” is declared.\nTo demonstrate the effect of this keyword let’s focus again on the User struct that we have declared on the previous section. For our example here, let’s suppose that this User struct is declared inside a Zig module named user.zig. If I don’t use the pub keyword on the User struct, it means that I can create an User object, and call it’s methods (print_name() and init()) only from within the module where the User struct is declared, which in this case is the user.zig module.\nThis is why the previous code example works fine. Because we declare and also use the User struct inside the same module. But problems start to arise when we try to import and call/use this struct from another module. For example, if I create a new module called register.zig, and import the user.zig module into it, and try to annotate any variable with the User type, I get an error from the compiler.\n// register.zig\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = undefined;\n _ = u;\n}\nregister.zig:3:18: error: 'User' is not marked 'pub'\n const u: user.User = undefined;\n ~~~~^~~~~\nuser.zig:3:1: note: declared here\nconst User = struct {\n^~~~~\nTherefore, if you want to use something outside of the module where this “something” is declared, you have to mark it with the pub keyword. This “something” can be a module, a struct, a function, an object, etc.\nFor our example here, if we go back to the user.zig module, and add the pub keyword to the User struct declaration, then, I can successfully compile the register.zig module.\n// user.zig\n// Added the `pub` keyword to `User`\npub const User = struct {\n// ...\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = undefined;\n _ = u;\n}\nNow, what do you think it will happen if I try to actually call from register.zig any of the methods of the User struct? For example, if I try to call the init() method? The answer is: I get a similar error message, warning me that the init() method is not marked as pub, as you can see below:\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = user.User.init(\n 1, \"pedro\", \"email@gmail.com\"\n );\n _ = u;\n}\nregister.zig:3:35: error: 'init' is not marked 'pub'\n const u: user.User = user.User.init(\n ~~~~~~~~~^~~~~\nuser.zig:8:5: note: declared here\n fn init(id: u64,\n ^~~~~~~\nThus, just because we have applied the pub keyword on the struct declaration, this does not make the methods of that struct public as well. If we want to use any method from a struct (such as the init() method) outside of the module where this struct is declared, we have to mark this method with the pub keyword as well.\nGoing back to the user.zig module, and marking both the init() and print_name() methods with the pub keyword, makes them both available to the outside world, and, as consequence, makes the previous code example work.\n// user.zig\n// Added the `pub` keyword to `User.init`\n pub fn init(\n// ...\n// Added the `pub` keyword to `User.print_name`\n pub fn print_name(self: User) !void {\n// ...\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n const u: user.User = user.User.init(\n 1, \"pedro\", \"email@gmail.com\"\n );\n _ = u;\n}\n\n\n2.3.2 Anonymous struct literals\nYou can declare a struct object as a literal value. When we do that, we normally specify the data type of this struct literal by writing its data type just before the opening curly brace. For example, I could write a struct literal value of the type User that we have defined in the previous section like this:\n\nconst eu = User {\n .id = 1,\n .name = \"Pedro\",\n .email = \"someemail@gmail.com\"\n};\n_ = eu;\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a struct literal, but not specify explicitly the type of this particular struct. An anonymous struct is written by using the syntax .{}. So, we essentially replaced the explicit type of the struct literal with a dot character (.).\nAs we described in Section 2.4, when you put a dot before a struct literal, the type of this struct literal is automatically inferred by the zig compiler. In essence, the zig compiler will look for some hint of what is the type of that struct. This hint can be the type annotation of a function argument, or the return type annotation of the function that you are using, or the type annotation of an existing object. If the compiler does find such type annotation, it will use this type in your literal struct.\nAnonymous structs are very commonly used as inputs to function arguments in Zig. One example that you have seen already constantly, is the print() function from the stdout object. This function takes two arguments. The first argument, is a template string, which should contain string format specifiers in it, which tells how the values provided in the second argument should be printed into the message.\nWhile the second argument is a struct literal that lists the values to be printed into the template message specified in the first argument. You normally want to use an anonymous struct literal here, so that the zig compiler do the job of specifying the type of this particular anonymous struct for you.\n\nconst std = @import(\"std\");\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n\nHello, world!\n\n\n\n\n2.3.3 Struct declarations must be constant\nTypes in Zig must be const or comptime (we are going to talk more about comptime in Section 12.1). What this means is that you cannot create a new data type, and mark it as variable with the var keyword. So struct declarations are always constant. You cannot declare a new struct type using the var keyword. It must be const.\nIn the Vec3 example below, this declaration is allowed because I’m using the const keyword to declare this new data type.\n\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n};\n\n\n\n2.3.4 The self method argument\nIn every language that have OOP, when we declare a method of some class or struct, we usually declare this method as a function that has a self argument. This self argument is the reference to the object itself from which the method is being called from.\nIt’s not mandatory to use this self argument. But why would you not use this self argument? There is no reason to not use it. Because the only way to get access to the data stored in the data members of your struct is to access them through this self argument. If you don’t need to use the data in the data members of your struct inside your method, you very likely don’t need a method. You can just declare this logic as a simple function, outside of your struct declaration.\nTake the Vec3 struct below. Inside this Vec3 struct we declared a method named distance(). This method calculates the distance between two Vec3 objects, by following the distance formula in euclidean space. Notice that this distance() method takes two Vec3 objects as input, self and other.\n\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n};\n\nThe self argument corresponds to the Vec3 object from which this distance() method is being called from. While the other is a separate Vec3 object that is given as input to this method. In the example below, the self argument corresponds to the object v1, because the distance() method is being called from the v1 object, while the other argument corresponds to the object v2.\n\nconst v1 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n \"Distance: {d}\\n\",\n .{v1.distance(v2)}\n);\n\nDistance: 3.3970575502926055\n\n\n2.3.5 About the struct state\nSometimes you don’t need to care about the state of your struct object. Sometimes, you just need to instantiate and use the objects, without altering their state. You can notice that when you have methods inside your struct declaration that might use the values that are present in the data members, but they do not alter the values in these data members of the struct in anyway.\nThe Vec3 struct that was presented in Section 2.3.4 is an example of that. This struct have a single method named distance(), and this method does use the values present in all three data members of the struct (x, y and z). But at the same time, this method does not change the values of these data members at any point.\nAs a result of that, when we create Vec3 objects we usually create them as constant objects, like the v1 and v2 objects presented in Section 2.3.4. We can create them as variable objects with the var keyword, if we want to. But because the methods of this Vec3 struct do not change the state of the objects in any point, it’s unnecessary to mark them as variable objects.\nBut why? Why am I talking about this here? It’s because the self argument in the methods are affected depending on whether the methods present in a struct change or don’t change the state of the object itself. More specifically, when you have a method in a struct that changes the state of the object (i.e., changes the value of a data member), the self argument in this method must be annotated in a different manner.\nAs I described in Section 2.3.4, the self argument in methods of a struct is the argument that receives as input the object from which the method was called from. We usually annotate this argument in the methods by writing self, followed by the colon character (:), and the data type of the struct to which the method belongs to (e.g. User, Vec3, etc.).\nIf we take the Vec3 struct that we defined in the previous section as an example, we can see in the distance() method that this self argument is annotated as self: Vec3. Because the state of the Vec3 object is never altered by this method.\nBut what if we do have a method that alters the state of the object, by altering the values of its data members, how should we annotate self in this instance? The answer is: “we should annotate self as a pointer of x, instead of just x”. In other words, you should annotate self as self: *x, instead of annotating it as self: x.\nIf we create a new method inside the Vec3 object that, for example, expands the vector by multiplying its coordinates by a factor of two, then, we need to follow this rule specified in the previous paragraph. The code example below demonstrates this idea:\n\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n x: f64,\n y: f64,\n z: f64,\n\n pub fn distance(self: Vec3, other: Vec3) f64 {\n const xd = m.pow(f64, self.x - other.x, 2.0);\n const yd = m.pow(f64, self.y - other.y, 2.0);\n const zd = m.pow(f64, self.z - other.z, 2.0);\n return m.sqrt(xd + yd + zd);\n }\n\n pub fn twice(self: *Vec3) void {\n self.x = self.x * 2.0;\n self.y = self.y * 2.0;\n self.z = self.z * 2.0;\n }\n};\n\nNotice in the code example above that we have added a new method to our Vec3 struct named twice(). This method doubles the coordinate values of our vector object. In the case of the twice() method, we annotated the self argument as *Vec3, indicating that this argument receives a pointer (or a reference, if you prefer to call it this way) to a Vec3 object as input.\n\nvar v3 = Vec3 {\n .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n\nDoubled: 8.4\nNow, if you change the self argument in this twice() method to self: Vec3, like in the distance() method, you will get the compiler error exposed below as result. Notice that this error message is showing a line from the twice() method body, indicating that you cannot alter the value of the x data member.\n\n// If we change the function signature of double to:\n pub fn twice(self: Vec3) void {\n\nt.zig:16:13: error: cannot assign to constant\n self.x = self.x * 2.0;\n ~~~~^~\nThis error message indicates that the x data member belongs to a constant object, and, because of that, it cannot be changed. Ultimately, this error message is telling us that the self argument is constant.\nIf you take some time, and think hard about this error message, you will understand it. You already have the tools to understand why we are getting this error message. We have talked about it already in Section 2.2. So remember, every function argument is immutable in Zig, and self is no exception to this rule.\nIn this example, we marked the v3 object as a variable object. But this does not matter. Because it’s not about the input object, it’s about the function argument.\nThe problem begins when we try to alter the value of self directly, which is a function argument, and, every function argument is immutable by default. You may ask yourself how can we overcome this barrier, and once again, the solution was also discussed in Section 2.2. We overcome this barrier, by explicitly marking the self argument as a pointer.\n\n\n\n\n\n\nNote\n\n\n\nIf a method of your x struct alters the state of the object, by changing the value of any data member, then, remember to use self: *x, instead of self: x in the function signature of this method.\n\n\nYou could also interpret the content discussed in this section as: “if you need to alter the state of your x struct object in one of its methods, you must explicitly pass the x struct object by reference to the self argument of this method”.", "crumbs": [ "2  Control flow, structs, modules and types" ] @@ -274,7 +274,7 @@ "href": "Chapters/03-structs.html#sec-type-cast", "title": "2  Control flow, structs, modules and types", "section": "2.5 Type casting", - "text": "2.5 Type casting\nIn this section, I want to discuss type casting (or, type conversion) with you. We use type casting when we have an object of type “x”, and we want to convert it into an object of type “y”, i.e., we want to change the data type of the object.\nMost languages have a formal way to perform type casting. In Rust for example, we normally use the keyword as, and in C, we normally use the type casting syntax, e.g. (int) x. In Zig, we use the @as() built-in function to cast an object of type “x”, into an object of type “y”.\nThis @as() function is the preferred way to perform type conversion (or type casting) in Zig. Because it’s explicit, and, it also performs the casting only if it is unambiguous and safe. To use this function, you just provide the target data type in the first argument, and, the object that you want cast as the second argument.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n\n1/1 file3c448aa9d5f.test_0...OKAll 1 tests passed.\n\n\nThis is the general way to perform type casting in Zig. But remember, @as() works only when casting is unambiguous and safe. There are many situations where these assumptions do not hold. For example,\nwhen casting an integer value into a float value, or vice-versa, it’s not clear to the compiler how to perform this conversion safely.\nTherefore, we need to use specialized “casting functions” in such situations. For example, if you want to cast an integer value into a float value, then, you should use the @floatFromInt() function. In the inverse scenario, you should use the @intFromFloat() function.\nIn these functions, you just provide the object that you want to cast as input. Then, the target data type of the “type casting operation” is determined by the type annotation of the object where you are saving the results. In the example below, we are casting the object x into a value of type f32, because the object y, which is where we are saving the results, is annotated as an object of type f32.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n\n1/1 file3c4427337b66.test_0...OKAll 1 tests passed\n d.\n\n\nAnother built-in function that is very useful when performing type casting operations is @ptrCast(). In essence, we use the @as() built-in function when we want to explicit convert (or cast) a Zig value/object from a type “x” to a type “y”, etc. However, pointers (we are going to discuss pointers in more depth in Chapter 6) are a special type of object in Zig, i.e., they are treated differently from “normal objects”.\nEverytime a pointer is involved in some “type casting operation” in Zig, the @ptrCast() function is used. This function works similarly to @floatFromInt(). You just provide the pointer object that you want to cast as input to this function, and the target data type is, once again, determined by the type annotation of the object where the results are being stored.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n\n1/1 file3c4479f1f6f8.test_0...OKAll 1 tests passed\n d.", + "text": "2.5 Type casting\nIn this section, I want to discuss type casting (or, type conversion) with you. We use type casting when we have an object of type “x”, and we want to convert it into an object of type “y”, i.e., we want to change the data type of the object.\nMost languages have a formal way to perform type casting. In Rust for example, we normally use the keyword as, and in C, we normally use the type casting syntax, e.g. (int) x. In Zig, we use the @as() built-in function to cast an object of type “x”, into an object of type “y”.\nThis @as() function is the preferred way to perform type conversion (or type casting) in Zig. Because it’s explicit, and, it also performs the casting only if it is unambiguous and safe. To use this function, you just provide the target data type in the first argument, and, the object that you want cast as the second argument.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 500;\n const y = @as(u32, x);\n try expect(@TypeOf(y) == u32);\n}\n\n1/1 file3fc93b4ea641.test_0...OKAll 1 tests passed\n d.\n\n\nThis is the general way to perform type casting in Zig. But remember, @as() works only when casting is unambiguous and safe. There are many situations where these assumptions do not hold. For example,\nwhen casting an integer value into a float value, or vice-versa, it’s not clear to the compiler how to perform this conversion safely.\nTherefore, we need to use specialized “casting functions” in such situations. For example, if you want to cast an integer value into a float value, then, you should use the @floatFromInt() function. In the inverse scenario, you should use the @intFromFloat() function.\nIn these functions, you just provide the object that you want to cast as input. Then, the target data type of the “type casting operation” is determined by the type annotation of the object where you are saving the results. In the example below, we are casting the object x into a value of type f32, because the object y, which is where we are saving the results, is annotated as an object of type f32.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const x: usize = 565;\n const y: f32 = @floatFromInt(x);\n try expect(@TypeOf(y) == f32);\n}\n\n1/1 file3fc91795a712.test_0...OKAll 1 tests passed\n d.\n\n\nAnother built-in function that is very useful when performing type casting operations is @ptrCast(). In essence, we use the @as() built-in function when we want to explicit convert (or cast) a Zig value/object from a type “x” to a type “y”, etc. However, pointers (we are going to discuss pointers in more depth in Chapter 6) are a special type of object in Zig, i.e., they are treated differently from “normal objects”.\nEverytime a pointer is involved in some “type casting operation” in Zig, the @ptrCast() function is used. This function works similarly to @floatFromInt(). You just provide the pointer object that you want to cast as input to this function, and the target data type is, once again, determined by the type annotation of the object where the results are being stored.\n\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n const bytes align(@alignOf(u32)) = [_]u8{\n 0x12, 0x12, 0x12, 0x12\n };\n const u32_ptr: *const u32 = @ptrCast(&bytes);\n try expect(@TypeOf(u32_ptr) == *const u32);\n}\n\n1/1 file3fc945f8b4b0.test_0...OKAll 1 tests passed\n d.", "crumbs": [ "2  Control flow, structs, modules and types" ] From 8f5a53feb455fa3b0ad50ab516b94897cb44cad9 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Thu, 20 Mar 2025 19:36:14 -0300 Subject: [PATCH 118/151] Update index --- _freeze/index/execute-results/html.json | 4 ++-- docs/index.html | 8 ++++---- docs/search.json | 4 ++-- index.qmd | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/_freeze/index/execute-results/html.json b/_freeze/index/execute-results/html.json index abf34f7d..16283e0b 100644 --- a/_freeze/index/execute-results/html.json +++ b/_freeze/index/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "335ac568e17c5057352e05da9521e5ae", + "hash": "0b80ffe49bae68e2641a31569b9e19df", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy\nof the book, either at Amazon, or at Leanpub:\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Data Platform Engineer at [Blip](https://www.blip.ai/en/)[^blip], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^blip]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.11.0-19-generic, 24.04.1-Ubuntu, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion), glystik (\\@glystik), Michael Lynch (\\@mtlynch)\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy\nof the book, either at Amazon, or at Leanpub:\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Senior Data Engineer at [DSM-Firmenich](https://www.dsm-firmenich.com)[^dsm], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^dsm]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n\n- System version: Linux, 6.11.0-19-generic, 24.04.1-Ubuntu, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion), glystik (\\@glystik), Michael Lynch (\\@mtlynch)\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/docs/index.html b/docs/index.html index 34e98809..846deca6 100644 --- a/docs/index.html +++ b/docs/index.html @@ -7,7 +7,7 @@ - + Introduction to Zig \n\n\n\n \n\n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Senior Data Engineer at [DSM-Firmenich](https://www.dsm-firmenich.com)[^dsm], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^dsm]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n\n- System version: Linux, 6.11.0-19-generic, 24.04.1-Ubuntu, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion), glystik (\\@glystik), Michael Lynch (\\@mtlynch)\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy\nof the book, either at Amazon, or at Leanpub:\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Senior Data Engineer at [DSM-Firmenich](https://www.dsm-firmenich.com)[^dsm], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^dsm]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.11.0-21-generic, 24.04.1-Ubuntu, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion), glystik (\\@glystik), Michael Lynch (\\@mtlynch), Yashank (\\@stickyburn)\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/contributors.txt b/contributors.txt index 8a789f25..73ae3ac2 100644 --- a/contributors.txt +++ b/contributors.txt @@ -24,3 +24,4 @@ Maarten Coopens,@maarteNNNN Niklas Johansson,@Raphexion glystik,@glystik Michael Lynch,@mtlynch +Yashank,@stickyburn diff --git a/docs/index.html b/docs/index.html index 63c5d147..ddb5b3ed 100644 --- a/docs/index.html +++ b/docs/index.html @@ -426,7 +426,7 @@

    License

    Book compilation metadata

    This book was compiled using the following versions of Zig and Quarto:

      -
    • System version: Linux, 6.11.0-19-generic, 24.04.1-Ubuntu, x86_64.
    • +
    • System version: Linux, 6.11.0-21-generic, 24.04.1-Ubuntu, x86_64.
    • Zig version: 0.14.0-dev.3046+08d661fcf.
    • Quarto version: 1.5.57.
    @@ -454,7 +454,7 @@

    Acknowledgments

    This book is also a product of many conversations and exchanges that we had with different people from the Zig community. I (Pedro Duarte Faria) am incredibly grateful for these conversations, and also, for some direct contributions that we had. Below we have a list of the people involved (name of the person with their usename in GitHub):

    -

    Calin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m), Alexander (@alexwheezy), Maarten Coopens (@maarteNNNN), Niklas Johansson (@Raphexion), glystik (@glystik), Michael Lynch (@mtlynch)

    +

    Calin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m), Alexander (@alexwheezy), Maarten Coopens (@maarteNNNN), Niklas Johansson (@Raphexion), glystik (@glystik), Michael Lynch (@mtlynch), Yashank (@stickyburn)

    diff --git a/docs/search.json b/docs/search.json index 29d18ab1..07f2b577 100644 --- a/docs/search.json +++ b/docs/search.json @@ -54,7 +54,7 @@ "href": "index.html#book-compilation-metadata", "title": "Introduction to Zig", "section": "Book compilation metadata", - "text": "Book compilation metadata\nThis book was compiled using the following versions of Zig and Quarto:\n\nSystem version: Linux, 6.11.0-19-generic, 24.04.1-Ubuntu, x86_64.\nZig version: 0.14.0-dev.3046+08d661fcf.\nQuarto version: 1.5.57.", + "text": "Book compilation metadata\nThis book was compiled using the following versions of Zig and Quarto:\n\nSystem version: Linux, 6.11.0-21-generic, 24.04.1-Ubuntu, x86_64.\nZig version: 0.14.0-dev.3046+08d661fcf.\nQuarto version: 1.5.57.", "crumbs": [ "Welcome" ] @@ -84,7 +84,7 @@ "href": "index.html#acknowledgments", "title": "Introduction to Zig", "section": "Acknowledgments", - "text": "Acknowledgments\nThis book is also a product of many conversations and exchanges that we had with different people from the Zig community. I (Pedro Duarte Faria) am incredibly grateful for these conversations, and also, for some direct contributions that we had. Below we have a list of the people involved (name of the person with their usename in GitHub):\nCalin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m), Alexander (@alexwheezy), Maarten Coopens (@maarteNNNN), Niklas Johansson (@Raphexion), glystik (@glystik), Michael Lynch (@mtlynch)", + "text": "Acknowledgments\nThis book is also a product of many conversations and exchanges that we had with different people from the Zig community. I (Pedro Duarte Faria) am incredibly grateful for these conversations, and also, for some direct contributions that we had. Below we have a list of the people involved (name of the person with their usename in GitHub):\nCalin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m), Alexander (@alexwheezy), Maarten Coopens (@maarteNNNN), Niklas Johansson (@Raphexion), glystik (@glystik), Michael Lynch (@mtlynch), Yashank (@stickyburn)", "crumbs": [ "Welcome" ] From a007fc342a16645dd981d6c50e970caac4d44ce0 Mon Sep 17 00:00:00 2001 From: Pedro Faria <69123925+pedropark99@users.noreply.github.com> Date: Sun, 13 Apr 2025 12:41:08 -0300 Subject: [PATCH 128/151] Update 01-zig-weird.qmd --- Chapters/01-zig-weird.qmd | 2 -- 1 file changed, 2 deletions(-) diff --git a/Chapters/01-zig-weird.qmd b/Chapters/01-zig-weird.qmd index b37dcfe3..1f6a2c74 100644 --- a/Chapters/01-zig-weird.qmd +++ b/Chapters/01-zig-weird.qmd @@ -53,10 +53,8 @@ are what makes C++ so complex and hard to learn. Zig tries to go in the opposite Zig is a very simple language, more closely related to other simple languages such as C and Go. The phrase above is still important for C programmers too. Because, even C being a simple - language, it's still hard sometimes to read and understand C code. For example, pre-processor macros in C are a frequent source of confusion. Sometimes, they really make it hard to debug - C programs. Because macros are essentially a second language embedded in C that obscures your C code. With macros, you are no longer 100% sure about which pieces of the code are being sent to the compiler, i.e. From 1563c613605e161b7ac1e6ea3de2885f9d3dd862 Mon Sep 17 00:00:00 2001 From: Pedro Faria <69123925+pedropark99@users.noreply.github.com> Date: Sun, 13 Apr 2025 12:47:28 -0300 Subject: [PATCH 129/151] Update 01-zig-weird.qmd --- Chapters/01-zig-weird.qmd | 1 - 1 file changed, 1 deletion(-) diff --git a/Chapters/01-zig-weird.qmd b/Chapters/01-zig-weird.qmd index 1f6a2c74..99c710af 100644 --- a/Chapters/01-zig-weird.qmd +++ b/Chapters/01-zig-weird.qmd @@ -449,7 +449,6 @@ Hello You can read more details about this Windows-specific limitation in a couple of GitHub issues opened at the official Zig repository. More specifically, the issues - 17186 [^cissue1] and 19864 [^cissue2]. [^cissue1]: From 00cd2f39ffe0aae9c0ba2476c5e179761abb1cf3 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 13 Apr 2025 14:38:29 -0300 Subject: [PATCH 130/151] Recompile book with fixes --- .../01-zig-weird/execute-results/html.json | 8 +++----- docs/Chapters/01-zig-weird.html | 19 ++++++++----------- docs/search.json | 12 ++++++------ 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/_freeze/Chapters/01-zig-weird/execute-results/html.json b/_freeze/Chapters/01-zig-weird/execute-results/html.json index 4f120244..4920b2b5 100644 --- a/_freeze/Chapters/01-zig-weird/execute-results/html.json +++ b/_freeze/Chapters/01-zig-weird/execute-results/html.json @@ -1,11 +1,9 @@ { - "hash": "569cc4cd11b03e6a2e83a391821389ed", + "hash": "4d435d48922c81726d4668b9e1fc1e4f", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\n\nlanguage, it's still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. Sometimes, they really make it hard to debug\n\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscure the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that gets compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e., where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contains Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nWe can use this build system to write small scripts in Zig,\nwhich describe the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e., creating new objects)\nare made in Zig. You can create a new object in Zig by using the syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). In @sec-assignments we talk more about objects in general.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n```\n:::\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that in @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIt's worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt's like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portable C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig build.zig.zon main src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nIn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e., the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. If you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith an \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, on Windows, operations like accessing the `stdout` (or opening a file) depend on\nresources that are available only at *runtime* (you will learn more about compile-time versus runtime\nin @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerges from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword in @sec-comptime.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation in a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues\n\n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described in @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig later in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig?\nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar to our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentation.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It's a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (on YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e., identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n age = 25;\n ~~^~~\n```\n\nSo, if you want to change the value of your object, you need to transform your immutable (or \"constant\")\nobject into a mutable (or \"variable\") object. You can do that by using the `var` keyword.\nThis keyword stands for \"variable\", and when you apply this keyword to some object, you are\ntelling the Zig compiler that the value associated with this object might change at some point.\n\nThus, if we come back to the previous example, and change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it's a \"variable object\".\n\nHowever, if you take a look at the example below, you will notice that we have not only declared the\n`age` object with the `var` keyword, but we also have explicitly annotated the data type\nof the `age` object with the `u8` type this time. The basic idea is, when we use a variable/mutable object,\nthe Zig compiler ask for us to be more explicit with what we want, to be more clear\nabout what our code does. This translates into being more explicit about the data types that we want\nto use in our objects.\n\nTherefore, if you transform your object into a variable/mutable object, just remember to always\nannotate the type of the object explicitly in your code. Otherwise, the Zig compiler might raise\na compilation error, asking you to transform your object back into a `const` object, or,\nto give your object an \"explicit type\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIt's important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code uses this object while it's uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object.\n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e., if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n const age = 15;\n ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to a special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It's discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also gets discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig have many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e., the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\nIt's worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it have the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it's a slice that\naccesses all elements in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhave 2 elements in it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" in @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth in @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially in @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned in @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e., both the start and the end of this range)\nis known at compile-time, the slice object that gets created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nin @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that gets created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e., a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can\ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n 1, 2, 3, 4, 5,\n 6, 7, 8, 9, 10\n};\n// This slice have a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n_ = slice;\n```\n:::\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat gets created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, we are reading a file, and then, we try to create a slice object\nthat covers the entire buffer that contains the contents of this file. This is obviously\nan example of a runtime known range, because the end index of the range\nis not known at compile time.\n\nIn other words, the end index of the range is the size of\nthe array `file_contents`. However, the size of `file_contents` is not known at compile time.\nBecause we don't know how many bytes are stored inside this `shop-list.txt` file.\nAnd because this is a file, someone might edit this file tomorrow and add more lines\nor remove lines from it. Therefore, the size of this file might vary drastically from one execution to another.\n\nNow, if the file size can vary from one run to another, then, we can conclude that the value of the expression\n`file_contents.len` exposed in the example below can also vary from one run to another. As consequence,\nthe value of the expression `file_contents.len` is runtime-known only, and, as a consequence of that,\nthe range `0..file_contents.len` is also runtime-known only.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\nfn read_file(allocator: std.mem.Allocator, path: []const u8) ![]u8 {\n const file = try std.fs.cwd().openFile(path, .{});\n defer file.close();\n return try file.reader().readAllAlloc(\n allocator, std.math.maxInt(usize)\n );\n}\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const path = \"../ZigExamples/file-io/shop-list.txt\";\n const file_contents = try read_file(allocator, path);\n const slice = file_contents[0..file_contents.len];\n _ = slice;\n}\n```\n:::\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code have its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e., a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n y += 1;\n break :add_one y;\n};\nif (x == 124 and y == 124) {\n try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nStrings in Zig work very similarly to strings in C, but they come with some extra caveats which adds more safety\nand efficiency to them. You could also say that Zig simply uses a more modern and safe approach to manage\nand use strings.\n\nA string in Zig is essentially an array of arbitrary bytes, or, more specifically, an array of `u8` values.\nThis very similar to a string in C, which is also interpreted as an array of arbitrary bytes, or, in the case\nof C, an array of `char` (which usually represents an unsigned 8-bit integer value in most systems) values.\n\nNow, because a string in Zig is an array, you automatically\nget the length of the string (i.e. the length of the array) embedded in the value itself. This makes\nall the difference! Because now, the Zig compiler can use the length value that is embedded in the string to\ncheck for \"buffer overflow\" or \"wrong memory access\" problems in your code.\n\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need to do something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n char* array = \"An example of string in C\";\n int index = 0;\n while (1) {\n if (array[index] == '\\0') {\n break;\n }\n index++;\n }\n printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible in the string value itself. You can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example of string literal in Zig\";\n try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\nAnother point is that Zig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e., a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Using a slice versus a sentinel-terminated array\n\nIn memory, all string values in Zig are always stored in the same way.\nThey are simply stored as sequences/arrays of arbitrary bytes. But you can use and access\nthis sequence of bytes in two different ways. You can access this sequence of bytes as:\n\n- a sentinel-terminated array of `u8` values.\n- or as a slice of `u8` values.\n\n\n#### Sentinel-terminated arrays\n\nSentinel-terminated arrays in Zig are described in the Language Reference of Zig[^sentinel].\nIn summary a sentinel-terminated array is just a normal array, but, the difference is that they\ncontain a \"sentinel value\" at the last index/element of the array. With a sentinel-terminated array\nyou embed both the length of the array, and also, the sentinel value in the type itself of your object.\n\n[^sentinel]: .\n\nFor example, if you write a string literal value in your code, and ask Zig to print the data type of this value,\nyou usually get a data type in the format `*const [n:0]u8`. The `n` in the data type indicates the size of\nthe string (that is the length of the array). The zero after the `n:` part of the data type is the sentinel\nvalue itself.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n_ = \"A literal value\";\ntry stdout.print(\"{any}\\n\", .{@TypeOf(\"A literal value\")});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n*const [15:0]u8\n```\n\n\n:::\n:::\n\n\n\n\n\nSo, with this data type `*const [n:0]u8` you are essentially saying that you have an array of `u8` values\nof length `n`, where, the element at the index corresponding to the length `n` in the array is the\nnumber zero. If you really think about this description, you will notice that this is just a fancy way to\ndescribe a string in C, which is a null-terminated array of bytes. The `NULL` value in C is the number\nzero. So, an array that ends in a null/zero value in C is essentially a sentinel-terminated array in Zig,\nwhere the sentinel value of the array is the number zero.\n\nTherefore, a string literal value in Zig is just a pointer to a null-terminated array of bytes (i.e., similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string, and also, the fact that they are \"NULL terminated\",\ninto the data type of the value itself.\n\n\n\n#### Slice\n\nYou can also access and use the arbitrary sequence of bytes that represent your string as a slice of `u8` values.\nThe majority of functions from the Zig standard library usually receive strings as inputs as slices of\n`u8` values (slices were presented in @sec-arrays).\n\nThus, you will see a lot of string values with a data type of `[]u8` or `[]const u8`, depending if the object\nwhere this string is stored is marked as constant with `const`, or as variable with `var`. Now, because\nthe string in this case is being interpreted as a slice, this slice is not necessarilly null-terminated,\nbecause now, the sentinel value is not mandatory. You can include the null/zero value in the slice if you\nwant to, but there is no need to do it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string value being\n// interpreted as a slice.\nconst str: []const u8 = \"A string value\";\ntry stdout.print(\"{any}\\n\", .{@TypeOf(str)});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n[]const u8\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Iterating through the string\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example\";\n try stdout.print(\"Bytes that represents the string object: \", .{});\n for (string_object) |byte| {\n try stdout.print(\"{X} \", .{byte});\n }\n try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n 73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below,\nand also, you can see that this is a null-terminated array, because of the zero value after the `:` character in the data type.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it's a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const simple_array = [_]i32{1, 2, 3, 4};\n const string_obj: []const u8 = \"A string object\";\n std.debug.print(\n \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n );\n std.debug.print(\n \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n );\n std.debug.print(\n \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n );\n std.debug.print(\n \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n );\n}\n```\n:::\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIt's important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"Ⱥ\";\n _ = try stdout.write(\n \"Bytes that represents the string object: \"\n );\n for (string_object) |char| {\n try stdout.print(\"{X} \", .{char});\n }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n var iterator = utf8.iterator();\n while (iterator.nextCodepointSlice()) |codepoint| {\n try stdout.print(\n \"got codepoint {}\\n\",\n .{std.fmt.fmtSliceHexUpper(codepoint)},\n );\n }\n}\n\n```\n:::\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig in @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers in @sec-root-file and especially in @sec-assignments.\n- How strings work in Zig in @sec-zig-strings.\n- How to use arrays and slices in @sec-arrays.\n- How to import functionality from other Zig modules in @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* in @sec-structs-and-oop.\n- Basic control flow syntax in @sec-zig-control-flow.\n- Enums in @sec-enum;\n- Pointers and Optionals in @sec-pointer;\n- Error handling with `try` and `catch` in @sec-error-handling;\n- Unit tests in @sec-unittests;\n- Vectors in @sec-vectors-simd;\n- Build System in @sec-build-system;\n", - "supporting": [ - "01-zig-weird_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it's still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. Sometimes, they really make it hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscure the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that gets compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e., where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contains Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nWe can use this build system to write small scripts in Zig,\nwhich describe the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e., creating new objects)\nare made in Zig. You can create a new object in Zig by using the syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). In @sec-assignments we talk more about objects in general.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n```\n:::\n\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that in @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIt's worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt's like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portable C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig build.zig.zon main src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nIn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e., the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. If you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith an \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, on Windows, operations like accessing the `stdout` (or opening a file) depend on\nresources that are available only at *runtime* (you will learn more about compile-time versus runtime\nin @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerges from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword in @sec-comptime.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation in a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues\n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described in @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig later in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig?\nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar to our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentation.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It's a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (on YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e., identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n age = 25;\n ~~^~~\n```\n\nSo, if you want to change the value of your object, you need to transform your immutable (or \"constant\")\nobject into a mutable (or \"variable\") object. You can do that by using the `var` keyword.\nThis keyword stands for \"variable\", and when you apply this keyword to some object, you are\ntelling the Zig compiler that the value associated with this object might change at some point.\n\nThus, if we come back to the previous example, and change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it's a \"variable object\".\n\nHowever, if you take a look at the example below, you will notice that we have not only declared the\n`age` object with the `var` keyword, but we also have explicitly annotated the data type\nof the `age` object with the `u8` type this time. The basic idea is, when we use a variable/mutable object,\nthe Zig compiler ask for us to be more explicit with what we want, to be more clear\nabout what our code does. This translates into being more explicit about the data types that we want\nto use in our objects.\n\nTherefore, if you transform your object into a variable/mutable object, just remember to always\nannotate the type of the object explicitly in your code. Otherwise, the Zig compiler might raise\na compilation error, asking you to transform your object back into a `const` object, or,\nto give your object an \"explicit type\".\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIt's important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code uses this object while it's uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object.\n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e., if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n const age = 15;\n ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to a special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It's discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also gets discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig has many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e., the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\n\nIt's worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it has the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it's a slice that\naccesses all elements in the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhas 2 elements in it.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" in @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth in @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially in @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned in @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e., both the start and the end of this range)\nis known at compile-time, the slice object that gets created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nin @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that gets created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e., a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can\ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n 1, 2, 3, 4, 5,\n 6, 7, 8, 9, 10\n};\n// This slice has a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n_ = slice;\n```\n:::\n\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat gets created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, we are reading a file, and then, we try to create a slice object\nthat covers the entire buffer that contains the contents of this file. This is obviously\nan example of a runtime known range, because the end index of the range\nis not known at compile time.\n\nIn other words, the end index of the range is the size of\nthe array `file_contents`. However, the size of `file_contents` is not known at compile time.\nBecause we don't know how many bytes are stored inside this `shop-list.txt` file.\nAnd because this is a file, someone might edit this file tomorrow and add more lines\nor remove lines from it. Therefore, the size of this file might vary drastically from one execution to another.\n\nNow, if the file size can vary from one run to another, then, we can conclude that the value of the expression\n`file_contents.len` exposed in the example below can also vary from one run to another. As consequence,\nthe value of the expression `file_contents.len` is runtime-known only, and, as a consequence of that,\nthe range `0..file_contents.len` is also runtime-known only.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\nfn read_file(allocator: std.mem.Allocator, path: []const u8) ![]u8 {\n const file = try std.fs.cwd().openFile(path, .{});\n defer file.close();\n return try file.reader().readAllAlloc(\n allocator, std.math.maxInt(usize)\n );\n}\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const path = \"../ZigExamples/file-io/shop-list.txt\";\n const file_contents = try read_file(allocator, path);\n const slice = file_contents[0..file_contents.len];\n _ = slice;\n}\n```\n:::\n\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code has its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e., a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n y += 1;\n break :add_one y;\n};\nif (x == 124 and y == 124) {\n try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nStrings in Zig work very similarly to strings in C, but they come with some extra caveats which adds more safety\nand efficiency to them. You could also say that Zig simply uses a more modern and safe approach to manage\nand use strings.\n\nA string in Zig is essentially an array of arbitrary bytes, or, more specifically, an array of `u8` values.\nThis very similar to a string in C, which is also interpreted as an array of arbitrary bytes, or, in the case\nof C, an array of `char` (which usually represents an unsigned 8-bit integer value in most systems) values.\n\nNow, because a string in Zig is an array, you automatically\nget the length of the string (i.e. the length of the array) embedded in the value itself. This makes\nall the difference! Because now, the Zig compiler can use the length value that is embedded in the string to\ncheck for \"buffer overflow\" or \"wrong memory access\" problems in your code.\n\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need to do something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n char* array = \"An example of string in C\";\n int index = 0;\n while (1) {\n if (array[index] == '\\0') {\n break;\n }\n index++;\n }\n printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible in the string value itself. You can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example of string literal in Zig\";\n try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\n\nAnother point is that Zig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e., a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### Using a slice versus a sentinel-terminated array\n\nIn memory, all string values in Zig are always stored in the same way.\nThey are simply stored as sequences/arrays of arbitrary bytes. But you can use and access\nthis sequence of bytes in two different ways. You can access this sequence of bytes as:\n\n- a sentinel-terminated array of `u8` values.\n- or as a slice of `u8` values.\n\n\n#### Sentinel-terminated arrays\n\nSentinel-terminated arrays in Zig are described in the Language Reference of Zig[^sentinel].\nIn summary a sentinel-terminated array is just a normal array, but, the difference is that they\ncontain a \"sentinel value\" at the last index/element of the array. With a sentinel-terminated array\nyou embed both the length of the array, and also, the sentinel value in the type itself of your object.\n\n[^sentinel]: .\n\nFor example, if you write a string literal value in your code, and ask Zig to print the data type of this value,\nyou usually get a data type in the format `*const [n:0]u8`. The `n` in the data type indicates the size of\nthe string (that is the length of the array). The zero after the `n:` part of the data type is the sentinel\nvalue itself.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n_ = \"A literal value\";\ntry stdout.print(\"{any}\\n\", .{@TypeOf(\"A literal value\")});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n*const [15:0]u8\n```\n\n\n:::\n:::\n\n\n\n\n\n\nSo, with this data type `*const [n:0]u8` you are essentially saying that you have an array of `u8` values\nof length `n`, where, the element at the index corresponding to the length `n` in the array is the\nnumber zero. If you really think about this description, you will notice that this is just a fancy way to\ndescribe a string in C, which is a null-terminated array of bytes. The `NULL` value in C is the number\nzero. So, an array that ends in a null/zero value in C is essentially a sentinel-terminated array in Zig,\nwhere the sentinel value of the array is the number zero.\n\nTherefore, a string literal value in Zig is just a pointer to a null-terminated array of bytes (i.e., similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string, and also, the fact that they are \"NULL terminated\",\ninto the data type of the value itself.\n\n\n\n#### Slice\n\nYou can also access and use the arbitrary sequence of bytes that represent your string as a slice of `u8` values.\nThe majority of functions from the Zig standard library usually receive strings as inputs as slices of\n`u8` values (slices were presented in @sec-arrays).\n\nThus, you will see a lot of string values with a data type of `[]u8` or `[]const u8`, depending if the object\nwhere this string is stored is marked as constant with `const`, or as variable with `var`. Now, because\nthe string in this case is being interpreted as a slice, this slice is not necessarilly null-terminated,\nbecause now, the sentinel value is not mandatory. You can include the null/zero value in the slice if you\nwant to, but there is no need to do it.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string value being\n// interpreted as a slice.\nconst str: []const u8 = \"A string value\";\ntry stdout.print(\"{any}\\n\", .{@TypeOf(str)});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n[]const u8\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### Iterating through the string\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example\";\n try stdout.print(\"Bytes that represents the string object: \", .{});\n for (string_object) |byte| {\n try stdout.print(\"{X} \", .{byte});\n }\n try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n 73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below,\nand also, you can see that this is a null-terminated array, because of the zero value after the `:` character in the data type.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it's a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n const simple_array = [_]i32{1, 2, 3, 4};\n const string_obj: []const u8 = \"A string object\";\n std.debug.print(\n \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n );\n std.debug.print(\n \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n );\n std.debug.print(\n \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n );\n std.debug.print(\n \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n );\n}\n```\n:::\n\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIt's important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"Ⱥ\";\n _ = try stdout.write(\n \"Bytes that represents the string object: \"\n );\n for (string_object) |char| {\n try stdout.print(\"{X} \", .{char});\n }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop through the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n var iterator = utf8.iterator();\n while (iterator.nextCodepointSlice()) |codepoint| {\n try stdout.print(\n \"got codepoint {}\\n\",\n .{std.fmt.fmtSliceHexUpper(codepoint)},\n );\n }\n}\n\n```\n:::\n\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig in @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers in @sec-root-file and especially in @sec-assignments.\n- How strings work in Zig in @sec-zig-strings.\n- How to use arrays and slices in @sec-arrays.\n- How to import functionality from other Zig modules in @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* in @sec-structs-and-oop.\n- Basic control flow syntax in @sec-zig-control-flow.\n- Enums in @sec-enum;\n- Pointers and Optionals in @sec-pointer;\n- Error handling with `try` and `catch` in @sec-error-handling;\n- Unit tests in @sec-unittests;\n- Vectors in @sec-vectors-simd;\n- Build System in @sec-build-system;\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/docs/Chapters/01-zig-weird.html b/docs/Chapters/01-zig-weird.html index 4c437852..50076fd1 100644 --- a/docs/Chapters/01-zig-weird.html +++ b/docs/Chapters/01-zig-weird.html @@ -372,9 +372,7 @@

    “Focus on debugging your application rather than debugging your programming language knowledge”.

    This phrase is specially true for C++ programmers. Because C++ is a gigantic language, with tons of features, and also, there are lots of different “flavors of C++”. These elements are what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction. Zig is a very simple language, more closely related to other simple languages such as C and Go.

    -

    The phrase above is still important for C programmers too. Because, even C being a simple

    -

    language, it’s still hard sometimes to read and understand C code. For example, pre-processor macros in C are a frequent source of confusion. Sometimes, they really make it hard to debug

    -

    C programs. Because macros are essentially a second language embedded in C that obscures your C code. With macros, you are no longer 100% sure about which pieces of the code are being sent to the compiler, i.e. they obscure the actual source code that you wrote.

    +

    The phrase above is still important for C programmers too. Because, even C being a simple language, it’s still hard sometimes to read and understand C code. For example, pre-processor macros in C are a frequent source of confusion. Sometimes, they really make it hard to debug C programs. Because macros are essentially a second language embedded in C that obscures your C code. With macros, you are no longer 100% sure about which pieces of the code are being sent to the compiler, i.e. they obscure the actual source code that you wrote.

    You don’t have macros in Zig. In Zig, the code you write, is the actual code that gets compiled by the compiler. You also don’t have a hidden control flow happening behind the scenes. And, you also don’t have functions or operators from the standard library that make hidden memory allocations behind your back.

    By being a simpler language, Zig becomes much more clear and easier to read/write, but at the same time, it also achieves a much more robust state, with more consistent behaviour in edge situations. Once again, less is more.

    @@ -507,8 +505,7 @@

    }
    Hello
    -

    You can read more details about this Windows-specific limitation in a couple of GitHub issues opened at the official Zig repository. More specifically, the issues

    -

    17186 7 and 19864 8.

    +

    You can read more details about this Windows-specific limitation in a couple of GitHub issues opened at the official Zig repository. More specifically, the issues 17186 7 and 19864 8.

    1.2.7 Compiling the entire project

    @@ -653,7 +650,7 @@

    1.5 Primitive Data Types

    -

    Zig have many different primitive data types available for you to use. You can see the full list of available data types at the official Language Reference page21.

    +

    Zig has many different primitive data types available for you to use. You can see the full list of available data types at the official Language Reference page21.

    But here is a quick list:

    • Unsigned integers: u8, 8-bit integer; u16, 16-bit integer; u32, 32-bit integer; u64, 64-bit integer; u128, 128-bit integer.
    • @@ -686,7 +683,7 @@

      12
      -

      In contrast, you can also select specific slices (or sections) of your array, by using a range selector. Some programmers also call these selectors of “slice selectors”, and they also exist in Rust, and have the exact same syntax as in Zig. Anyway, a range selector is a special expression in Zig that defines a range of indexes, and it have the syntax start..end.

      +

      In contrast, you can also select specific slices (or sections) of your array, by using a range selector. Some programmers also call these selectors of “slice selectors”, and they also exist in Rust, and have the exact same syntax as in Zig. Anyway, a range selector is a special expression in Zig that defines a range of indexes, and it has the syntax start..end.

      In the example below, at the second line of code, the sl object stores a slice (or a portion) of the ns array. More precisely, the elements at index 1 and 2 in the ns array.

      const ns = [4]u8{48, 24, 12, 6};
      @@ -715,7 +712,7 @@ 

      Slices can be thought of as a pair of [*]T (the pointer to the data) and a usize (the element count) (Sobeston 2024).

      Through the pointer contained inside the slice you can access the elements (or values) that are inside this range (or portion) that you selected from the original array. But the length number (which you can access through the len property of your slice object) is the really big improvement (over C arrays for example) that Zig brings to the table here.

      -

      Because with this length number the zig compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice, or, if you are causing any buffer overflow problems. In the example below, we access the len property of the slice sl, which tells us that this slice have 2 elements in it.

      +

      Because with this length number the zig compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice, or, if you are causing any buffer overflow problems. In the example below, we access the len property of the slice sl, which tells us that this slice has 2 elements in it.

      const ns = [4]u8{48, 24, 12, 6};
       const sl = ns[1..3];
      @@ -761,7 +758,7 @@ 

      1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; -// This slice have a compile-time known range. +// This slice has a compile-time known range. // Because we know both the start and end of the range. const slice = arr1[1..4]; _ = slice;

      @@ -798,7 +795,7 @@

      This means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together to represent the number 570. That is why the relationship between bytes and unicode points is not always 1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds to a single unicode point.

      -

      All of this means that if you loop trough the elements of a string in Zig, you will be looping through the bytes that represents that string, and not through the characters of that string. In the Ⱥ example above, the for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.

      +

      All of this means that if you loop through the elements of a string in Zig, you will be looping through the bytes that represents that string, and not through the characters of that string. In the Ⱥ example above, the for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.

      Now, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a consequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because the number of bytes will be equal to the number of characters in that string. In other words, in this specific situation, the relationship between bytes and unicode points is 1 to 1.

      But on the other side, if your string contains other types of letters… for example, you might be working with text data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent your UTF-8 string will likely be much higher than the number of characters in that string.

      If you need to iterate through the characters of a string, instead of its bytes, then, you can use the std.unicode.Utf8View struct to create an iterator that iterates through the unicode points of your string.

      diff --git a/docs/search.json b/docs/search.json index 07f2b577..fbcaa66e 100644 --- a/docs/search.json +++ b/docs/search.json @@ -104,7 +104,7 @@ "href": "Chapters/01-zig-weird.html", "title": "1  Introducing Zig", "section": "", - "text": "1.1 What is Zig?\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of Zig as a modern and better version of C.\nIn the author’s personal interpretation, Zig is tightly connected with “less is more”. Instead of trying to become a modern language by adding more and more features, many of the core improvements that Zig brings to the table are actually about removing annoying behaviours/features from C and C++. In other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour. As a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\nThis philosophy becomes clear with the following phrase from the official website of Zig:\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language, with tons of features, and also, there are lots of different “flavors of C++”. These elements are what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction. Zig is a very simple language, more closely related to other simple languages such as C and Go.\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it’s still hard sometimes to read and understand C code. For example, pre-processor macros in C are a frequent source of confusion. Sometimes, they really make it hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures your C code. With macros, you are no longer 100% sure about which pieces of the code are being sent to the compiler, i.e. they obscure the actual source code that you wrote.\nYou don’t have macros in Zig. In Zig, the code you write, is the actual code that gets compiled by the compiler. You also don’t have a hidden control flow happening behind the scenes. And, you also don’t have functions or operators from the standard library that make hidden memory allocations behind your back.\nBy being a simpler language, Zig becomes much more clear and easier to read/write, but at the same time, it also achieves a much more robust state, with more consistent behaviour in edge situations. Once again, less is more.", + "text": "1.1 What is Zig?\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of Zig as a modern and better version of C.\nIn the author’s personal interpretation, Zig is tightly connected with “less is more”. Instead of trying to become a modern language by adding more and more features, many of the core improvements that Zig brings to the table are actually about removing annoying behaviours/features from C and C++. In other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour. As a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\nThis philosophy becomes clear with the following phrase from the official website of Zig:\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language, with tons of features, and also, there are lots of different “flavors of C++”. These elements are what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction. Zig is a very simple language, more closely related to other simple languages such as C and Go.\nThe phrase above is still important for C programmers too. Because, even C being a simple language, it’s still hard sometimes to read and understand C code. For example, pre-processor macros in C are a frequent source of confusion. Sometimes, they really make it hard to debug C programs. Because macros are essentially a second language embedded in C that obscures your C code. With macros, you are no longer 100% sure about which pieces of the code are being sent to the compiler, i.e. they obscure the actual source code that you wrote.\nYou don’t have macros in Zig. In Zig, the code you write, is the actual code that gets compiled by the compiler. You also don’t have a hidden control flow happening behind the scenes. And, you also don’t have functions or operators from the standard library that make hidden memory allocations behind your back.\nBy being a simpler language, Zig becomes much more clear and easier to read/write, but at the same time, it also achieves a much more robust state, with more consistent behaviour in edge situations. Once again, less is more.", "crumbs": [ "1  Introducing Zig" ] @@ -124,7 +124,7 @@ "href": "Chapters/01-zig-weird.html#hello-world-in-zig", "title": "1  Introducing Zig", "section": "1.2 Hello world in Zig", - "text": "1.2 Hello world in Zig\nWe begin our journey in Zig by creating a small “Hello World” program. To start a new Zig project in your computer, you simply call the init command from the zig compiler. Just create a new directory in your computer, then, init a new Zig project inside this directory, like this:\nmkdir hello_world\ncd hello_world\nzig init\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n\n1.2.1 Understanding the project files\nAfter you run the init command from the zig compiler, some new files are created inside of your current directory. First, a “source” (src) directory is created, containing two files, main.zig and root.zig. Each .zig file is a separate Zig module, which is simply a text file that contains some Zig code.\nBy convention, the main.zig module is where your main function lives. Thus, if you are building an executable program in Zig, you need to declare a main() function, which represents the entrypoint of your program, i.e., where the execution of your program begins.\nHowever, if you are building a library (instead of an executable program), then, the normal procedure is to delete this main.zig file and start with the root.zig module. By convention, the root.zig module is the root source file of your library.\ntree .\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\nThe init command also creates two additional files in our working directory: build.zig and build.zig.zon. The first file (build.zig) represents a build script written in Zig. This script is executed when you call the build command from the zig compiler. In other words, this file contains Zig code that executes the necessary steps to build the entire project.\nLow-level languages normally use a compiler to build your source code into binary executables or binary libraries. Nevertheless, this process of compiling your source code and building binary executables or binary libraries from it, became a real challenge in the programming world, once the projects became bigger and bigger. As a result, programmers created “build systems”, which are a second set of tools designed to make this process of compiling and building complex projects, easier.\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja, which are used to build complex C and C++ projects. With these systems, you can write scripts, which are called “build scripts”. They simply are scripts that describes the necessary steps to compile/build your project.\nHowever, these are separate tools, that do not belong to C/C++ compilers, like gcc or clang. As a result, in C/C++ projects, you have not only to install and manage your C/C++ compilers, but you also have to install and manage these build systems separately.\nIn Zig, we don’t need to use a separate set of tools to build our projects, because a build system is embedded inside the language itself. We can use this build system to write small scripts in Zig, which describe the necessary steps to build/compile our Zig project1. So, everything you need to build a complex Zig project is the zig compiler, and nothing more.\nThe second generated file (build.zig.zon) is a JSON-like file, in which you can describe your project, and also, declare a set of dependencies of your project that you want to fetch from the internet. In other words, you can use this build.zig.zon file to include a list of external libraries in your project.\nOne possible way to include an external Zig library in your project, is to manually build and install the library in your system, and just link your source code with the library at the build step of your project.\nHowever, if this external Zig library is available on GitHub for example, and it has a valid build.zig.zon file in root folder of the project, which describes the project, you can easily include this library in your project by simply listing this external library in your build.zig.zon file.\nIn other words, this build.zig.zon file works similarly to the package.json file in Javascript projects, or the Pipfile file in Python projects, or the Cargo.toml file in Rust projects. You can read more about this specific file in a couple of articles on the internet23, and you can also see the expected schema for this build.zig.zon file in a documentation file inside the official repository of Zig4.\n\n\n1.2.2 The file root.zig\nLet’s take a look into the root.zig file. You might have noticed that every line of code with an expression ends with a semicolon (;). This follows the syntax of a C-family programming language5.\nAlso, notice the @import() call at the first line. We use this built-in function to import functionality from other Zig modules into our current module. This @import() function works similarly to the #include pre-processor in C or C++, or, to the import statement in Python or Javascript code. In this example, we are importing the std module, which gives you access to the Zig Standard Library.\nIn this root.zig file, we can also see how assignments (i.e., creating new objects) are made in Zig. You can create a new object in Zig by using the syntax (const|var) name = value;. In the example below, we are creating two constant objects (std and testing). In Section 1.4 we talk more about objects in general.\n\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n\nFunctions in Zig are declared using the fn keyword. In this root.zig module, we are declaring a function called add(), which has two arguments named a and b. The function returns an integer of the type i32 as result.\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit the type of an object in your code, if this type can be inferred by the zig compiler (we talk more about that in Section 2.4). But there are other situations where you do need to be explicit. For example, you do have to explicitly specify the type of each function argument, and also, the return type of every function that you create in Zig.\nWe specify the type of an object or a function argument in Zig by using a colon character (:) followed by the type after the name of this object/function argument. With the expressions a: i32 and b: i32, we know that both a and b arguments have type i32, which is a signed 32 bit integer. In this part, the syntax in Zig is identical to the syntax in Rust, which also specifies types by using the colon character.\nLastly, we have the return type of the function at the end of the line, before we open the curly braces to start writing the function’s body. In the example above, this type is also a signed 32 bit integer (i32) value.\nNotice that we also have an export keyword before the function declaration. This keyword is similar to the extern keyword in C. It exposes the function to make it available in the library API. Therefore, if you are writing a library for other people to use, you have to expose the functions you write in the public API of this library by using this export keyword. If we removed the export keyword from the add() function declaration, then, this function would be no longer exposed in the library object built by the zig compiler.\n\n\n1.2.3 The main.zig file\nNow that we have learned a lot about Zig’s syntax from the root.zig file, let’s take a look at the main.zig file. A lot of the elements we saw in root.zig are also present in main.zig. But there are some other elements that we haven’t seen yet, so let’s dive in.\nFirst, look at the return type of the main() function in this file. We can see a small change. The return type of the function (void) is accompanied by an exclamation mark (!). This exclamation mark tells us that this main() function might return an error.\nIt’s worth noting that, a main() function in Zig is allowed to return nothing (void), or an unsigned 8-bit integer (u8) value6, or an error. In other words, you can write your main() function in Zig to return essentially nothing (void), or, if you prefer, you can also write a more C-like main() function, which returns an integer value that usually serves as a “status code” for the process.\nIn this example, the return type annotation of main() indicates that this function can either return nothing (void), or return an error. This exclamation mark in the return type annotation is an interesting and powerful feature of Zig. In summary, if you write a function and something inside the body of this function might return an error, then, you are forced to:\n\neither add the exclamation mark to the return type of the function and make it clear that this function might return an error.\nexplicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through a try catch pattern. Zig does have both try and catch keywords. But they work a little differently than what you’re probably used to in other languages.\nIf we look at the main() function below, you can see that we do have a try keyword on the 5th line. But we do not have a catch keyword in this code. In Zig, we use the try keyword to execute an expression that might return an error, which, in this example, is the stdout.print() expression.\nIn essence, the try keyword executes the expression stdout.print(). If this expression returns a valid value, then, the try keyword does absolutely nothing. It only passes the value forward. It’s like if this try keyword was never there. However, if the expression does return an error, then, the try keyword will unwrap the error value, then, it returns this error from the function and also prints the current stack trace to stderr.\nThis might sound weird to you if you come from a high-level language. Because in high-level languages, such as Python, if an error occurs somewhere, this error is automatically returned and the execution of your program will automatically stop even if you don’t want to stop the execution. You are obligated to face the error.\n\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n\nAnother thing that you might have noticed in this code example, is that the main() function is marked with the pub keyword. It marks the main() function as a public function from this module. Every function in your Zig module is by default private to this Zig module and can only be called from within the module. Unless, you explicitly mark this function as a public function with the pub keyword.\nIf you think about it, this pub keyword in Zig does essentially the opposite of what the static keyword do in C/C++. By making a function “public” you allow other Zig modules to access and call this function. A calling Zig module imports another module by using the @import() built-in function, which makes all public functions from the imported module visible to the calling Zig module.\n\n\n1.2.4 Compiling your source code\nYou can compile your Zig modules into a binary executable by running the build-exe command from the zig compiler. You simply list all the Zig modules that you want to build after the build-exe command, separated by spaces. In the example below, we are compiling the module main.zig.\nzig build-exe src/main.zig\nSince we are building an executable, the zig compiler will look for a main() function declared in any of the files that you list after the build-exe command. If the compiler does not find a main() function declared somewhere, a compilation error will be raised, warning about this mistake.\nThe zig compiler also offers a build-lib and build-obj commands, which work the exact same way as the build-exe command. The only difference is that, they compile your Zig modules into a portable C ABI library, or, into object files, respectively.\nIn the case of the build-exe command, a binary executable file is created by the zig compiler in the root directory of your project. If we take a look now at the contents of our current directory, with a simple ls command, we can see the binary file called main that was created by the compiler.\nls\nbuild.zig build.zig.zon main src\nIf I execute this binary executable, I get the “Hello World” message in the terminal , as we expected.\n./main\nHello, world!\n\n\n1.2.5 Compile and execute at the same time\nIn the previous section, I presented the zig build-exe command, which compiles Zig modules into an executable file. However, this means that, in order to execute the executable file, we have to run two different commands. First, the zig build-exe command, and then, we call the executable file created by the compiler.\nBut what if we wanted to perform these two steps, all at once, in a single command? We can do that by using the zig run command.\nzig run src/main.zig\nHello, world!\n\n\n1.2.6 Important note for Windows users\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other operating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that includes some global variables whose initialization rely on runtime resources, then, you might have some troubles while trying to compile this Zig code on Windows.\nAn example of that is accessing the stdout (i.e., the standard output of your system), which is usually done in Zig by using the expression std.io.getStdOut(). If you use this expression to instantiate a global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows, with an “unable to evaluate comptime expression” error message.\nThis failure in the compilation process happens because all global variables in Zig are initialized at compile-time. However, on Windows, operations like accessing the stdout (or opening a file) depend on resources that are available only at runtime (you will learn more about compile-time versus runtime in Section 3.1.1).\nFor example, if you try to compile this code example on Windows, you will likely get the error message exposed below:\n\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerges from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\nTo avoid this problem on Windows, we need to force the zig compiler to instantiate this stdout object only at runtime, instead of instantiating it at compile-time. We can achieve that by simply moving the expression to a function body.\nThis solves the problem because all expressions that are inside a function body in Zig are evaluated only at runtime, unless you use the comptime keyword explicitly to change this behaviour. You will learn more about this comptime keyword in Section 12.1.\n\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n\nHello\nYou can read more details about this Windows-specific limitation in a couple of GitHub issues opened at the official Zig repository. More specifically, the issues\n17186 7 and 19864 8.\n\n\n1.2.7 Compiling the entire project\nJust as I described in Section 1.2.1, as our project grows in size and complexity, we usually prefer to organize the compilation and build process of the project into a build script, using some sort of “build system”.\nIn other words, as our project grows in size and complexity, the build-exe, build-lib and build-obj commands become harder to use directly. Because then, we start to list multiple and multiple modules at the same time. We also start to add built-in compilation flags to customize the build process for our needs, etc. It becomes a lot of work to write the necessary commands by hand.\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, Makefile or configure scripts to organize this process. However, in Zig, we have a native build system in the language itself. So, we can write build scripts in Zig to compile and build Zig projects. Then, all we need to do, is to call the zig build command to build our project.\nSo, when you execute the zig build command, the zig compiler will search for a Zig module named build.zig inside your current directory, which should be your build script, containing the necessary code to compile and build your project. If the compiler does find this build.zig file in your directory, then, the compiler will essentially execute a zig run command over this build.zig file, to compile and execute this build script, which in turn, will compile and build your entire project.\nzig build\nAfter you execute this “build project” command, a zig-out directory is created in the root of your project directory, where you can find the binary executables and libraries created from your Zig modules accordingly to the build commands that you specified at build.zig. We will talk more about the build system in Zig later in this book.\nIn the example below, I’m executing the binary executable named hello_world that was generated by the compiler after the zig build command.\n./zig-out/bin/hello_world\nHello, world!", + "text": "1.2 Hello world in Zig\nWe begin our journey in Zig by creating a small “Hello World” program. To start a new Zig project in your computer, you simply call the init command from the zig compiler. Just create a new directory in your computer, then, init a new Zig project inside this directory, like this:\nmkdir hello_world\ncd hello_world\nzig init\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n\n1.2.1 Understanding the project files\nAfter you run the init command from the zig compiler, some new files are created inside of your current directory. First, a “source” (src) directory is created, containing two files, main.zig and root.zig. Each .zig file is a separate Zig module, which is simply a text file that contains some Zig code.\nBy convention, the main.zig module is where your main function lives. Thus, if you are building an executable program in Zig, you need to declare a main() function, which represents the entrypoint of your program, i.e., where the execution of your program begins.\nHowever, if you are building a library (instead of an executable program), then, the normal procedure is to delete this main.zig file and start with the root.zig module. By convention, the root.zig module is the root source file of your library.\ntree .\n.\n├── build.zig\n├── build.zig.zon\n└── src\n ├── main.zig\n └── root.zig\n\n1 directory, 4 files\nThe init command also creates two additional files in our working directory: build.zig and build.zig.zon. The first file (build.zig) represents a build script written in Zig. This script is executed when you call the build command from the zig compiler. In other words, this file contains Zig code that executes the necessary steps to build the entire project.\nLow-level languages normally use a compiler to build your source code into binary executables or binary libraries. Nevertheless, this process of compiling your source code and building binary executables or binary libraries from it, became a real challenge in the programming world, once the projects became bigger and bigger. As a result, programmers created “build systems”, which are a second set of tools designed to make this process of compiling and building complex projects, easier.\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja, which are used to build complex C and C++ projects. With these systems, you can write scripts, which are called “build scripts”. They simply are scripts that describes the necessary steps to compile/build your project.\nHowever, these are separate tools, that do not belong to C/C++ compilers, like gcc or clang. As a result, in C/C++ projects, you have not only to install and manage your C/C++ compilers, but you also have to install and manage these build systems separately.\nIn Zig, we don’t need to use a separate set of tools to build our projects, because a build system is embedded inside the language itself. We can use this build system to write small scripts in Zig, which describe the necessary steps to build/compile our Zig project1. So, everything you need to build a complex Zig project is the zig compiler, and nothing more.\nThe second generated file (build.zig.zon) is a JSON-like file, in which you can describe your project, and also, declare a set of dependencies of your project that you want to fetch from the internet. In other words, you can use this build.zig.zon file to include a list of external libraries in your project.\nOne possible way to include an external Zig library in your project, is to manually build and install the library in your system, and just link your source code with the library at the build step of your project.\nHowever, if this external Zig library is available on GitHub for example, and it has a valid build.zig.zon file in root folder of the project, which describes the project, you can easily include this library in your project by simply listing this external library in your build.zig.zon file.\nIn other words, this build.zig.zon file works similarly to the package.json file in Javascript projects, or the Pipfile file in Python projects, or the Cargo.toml file in Rust projects. You can read more about this specific file in a couple of articles on the internet23, and you can also see the expected schema for this build.zig.zon file in a documentation file inside the official repository of Zig4.\n\n\n1.2.2 The file root.zig\nLet’s take a look into the root.zig file. You might have noticed that every line of code with an expression ends with a semicolon (;). This follows the syntax of a C-family programming language5.\nAlso, notice the @import() call at the first line. We use this built-in function to import functionality from other Zig modules into our current module. This @import() function works similarly to the #include pre-processor in C or C++, or, to the import statement in Python or Javascript code. In this example, we are importing the std module, which gives you access to the Zig Standard Library.\nIn this root.zig file, we can also see how assignments (i.e., creating new objects) are made in Zig. You can create a new object in Zig by using the syntax (const|var) name = value;. In the example below, we are creating two constant objects (std and testing). In Section 1.4 we talk more about objects in general.\n\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n\nFunctions in Zig are declared using the fn keyword. In this root.zig module, we are declaring a function called add(), which has two arguments named a and b. The function returns an integer of the type i32 as result.\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit the type of an object in your code, if this type can be inferred by the zig compiler (we talk more about that in Section 2.4). But there are other situations where you do need to be explicit. For example, you do have to explicitly specify the type of each function argument, and also, the return type of every function that you create in Zig.\nWe specify the type of an object or a function argument in Zig by using a colon character (:) followed by the type after the name of this object/function argument. With the expressions a: i32 and b: i32, we know that both a and b arguments have type i32, which is a signed 32 bit integer. In this part, the syntax in Zig is identical to the syntax in Rust, which also specifies types by using the colon character.\nLastly, we have the return type of the function at the end of the line, before we open the curly braces to start writing the function’s body. In the example above, this type is also a signed 32 bit integer (i32) value.\nNotice that we also have an export keyword before the function declaration. This keyword is similar to the extern keyword in C. It exposes the function to make it available in the library API. Therefore, if you are writing a library for other people to use, you have to expose the functions you write in the public API of this library by using this export keyword. If we removed the export keyword from the add() function declaration, then, this function would be no longer exposed in the library object built by the zig compiler.\n\n\n1.2.3 The main.zig file\nNow that we have learned a lot about Zig’s syntax from the root.zig file, let’s take a look at the main.zig file. A lot of the elements we saw in root.zig are also present in main.zig. But there are some other elements that we haven’t seen yet, so let’s dive in.\nFirst, look at the return type of the main() function in this file. We can see a small change. The return type of the function (void) is accompanied by an exclamation mark (!). This exclamation mark tells us that this main() function might return an error.\nIt’s worth noting that, a main() function in Zig is allowed to return nothing (void), or an unsigned 8-bit integer (u8) value6, or an error. In other words, you can write your main() function in Zig to return essentially nothing (void), or, if you prefer, you can also write a more C-like main() function, which returns an integer value that usually serves as a “status code” for the process.\nIn this example, the return type annotation of main() indicates that this function can either return nothing (void), or return an error. This exclamation mark in the return type annotation is an interesting and powerful feature of Zig. In summary, if you write a function and something inside the body of this function might return an error, then, you are forced to:\n\neither add the exclamation mark to the return type of the function and make it clear that this function might return an error.\nexplicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through a try catch pattern. Zig does have both try and catch keywords. But they work a little differently than what you’re probably used to in other languages.\nIf we look at the main() function below, you can see that we do have a try keyword on the 5th line. But we do not have a catch keyword in this code. In Zig, we use the try keyword to execute an expression that might return an error, which, in this example, is the stdout.print() expression.\nIn essence, the try keyword executes the expression stdout.print(). If this expression returns a valid value, then, the try keyword does absolutely nothing. It only passes the value forward. It’s like if this try keyword was never there. However, if the expression does return an error, then, the try keyword will unwrap the error value, then, it returns this error from the function and also prints the current stack trace to stderr.\nThis might sound weird to you if you come from a high-level language. Because in high-level languages, such as Python, if an error occurs somewhere, this error is automatically returned and the execution of your program will automatically stop even if you don’t want to stop the execution. You are obligated to face the error.\n\nconst std = @import(\"std\");\n\npub fn main() !void {\n const stdout = std.io.getStdOut().writer();\n try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n\nAnother thing that you might have noticed in this code example, is that the main() function is marked with the pub keyword. It marks the main() function as a public function from this module. Every function in your Zig module is by default private to this Zig module and can only be called from within the module. Unless, you explicitly mark this function as a public function with the pub keyword.\nIf you think about it, this pub keyword in Zig does essentially the opposite of what the static keyword do in C/C++. By making a function “public” you allow other Zig modules to access and call this function. A calling Zig module imports another module by using the @import() built-in function, which makes all public functions from the imported module visible to the calling Zig module.\n\n\n1.2.4 Compiling your source code\nYou can compile your Zig modules into a binary executable by running the build-exe command from the zig compiler. You simply list all the Zig modules that you want to build after the build-exe command, separated by spaces. In the example below, we are compiling the module main.zig.\nzig build-exe src/main.zig\nSince we are building an executable, the zig compiler will look for a main() function declared in any of the files that you list after the build-exe command. If the compiler does not find a main() function declared somewhere, a compilation error will be raised, warning about this mistake.\nThe zig compiler also offers a build-lib and build-obj commands, which work the exact same way as the build-exe command. The only difference is that, they compile your Zig modules into a portable C ABI library, or, into object files, respectively.\nIn the case of the build-exe command, a binary executable file is created by the zig compiler in the root directory of your project. If we take a look now at the contents of our current directory, with a simple ls command, we can see the binary file called main that was created by the compiler.\nls\nbuild.zig build.zig.zon main src\nIf I execute this binary executable, I get the “Hello World” message in the terminal , as we expected.\n./main\nHello, world!\n\n\n1.2.5 Compile and execute at the same time\nIn the previous section, I presented the zig build-exe command, which compiles Zig modules into an executable file. However, this means that, in order to execute the executable file, we have to run two different commands. First, the zig build-exe command, and then, we call the executable file created by the compiler.\nBut what if we wanted to perform these two steps, all at once, in a single command? We can do that by using the zig run command.\nzig run src/main.zig\nHello, world!\n\n\n1.2.6 Important note for Windows users\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other operating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that includes some global variables whose initialization rely on runtime resources, then, you might have some troubles while trying to compile this Zig code on Windows.\nAn example of that is accessing the stdout (i.e., the standard output of your system), which is usually done in Zig by using the expression std.io.getStdOut(). If you use this expression to instantiate a global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows, with an “unable to evaluate comptime expression” error message.\nThis failure in the compilation process happens because all global variables in Zig are initialized at compile-time. However, on Windows, operations like accessing the stdout (or opening a file) depend on resources that are available only at runtime (you will learn more about compile-time versus runtime in Section 3.1.1).\nFor example, if you try to compile this code example on Windows, you will likely get the error message exposed below:\n\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerges from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n _ = try stdout.write(\"Hello\\n\");\n}\n\nt.zig:2107:28: error: unable to evaluate comptime expression\n break :blk asm {\n ^~~\nTo avoid this problem on Windows, we need to force the zig compiler to instantiate this stdout object only at runtime, instead of instantiating it at compile-time. We can achieve that by simply moving the expression to a function body.\nThis solves the problem because all expressions that are inside a function body in Zig are evaluated only at runtime, unless you use the comptime keyword explicitly to change this behaviour. You will learn more about this comptime keyword in Section 12.1.\n\nconst std = @import(\"std\");\npub fn main() !void {\n // SUCCESS: Stdout initialized at runtime.\n const stdout = std.io.getStdOut().writer();\n _ = try stdout.write(\"Hello\\n\");\n}\n\nHello\nYou can read more details about this Windows-specific limitation in a couple of GitHub issues opened at the official Zig repository. More specifically, the issues 17186 7 and 19864 8.\n\n\n1.2.7 Compiling the entire project\nJust as I described in Section 1.2.1, as our project grows in size and complexity, we usually prefer to organize the compilation and build process of the project into a build script, using some sort of “build system”.\nIn other words, as our project grows in size and complexity, the build-exe, build-lib and build-obj commands become harder to use directly. Because then, we start to list multiple and multiple modules at the same time. We also start to add built-in compilation flags to customize the build process for our needs, etc. It becomes a lot of work to write the necessary commands by hand.\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, Makefile or configure scripts to organize this process. However, in Zig, we have a native build system in the language itself. So, we can write build scripts in Zig to compile and build Zig projects. Then, all we need to do, is to call the zig build command to build our project.\nSo, when you execute the zig build command, the zig compiler will search for a Zig module named build.zig inside your current directory, which should be your build script, containing the necessary code to compile and build your project. If the compiler does find this build.zig file in your directory, then, the compiler will essentially execute a zig run command over this build.zig file, to compile and execute this build script, which in turn, will compile and build your entire project.\nzig build\nAfter you execute this “build project” command, a zig-out directory is created in the root of your project directory, where you can find the binary executables and libraries created from your Zig modules accordingly to the build commands that you specified at build.zig. We will talk more about the build system in Zig later in this book.\nIn the example below, I’m executing the binary executable named hello_world that was generated by the compiler after the zig build command.\n./zig-out/bin/hello_world\nHello, world!", "crumbs": [ "1  Introducing Zig" ] @@ -154,7 +154,7 @@ "href": "Chapters/01-zig-weird.html#sec-primitive-data-types", "title": "1  Introducing Zig", "section": "1.5 Primitive Data Types", - "text": "1.5 Primitive Data Types\nZig have many different primitive data types available for you to use. You can see the full list of available data types at the official Language Reference page21.\nBut here is a quick list:\n\nUnsigned integers: u8, 8-bit integer; u16, 16-bit integer; u32, 32-bit integer; u64, 64-bit integer; u128, 128-bit integer.\nSigned integers: i8, 8-bit integer; i16, 16-bit integer; i32, 32-bit integer; i64, 64-bit integer; i128, 128-bit integer.\nFloat number: f16, 16-bit floating point; f32, 32-bit floating point; f64, 64-bit floating point; f128, 128-bit floating point;\nBoolean: bool, represents true or false values.\nC ABI compatible types: c_long, c_char, c_short, c_ushort, c_int, c_uint, and many others.\nPointer sized integers: isize and usize.", + "text": "1.5 Primitive Data Types\nZig has many different primitive data types available for you to use. You can see the full list of available data types at the official Language Reference page21.\nBut here is a quick list:\n\nUnsigned integers: u8, 8-bit integer; u16, 16-bit integer; u32, 32-bit integer; u64, 64-bit integer; u128, 128-bit integer.\nSigned integers: i8, 8-bit integer; i16, 16-bit integer; i32, 32-bit integer; i64, 64-bit integer; i128, 128-bit integer.\nFloat number: f16, 16-bit floating point; f32, 32-bit floating point; f64, 64-bit floating point; f128, 128-bit floating point;\nBoolean: bool, represents true or false values.\nC ABI compatible types: c_long, c_char, c_short, c_ushort, c_int, c_uint, and many others.\nPointer sized integers: isize and usize.", "crumbs": [ "1  Introducing Zig" ] @@ -164,7 +164,7 @@ "href": "Chapters/01-zig-weird.html#sec-arrays", "title": "1  Introducing Zig", "section": "1.6 Arrays", - "text": "1.6 Arrays\nYou create arrays in Zig by using a syntax that resembles the C syntax. First, you specify the size of the array (i.e., the number of elements that will be stored in the array) you want to create inside a pair of brackets.\nThen, you specify the data type of the elements that will be stored inside this array. All elements present in an array in Zig must have the same data type. For example, you cannot mix elements of type f32 with elements of type i32 in the same array.\nAfter that, you simply list the values that you want to store in this array inside a pair of curly braces. In the example below, I am creating two constant objects that contain different arrays. The first object contains an array of 4 integer values, while the second object, an array of 3 floating point values.\nNow, you should notice that in the object ls, I am not explicitly specifying the size of the array inside of the brackets. Instead of using a literal value (like the value 4 that I used in the ns object), I am using the special character underscore (_). This syntax tells the zig compiler to fill this field with the number of elements listed inside of the curly braces. So, this syntax [_] is for lazy (or smart) programmers who leave the job of counting how many elements there are in the curly braces for the compiler.\n\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n\nIt’s worth noting that these are static arrays, meaning that they cannot grow in size. Once you declare your array, you cannot change the size of it. This is very common in low level languages. Because low level languages normally wants to give you (the programmer) full control over memory, and the way in which arrays are expanded is tightly related to memory management.\n\n1.6.1 Selecting elements of the array\nOne very common activity is to select specific portions of an array you have in your source code. In Zig, you can select a specific element from your array, by simply providing the index of this particular element inside brackets after the object name. In the example below, I am selecting the third element from the ns array. Notice that Zig is a “zero-index” based language, like C, C++, Rust, Python, and many other languages.\n\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n\n12\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a range selector. Some programmers also call these selectors of “slice selectors”, and they also exist in Rust, and have the exact same syntax as in Zig. Anyway, a range selector is a special expression in Zig that defines a range of indexes, and it have the syntax start..end.\nIn the example below, at the second line of code, the sl object stores a slice (or a portion) of the ns array. More precisely, the elements at index 1 and 2 in the ns array.\n\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n\nWhen you use the start..end syntax, the “end tail” of the range selector is non-inclusive, meaning that, the index at the end is not included in the range that is selected from the array. Therefore, the syntax start..end actually means start..end - 1 in practice.\nYou can for example, create a slice that goes from the first to the last elements of the array, by using ar[0..ar.len] syntax In other words, it’s a slice that accesses all elements in the array.\n\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n\nYou can also use the syntax start.. in your range selector. Which tells the zig compiler to select the portion of the array that begins at the start index until the last element of the array. In the example below, we are selecting the range from index 1 until the end of the array.\n\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n\n\n\n1.6.2 More on slices\nAs we discussed before, in Zig, you can select specific portions of an existing array. This is called slicing in Zig (Sobeston 2024), because when you select a portion of an array, you are creating a slice object from that array.\nA slice object is essentially a pointer object accompanied by a length number. The pointer object points to the first element in the slice, and the length number tells the zig compiler how many elements there are in this slice.\n\nSlices can be thought of as a pair of [*]T (the pointer to the data) and a usize (the element count) (Sobeston 2024).\n\nThrough the pointer contained inside the slice you can access the elements (or values) that are inside this range (or portion) that you selected from the original array. But the length number (which you can access through the len property of your slice object) is the really big improvement (over C arrays for example) that Zig brings to the table here.\nBecause with this length number the zig compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice, or, if you are causing any buffer overflow problems. In the example below, we access the len property of the slice sl, which tells us that this slice have 2 elements in it.\n\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n\n2\n\n\n\n\n1.6.3 Array operators\nThere are two array operators available in Zig that are very useful. The array concatenation operator (++), and the array multiplication operator (**). As the name suggests, these are array operators.\nOne important detail about these two operators is that they work only when both operands have a size (or “length”) that is compile-time known. We are going to talk more about the differences between “compile-time known” and “runtime known” in Section 3.1.1. But for now, keep this information in mind, that you cannot use these operators in every situation.\nIn summary, the ++ operator creates a new array that is the concatenation, of both arrays provided as operands. So, the expression a ++ b produces a new array which contains all the elements from arrays a and b.\n\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n\n{ 1, 2, 3, 4, 5 }\n\n\nThis ++ operator is particularly useful to concatenate strings together. Strings in Zig are described in depth in Section 1.8. In summary, a string object in Zig is essentially an arrays of bytes. So, you can use this array concatenation operator to effectively concatenate strings together.\nIn contrast, the ** operator is used to replicate an array multiple times. In other words, the expression a ** 3 creates a new array which contains the elements of the array a repeated 3 times.\n\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n\n{ 1, 2, 3, 1, 2, 3 }\n\n\n\n\n1.6.4 Runtime versus compile-time known length in slices\nWe are going to talk a lot about the differences between compile-time known and runtime known across this book, especially in Section 3.1.1. But the basic idea is that a thing is compile-time known, when we know everything (the value, the attributes and the characteristics) about this thing at compile-time. In contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime. Therefore, we don’t know the value of this thing at compile-time, only at runtime.\nWe have learned in Section 1.6.1 that slices are created by using a range selector, which represents a range of indexes. When this “range of indexes” (i.e., both the start and the end of this range) is known at compile-time, the slice object that gets created is actually, under the hood, just a single-item pointer to an array.\nYou don’t need to precisely understand what that means now. We are going to talk a lot about pointers in Chapter 6. For now, just understand that, when the range of indexes is known at compile-time, the slice that gets created is just a pointer to an array, accompanied by a length value that tells the size of the slice.\nIf you have a slice object like this, i.e., a slice that has a compile-time known range, you can use common pointer operations over this slice object. For example, you can dereference the pointer of this slice, by using the .* method, like you would do on a normal pointer object.\n\nconst arr1 = [10]u64 {\n 1, 2, 3, 4, 5,\n 6, 7, 8, 9, 10\n};\n// This slice have a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n_ = slice;\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object that gets created is not a pointer anymore, and, thus, it does not support pointer operations. For example, maybe the start index is known at compile time, but the end index is not. In such case, the range of the slice becomes runtime known only.\nIn the example below, we are reading a file, and then, we try to create a slice object that covers the entire buffer that contains the contents of this file. This is obviously an example of a runtime known range, because the end index of the range is not known at compile time.\nIn other words, the end index of the range is the size of the array file_contents. However, the size of file_contents is not known at compile time. Because we don’t know how many bytes are stored inside this shop-list.txt file. And because this is a file, someone might edit this file tomorrow and add more lines or remove lines from it. Therefore, the size of this file might vary drastically from one execution to another.\nNow, if the file size can vary from one run to another, then, we can conclude that the value of the expression file_contents.len exposed in the example below can also vary from one run to another. As consequence, the value of the expression file_contents.len is runtime-known only, and, as a consequence of that, the range 0..file_contents.len is also runtime-known only.\n\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\nfn read_file(allocator: std.mem.Allocator, path: []const u8) ![]u8 {\n const file = try std.fs.cwd().openFile(path, .{});\n defer file.close();\n return try file.reader().readAllAlloc(\n allocator, std.math.maxInt(usize)\n );\n}\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const path = \"../ZigExamples/file-io/shop-list.txt\";\n const file_contents = try read_file(allocator, path);\n const slice = file_contents[0..file_contents.len];\n _ = slice;\n}", + "text": "1.6 Arrays\nYou create arrays in Zig by using a syntax that resembles the C syntax. First, you specify the size of the array (i.e., the number of elements that will be stored in the array) you want to create inside a pair of brackets.\nThen, you specify the data type of the elements that will be stored inside this array. All elements present in an array in Zig must have the same data type. For example, you cannot mix elements of type f32 with elements of type i32 in the same array.\nAfter that, you simply list the values that you want to store in this array inside a pair of curly braces. In the example below, I am creating two constant objects that contain different arrays. The first object contains an array of 4 integer values, while the second object, an array of 3 floating point values.\nNow, you should notice that in the object ls, I am not explicitly specifying the size of the array inside of the brackets. Instead of using a literal value (like the value 4 that I used in the ns object), I am using the special character underscore (_). This syntax tells the zig compiler to fill this field with the number of elements listed inside of the curly braces. So, this syntax [_] is for lazy (or smart) programmers who leave the job of counting how many elements there are in the curly braces for the compiler.\n\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n\nIt’s worth noting that these are static arrays, meaning that they cannot grow in size. Once you declare your array, you cannot change the size of it. This is very common in low level languages. Because low level languages normally wants to give you (the programmer) full control over memory, and the way in which arrays are expanded is tightly related to memory management.\n\n1.6.1 Selecting elements of the array\nOne very common activity is to select specific portions of an array you have in your source code. In Zig, you can select a specific element from your array, by simply providing the index of this particular element inside brackets after the object name. In the example below, I am selecting the third element from the ns array. Notice that Zig is a “zero-index” based language, like C, C++, Rust, Python, and many other languages.\n\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n\n12\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a range selector. Some programmers also call these selectors of “slice selectors”, and they also exist in Rust, and have the exact same syntax as in Zig. Anyway, a range selector is a special expression in Zig that defines a range of indexes, and it has the syntax start..end.\nIn the example below, at the second line of code, the sl object stores a slice (or a portion) of the ns array. More precisely, the elements at index 1 and 2 in the ns array.\n\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n\nWhen you use the start..end syntax, the “end tail” of the range selector is non-inclusive, meaning that, the index at the end is not included in the range that is selected from the array. Therefore, the syntax start..end actually means start..end - 1 in practice.\nYou can for example, create a slice that goes from the first to the last elements of the array, by using ar[0..ar.len] syntax In other words, it’s a slice that accesses all elements in the array.\n\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n\nYou can also use the syntax start.. in your range selector. Which tells the zig compiler to select the portion of the array that begins at the start index until the last element of the array. In the example below, we are selecting the range from index 1 until the end of the array.\n\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n\n\n\n1.6.2 More on slices\nAs we discussed before, in Zig, you can select specific portions of an existing array. This is called slicing in Zig (Sobeston 2024), because when you select a portion of an array, you are creating a slice object from that array.\nA slice object is essentially a pointer object accompanied by a length number. The pointer object points to the first element in the slice, and the length number tells the zig compiler how many elements there are in this slice.\n\nSlices can be thought of as a pair of [*]T (the pointer to the data) and a usize (the element count) (Sobeston 2024).\n\nThrough the pointer contained inside the slice you can access the elements (or values) that are inside this range (or portion) that you selected from the original array. But the length number (which you can access through the len property of your slice object) is the really big improvement (over C arrays for example) that Zig brings to the table here.\nBecause with this length number the zig compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice, or, if you are causing any buffer overflow problems. In the example below, we access the len property of the slice sl, which tells us that this slice has 2 elements in it.\n\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n\n2\n\n\n\n\n1.6.3 Array operators\nThere are two array operators available in Zig that are very useful. The array concatenation operator (++), and the array multiplication operator (**). As the name suggests, these are array operators.\nOne important detail about these two operators is that they work only when both operands have a size (or “length”) that is compile-time known. We are going to talk more about the differences between “compile-time known” and “runtime known” in Section 3.1.1. But for now, keep this information in mind, that you cannot use these operators in every situation.\nIn summary, the ++ operator creates a new array that is the concatenation, of both arrays provided as operands. So, the expression a ++ b produces a new array which contains all the elements from arrays a and b.\n\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n\n{ 1, 2, 3, 4, 5 }\n\n\nThis ++ operator is particularly useful to concatenate strings together. Strings in Zig are described in depth in Section 1.8. In summary, a string object in Zig is essentially an arrays of bytes. So, you can use this array concatenation operator to effectively concatenate strings together.\nIn contrast, the ** operator is used to replicate an array multiple times. In other words, the expression a ** 3 creates a new array which contains the elements of the array a repeated 3 times.\n\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n\n{ 1, 2, 3, 1, 2, 3 }\n\n\n\n\n1.6.4 Runtime versus compile-time known length in slices\nWe are going to talk a lot about the differences between compile-time known and runtime known across this book, especially in Section 3.1.1. But the basic idea is that a thing is compile-time known, when we know everything (the value, the attributes and the characteristics) about this thing at compile-time. In contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime. Therefore, we don’t know the value of this thing at compile-time, only at runtime.\nWe have learned in Section 1.6.1 that slices are created by using a range selector, which represents a range of indexes. When this “range of indexes” (i.e., both the start and the end of this range) is known at compile-time, the slice object that gets created is actually, under the hood, just a single-item pointer to an array.\nYou don’t need to precisely understand what that means now. We are going to talk a lot about pointers in Chapter 6. For now, just understand that, when the range of indexes is known at compile-time, the slice that gets created is just a pointer to an array, accompanied by a length value that tells the size of the slice.\nIf you have a slice object like this, i.e., a slice that has a compile-time known range, you can use common pointer operations over this slice object. For example, you can dereference the pointer of this slice, by using the .* method, like you would do on a normal pointer object.\n\nconst arr1 = [10]u64 {\n 1, 2, 3, 4, 5,\n 6, 7, 8, 9, 10\n};\n// This slice has a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n_ = slice;\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object that gets created is not a pointer anymore, and, thus, it does not support pointer operations. For example, maybe the start index is known at compile time, but the end index is not. In such case, the range of the slice becomes runtime known only.\nIn the example below, we are reading a file, and then, we try to create a slice object that covers the entire buffer that contains the contents of this file. This is obviously an example of a runtime known range, because the end index of the range is not known at compile time.\nIn other words, the end index of the range is the size of the array file_contents. However, the size of file_contents is not known at compile time. Because we don’t know how many bytes are stored inside this shop-list.txt file. And because this is a file, someone might edit this file tomorrow and add more lines or remove lines from it. Therefore, the size of this file might vary drastically from one execution to another.\nNow, if the file size can vary from one run to another, then, we can conclude that the value of the expression file_contents.len exposed in the example below can also vary from one run to another. As consequence, the value of the expression file_contents.len is runtime-known only, and, as a consequence of that, the range 0..file_contents.len is also runtime-known only.\n\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\nfn read_file(allocator: std.mem.Allocator, path: []const u8) ![]u8 {\n const file = try std.fs.cwd().openFile(path, .{});\n defer file.close();\n return try file.reader().readAllAlloc(\n allocator, std.math.maxInt(usize)\n );\n}\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const path = \"../ZigExamples/file-io/shop-list.txt\";\n const file_contents = try read_file(allocator, path);\n const slice = file_contents[0..file_contents.len];\n _ = slice;\n}", "crumbs": [ "1  Introducing Zig" ] @@ -174,7 +174,7 @@ "href": "Chapters/01-zig-weird.html#sec-blocks", "title": "1  Introducing Zig", "section": "1.7 Blocks and scopes", - "text": "1.7 Blocks and scopes\nBlocks are created in Zig by a pair of curly braces. A block is just a group of expressions (or statements) contained inside of a pair of curly braces. All of these expressions that are contained inside of this pair of curly braces belongs to the same scope.\nIn other words, a block just delimits a scope in your code. The objects that you define inside the same block belongs to the same scope, and, therefore, are accessible from within this scope. At the same time, these objects are not accessible outside of this scope. So, you could also say that blocks are used to limit the scope of the objects that you create in your source code. In less technical terms, blocks are used to specify where in your source code you can access whatever object you have in your source code.\nSo, a block is just a group of expressions contained inside a pair of curly braces. And every block have its own scope separated from the others. The body of a function is a classic example of a block. If statements, for and while loops (and any other structure in the language that uses the pair of curly braces) are also examples of blocks.\nThis means that, every if statement, or for loop, etc., that you create in your source code have its own separate scope. That is why you can’t access the objects that you defined inside of your for loop (or if statement) in an outer scope, i.e., a scope outside of the for loop. Because you are trying to access an object that belongs to a scope that is different than your current scope.\nYou can create blocks within blocks, with multiple levels of nesting. You can also (if you want to) give a label to a particular block, with the colon character (:). Just write label: before you open the pair of curly braces that delimits your block. When you label a block in Zig, you can use the break keyword to return a value from this block, like as if it was a function’s body. You just write the break keyword, followed by the block label in the format :label, and the expression that defines the value that you want to return.\nLike in the example below, where we are returning the value from the y object from the block add_one, and saving the result inside the x object.\n\nvar y: i32 = 123;\nconst x = add_one: {\n y += 1;\n break :add_one y;\n};\nif (x == 124 and y == 124) {\n try stdout.print(\"Hey!\", .{});\n}\n\nHey!", + "text": "1.7 Blocks and scopes\nBlocks are created in Zig by a pair of curly braces. A block is just a group of expressions (or statements) contained inside of a pair of curly braces. All of these expressions that are contained inside of this pair of curly braces belongs to the same scope.\nIn other words, a block just delimits a scope in your code. The objects that you define inside the same block belongs to the same scope, and, therefore, are accessible from within this scope. At the same time, these objects are not accessible outside of this scope. So, you could also say that blocks are used to limit the scope of the objects that you create in your source code. In less technical terms, blocks are used to specify where in your source code you can access whatever object you have in your source code.\nSo, a block is just a group of expressions contained inside a pair of curly braces. And every block have its own scope separated from the others. The body of a function is a classic example of a block. If statements, for and while loops (and any other structure in the language that uses the pair of curly braces) are also examples of blocks.\nThis means that, every if statement, or for loop, etc., that you create in your source code has its own separate scope. That is why you can’t access the objects that you defined inside of your for loop (or if statement) in an outer scope, i.e., a scope outside of the for loop. Because you are trying to access an object that belongs to a scope that is different than your current scope.\nYou can create blocks within blocks, with multiple levels of nesting. You can also (if you want to) give a label to a particular block, with the colon character (:). Just write label: before you open the pair of curly braces that delimits your block. When you label a block in Zig, you can use the break keyword to return a value from this block, like as if it was a function’s body. You just write the break keyword, followed by the block label in the format :label, and the expression that defines the value that you want to return.\nLike in the example below, where we are returning the value from the y object from the block add_one, and saving the result inside the x object.\n\nvar y: i32 = 123;\nconst x = add_one: {\n y += 1;\n break :add_one y;\n};\nif (x == 124 and y == 124) {\n try stdout.print(\"Hey!\", .{});\n}\n\nHey!", "crumbs": [ "1  Introducing Zig" ] @@ -184,7 +184,7 @@ "href": "Chapters/01-zig-weird.html#sec-zig-strings", "title": "1  Introducing Zig", "section": "1.8 How strings work in Zig?", - "text": "1.8 How strings work in Zig?\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (Chapter 4). But in order for us to build such a thing, we need to get a better understanding on how strings work in Zig. So let’s discuss this specific aspect of Zig.\nStrings in Zig work very similarly to strings in C, but they come with some extra caveats which adds more safety and efficiency to them. You could also say that Zig simply uses a more modern and safe approach to manage and use strings.\nA string in Zig is essentially an array of arbitrary bytes, or, more specifically, an array of u8 values. This very similar to a string in C, which is also interpreted as an array of arbitrary bytes, or, in the case of C, an array of char (which usually represents an unsigned 8-bit integer value in most systems) values.\nNow, because a string in Zig is an array, you automatically get the length of the string (i.e. the length of the array) embedded in the value itself. This makes all the difference! Because now, the Zig compiler can use the length value that is embedded in the string to check for “buffer overflow” or “wrong memory access” problems in your code.\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless. So getting this kind of safety is not automatic and much harder to do in C. For example, if you want to track the length of your string throughout your program in C, then, you first need to loop through the array of bytes that represents this string, and find the null element ('\\0') position to discover where exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\nTo do that, you would need to do something like this in C. In this example, the C string stored in the object array is 25 bytes long:\n\n#include <stdio.h>\nint main() {\n char* array = \"An example of string in C\";\n int index = 0;\n while (1) {\n if (array[index] == '\\0') {\n break;\n }\n index++;\n }\n printf(\"Number of elements in the array: %d\\n\", index);\n}\n\nNumber of elements in the array: 25\nYou don’t have this kind of work in Zig. Because the length of the string is always present and accessible in the string value itself. You can easily access the length of the string through the len attribute. As an example, the string_object object below is 43 bytes long:\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example of string literal in Zig\";\n try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n\n43\n\n\nAnother point is that Zig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every sequence of bytes you’re working with, but is not really Zig’s job to fix the encoding of your strings (you can use iconv22 for that). Today, most of the text in our modern world, especially on the web, should be UTF-8 encoded. So if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\nLet’s take for example the word “Hello”. In UTF-8, this sequence of characters (H, e, l, l, o) is represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this sequence is 0x48, 0x65, 0x6C, 0x6C, 0x6F. So if I take this sequence of hexadecimal values, and ask Zig to print this sequence of bytes as a sequence of characters (i.e., a string), then, the text “Hello” will be printed into the terminal:\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n try stdout.print(\"{s}\\n\", .{bytes});\n}\n\nHello\n\n\n\n1.8.1 Using a slice versus a sentinel-terminated array\nIn memory, all string values in Zig are always stored in the same way. They are simply stored as sequences/arrays of arbitrary bytes. But you can use and access this sequence of bytes in two different ways. You can access this sequence of bytes as:\n\na sentinel-terminated array of u8 values.\nor as a slice of u8 values.\n\n\n1.8.1.1 Sentinel-terminated arrays\nSentinel-terminated arrays in Zig are described in the Language Reference of Zig23. In summary a sentinel-terminated array is just a normal array, but, the difference is that they contain a “sentinel value” at the last index/element of the array. With a sentinel-terminated array you embed both the length of the array, and also, the sentinel value in the type itself of your object.\nFor example, if you write a string literal value in your code, and ask Zig to print the data type of this value, you usually get a data type in the format *const [n:0]u8. The n in the data type indicates the size of the string (that is the length of the array). The zero after the n: part of the data type is the sentinel value itself.\n\n// This is a string literal value:\n_ = \"A literal value\";\ntry stdout.print(\"{any}\\n\", .{@TypeOf(\"A literal value\")});\n\n*const [15:0]u8\n\n\nSo, with this data type *const [n:0]u8 you are essentially saying that you have an array of u8 values of length n, where, the element at the index corresponding to the length n in the array is the number zero. If you really think about this description, you will notice that this is just a fancy way to describe a string in C, which is a null-terminated array of bytes. The NULL value in C is the number zero. So, an array that ends in a null/zero value in C is essentially a sentinel-terminated array in Zig, where the sentinel value of the array is the number zero.\nTherefore, a string literal value in Zig is just a pointer to a null-terminated array of bytes (i.e., similar to a C string). But in Zig, a string literal value also embeds the length of the string, and also, the fact that they are “NULL terminated”, into the data type of the value itself.\n\n\n1.8.1.2 Slice\nYou can also access and use the arbitrary sequence of bytes that represent your string as a slice of u8 values. The majority of functions from the Zig standard library usually receive strings as inputs as slices of u8 values (slices were presented in Section 1.6).\nThus, you will see a lot of string values with a data type of []u8 or []const u8, depending if the object where this string is stored is marked as constant with const, or as variable with var. Now, because the string in this case is being interpreted as a slice, this slice is not necessarilly null-terminated, because now, the sentinel value is not mandatory. You can include the null/zero value in the slice if you want to, but there is no need to do it.\n\n// This is a string value being\n// interpreted as a slice.\nconst str: []const u8 = \"A string value\";\ntry stdout.print(\"{any}\\n\", .{@TypeOf(str)});\n\n[]const u8\n\n\n\n\n\n1.8.2 Iterating through the string\nIf you want to see the actual bytes that represents a string in Zig, you can use a for loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal value to the terminal. You do that by using a print() statement with the X formatting specifier, like you would normally do with the printf() function24 in C.\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example\";\n try stdout.print(\"Bytes that represents the string object: \", .{});\n for (string_object) |byte| {\n try stdout.print(\"{X} \", .{byte});\n }\n try stdout.print(\"\\n\", .{});\n}\n\nBytes that represents the string object: 54 68 69 \n 73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n\n\n\n\n1.8.3 A better look at the object type\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the @TypeOf() function. If we look at the type of the simple_array object below, you will find that this object is an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type i32 in Zig. That is what an object of type [4]i32 is.\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a constant pointer (hence the *const annotation) to an array of 16 elements (or 16 bytes). Each element is a single byte (more precisely, an unsigned 8 bit integer - u8), that is why we have the [16:0]u8 portion of the type below, and also, you can see that this is a null-terminated array, because of the zero value after the : character in the data type. In other words, the string literal value exposed below is 16 bytes long.\nNow, if we create an pointer to the simple_array object, then, we get a constant pointer to an array of 4 elements (*const [4]i32), which is very similar to the type of the string literal value. This demonstrates that a string literal value in Zig is already a pointer to a null-terminated array of bytes.\nFurthermore, if we take a look at the type of the string_obj object, you will see that it’s a slice object (hence the [] portion of the type) to a sequence of constant u8 values (hence the const u8 portion of the type).\n\nconst std = @import(\"std\");\npub fn main() !void {\n const simple_array = [_]i32{1, 2, 3, 4};\n const string_obj: []const u8 = \"A string object\";\n std.debug.print(\n \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n );\n std.debug.print(\n \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n );\n std.debug.print(\n \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n );\n std.debug.print(\n \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n );\n}\n\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n\n\n1.8.4 Byte vs unicode points\nIt’s important to point out that each byte in the array is not necessarily a single character. This fact arises from the difference between a single byte and a single unicode point.\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in the string. For example, the character “H” is stored in UTF-8 as the decimal number 72. This means that the number 72 is the unicode point for the character “H”. Each possible character that can appear in a UTF-8 encoded string have its own unicode point.\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point) 570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which is 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why, the unicode point 570 is actually stored inside the computer’s memory as the bytes C8 BA.\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"Ⱥ\";\n _ = try stdout.write(\n \"Bytes that represents the string object: \"\n );\n for (string_object) |char| {\n try stdout.print(\"{X} \", .{char});\n }\n}\n\nBytes that represents the string object: C8 BA \n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together to represent the number 570. That is why the relationship between bytes and unicode points is not always 1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds to a single unicode point.\nAll of this means that if you loop trough the elements of a string in Zig, you will be looping through the bytes that represents that string, and not through the characters of that string. In the Ⱥ example above, the for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a consequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because the number of bytes will be equal to the number of characters in that string. In other words, in this specific situation, the relationship between bytes and unicode points is 1 to 1.\nBut on the other side, if your string contains other types of letters… for example, you might be working with text data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent your UTF-8 string will likely be much higher than the number of characters in that string.\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the std.unicode.Utf8View struct to create an iterator that iterates through the unicode points of your string.\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in this string is represented by three bytes. But the for loop iterates four times, one iteration for each character/unicode point in this string:\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n var iterator = utf8.iterator();\n while (iterator.nextCodepointSlice()) |codepoint| {\n try stdout.print(\n \"got codepoint {}\\n\",\n .{std.fmt.fmtSliceHexUpper(codepoint)},\n );\n }\n}\n\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n\n\n1.8.5 Some useful functions for strings\nIn this section, I just want to quickly describe some functions from the Zig Standard Library that are very useful to use when working with strings. Most notably:\n\nstd.mem.eql(): to compare if two strings are equal.\nstd.mem.splitScalar(): to split a string into an array of substrings given a delimiter value.\nstd.mem.splitSequence(): to split a string into an array of substrings given a substring delimiter.\nstd.mem.startsWith(): to check if string starts with substring.\nstd.mem.endsWith(): to check if string ends with substring.\nstd.mem.trim(): to remove specific values from both start and end of the string.\nstd.mem.concat(): to concatenate strings together.\nstd.mem.count(): to count the occurrences of substring in the string.\nstd.mem.replace(): to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the mem module of the Zig Standard Library. This module contains multiple functions and methods that are useful to work with memory and sequences of bytes in general.\nThe eql() function is used to check if two arrays of data are equal or not. Since strings are just arbitrary arrays of bytes, we can use this function to compare two strings together. This function returns a boolean value indicating if the two strings are equal or not. The first argument of this function is the data type of the elements of the arrays that are being compared.\n\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n\ntrue\n\n\nThe splitScalar() and splitSequence() functions are useful to split a string into multiple fragments, like the split() method from Python strings. The difference between these two methods is that the splitScalar() uses a single character as the separator to split the string, while splitSequence() uses a sequence of characters (a.k.a. a substring) as the separator. There is a practical example of these functions later in the book.\nThe startsWith() and endsWith() functions are pretty straightforward. They return a boolean value indicating if the string (or, more precisely, if the array of data) begins (startsWith) or ends (endsWith) with the sequence provided.\n\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n\ntrue\n\n\nThe concat() function, as the name suggests, concatenate two or more strings together. Because the process of concatenating the strings involves allocating enough space to accomodate all the strings together, this concat() function receives an allocator object as input.\n\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n\nAs you can imagine, the replace() function is used to replace substrings in a string by another substring. This function works very similarly to the replace() method from Python strings. Therefore, you provide a substring to search, and every time that the replace() function finds this substring within the input string, it replaces this substring with the “replacement substring” that you provided as input.\nIn the example below, we are taking the input string “Hello”, and replacing all occurrences of the substring “el” inside this input string with “34”, and saving the results inside the buffer object. As result, the replace() function returns an usize value that indicates how many replacements were performed.\n\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n\nNew string: H34lo\nN of replacements: 1", + "text": "1.8 How strings work in Zig?\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (Chapter 4). But in order for us to build such a thing, we need to get a better understanding on how strings work in Zig. So let’s discuss this specific aspect of Zig.\nStrings in Zig work very similarly to strings in C, but they come with some extra caveats which adds more safety and efficiency to them. You could also say that Zig simply uses a more modern and safe approach to manage and use strings.\nA string in Zig is essentially an array of arbitrary bytes, or, more specifically, an array of u8 values. This very similar to a string in C, which is also interpreted as an array of arbitrary bytes, or, in the case of C, an array of char (which usually represents an unsigned 8-bit integer value in most systems) values.\nNow, because a string in Zig is an array, you automatically get the length of the string (i.e. the length of the array) embedded in the value itself. This makes all the difference! Because now, the Zig compiler can use the length value that is embedded in the string to check for “buffer overflow” or “wrong memory access” problems in your code.\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless. So getting this kind of safety is not automatic and much harder to do in C. For example, if you want to track the length of your string throughout your program in C, then, you first need to loop through the array of bytes that represents this string, and find the null element ('\\0') position to discover where exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\nTo do that, you would need to do something like this in C. In this example, the C string stored in the object array is 25 bytes long:\n\n#include <stdio.h>\nint main() {\n char* array = \"An example of string in C\";\n int index = 0;\n while (1) {\n if (array[index] == '\\0') {\n break;\n }\n index++;\n }\n printf(\"Number of elements in the array: %d\\n\", index);\n}\n\nNumber of elements in the array: 25\nYou don’t have this kind of work in Zig. Because the length of the string is always present and accessible in the string value itself. You can easily access the length of the string through the len attribute. As an example, the string_object object below is 43 bytes long:\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example of string literal in Zig\";\n try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n\n43\n\n\nAnother point is that Zig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every sequence of bytes you’re working with, but is not really Zig’s job to fix the encoding of your strings (you can use iconv22 for that). Today, most of the text in our modern world, especially on the web, should be UTF-8 encoded. So if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\nLet’s take for example the word “Hello”. In UTF-8, this sequence of characters (H, e, l, l, o) is represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this sequence is 0x48, 0x65, 0x6C, 0x6C, 0x6F. So if I take this sequence of hexadecimal values, and ask Zig to print this sequence of bytes as a sequence of characters (i.e., a string), then, the text “Hello” will be printed into the terminal:\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n try stdout.print(\"{s}\\n\", .{bytes});\n}\n\nHello\n\n\n\n1.8.1 Using a slice versus a sentinel-terminated array\nIn memory, all string values in Zig are always stored in the same way. They are simply stored as sequences/arrays of arbitrary bytes. But you can use and access this sequence of bytes in two different ways. You can access this sequence of bytes as:\n\na sentinel-terminated array of u8 values.\nor as a slice of u8 values.\n\n\n1.8.1.1 Sentinel-terminated arrays\nSentinel-terminated arrays in Zig are described in the Language Reference of Zig23. In summary a sentinel-terminated array is just a normal array, but, the difference is that they contain a “sentinel value” at the last index/element of the array. With a sentinel-terminated array you embed both the length of the array, and also, the sentinel value in the type itself of your object.\nFor example, if you write a string literal value in your code, and ask Zig to print the data type of this value, you usually get a data type in the format *const [n:0]u8. The n in the data type indicates the size of the string (that is the length of the array). The zero after the n: part of the data type is the sentinel value itself.\n\n// This is a string literal value:\n_ = \"A literal value\";\ntry stdout.print(\"{any}\\n\", .{@TypeOf(\"A literal value\")});\n\n*const [15:0]u8\n\n\nSo, with this data type *const [n:0]u8 you are essentially saying that you have an array of u8 values of length n, where, the element at the index corresponding to the length n in the array is the number zero. If you really think about this description, you will notice that this is just a fancy way to describe a string in C, which is a null-terminated array of bytes. The NULL value in C is the number zero. So, an array that ends in a null/zero value in C is essentially a sentinel-terminated array in Zig, where the sentinel value of the array is the number zero.\nTherefore, a string literal value in Zig is just a pointer to a null-terminated array of bytes (i.e., similar to a C string). But in Zig, a string literal value also embeds the length of the string, and also, the fact that they are “NULL terminated”, into the data type of the value itself.\n\n\n1.8.1.2 Slice\nYou can also access and use the arbitrary sequence of bytes that represent your string as a slice of u8 values. The majority of functions from the Zig standard library usually receive strings as inputs as slices of u8 values (slices were presented in Section 1.6).\nThus, you will see a lot of string values with a data type of []u8 or []const u8, depending if the object where this string is stored is marked as constant with const, or as variable with var. Now, because the string in this case is being interpreted as a slice, this slice is not necessarilly null-terminated, because now, the sentinel value is not mandatory. You can include the null/zero value in the slice if you want to, but there is no need to do it.\n\n// This is a string value being\n// interpreted as a slice.\nconst str: []const u8 = \"A string value\";\ntry stdout.print(\"{any}\\n\", .{@TypeOf(str)});\n\n[]const u8\n\n\n\n\n\n1.8.2 Iterating through the string\nIf you want to see the actual bytes that represents a string in Zig, you can use a for loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal value to the terminal. You do that by using a print() statement with the X formatting specifier, like you would normally do with the printf() function24 in C.\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"This is an example\";\n try stdout.print(\"Bytes that represents the string object: \", .{});\n for (string_object) |byte| {\n try stdout.print(\"{X} \", .{byte});\n }\n try stdout.print(\"\\n\", .{});\n}\n\nBytes that represents the string object: 54 68 69 \n 73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n\n\n\n\n1.8.3 A better look at the object type\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the @TypeOf() function. If we look at the type of the simple_array object below, you will find that this object is an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type i32 in Zig. That is what an object of type [4]i32 is.\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a constant pointer (hence the *const annotation) to an array of 16 elements (or 16 bytes). Each element is a single byte (more precisely, an unsigned 8 bit integer - u8), that is why we have the [16:0]u8 portion of the type below, and also, you can see that this is a null-terminated array, because of the zero value after the : character in the data type. In other words, the string literal value exposed below is 16 bytes long.\nNow, if we create an pointer to the simple_array object, then, we get a constant pointer to an array of 4 elements (*const [4]i32), which is very similar to the type of the string literal value. This demonstrates that a string literal value in Zig is already a pointer to a null-terminated array of bytes.\nFurthermore, if we take a look at the type of the string_obj object, you will see that it’s a slice object (hence the [] portion of the type) to a sequence of constant u8 values (hence the const u8 portion of the type).\n\nconst std = @import(\"std\");\npub fn main() !void {\n const simple_array = [_]i32{1, 2, 3, 4};\n const string_obj: []const u8 = \"A string object\";\n std.debug.print(\n \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n );\n std.debug.print(\n \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n );\n std.debug.print(\n \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n );\n std.debug.print(\n \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n );\n}\n\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n\n\n1.8.4 Byte vs unicode points\nIt’s important to point out that each byte in the array is not necessarily a single character. This fact arises from the difference between a single byte and a single unicode point.\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in the string. For example, the character “H” is stored in UTF-8 as the decimal number 72. This means that the number 72 is the unicode point for the character “H”. Each possible character that can appear in a UTF-8 encoded string have its own unicode point.\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point) 570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which is 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why, the unicode point 570 is actually stored inside the computer’s memory as the bytes C8 BA.\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n const string_object = \"Ⱥ\";\n _ = try stdout.write(\n \"Bytes that represents the string object: \"\n );\n for (string_object) |char| {\n try stdout.print(\"{X} \", .{char});\n }\n}\n\nBytes that represents the string object: C8 BA \n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together to represent the number 570. That is why the relationship between bytes and unicode points is not always 1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds to a single unicode point.\nAll of this means that if you loop through the elements of a string in Zig, you will be looping through the bytes that represents that string, and not through the characters of that string. In the Ⱥ example above, the for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a consequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because the number of bytes will be equal to the number of characters in that string. In other words, in this specific situation, the relationship between bytes and unicode points is 1 to 1.\nBut on the other side, if your string contains other types of letters… for example, you might be working with text data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent your UTF-8 string will likely be much higher than the number of characters in that string.\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the std.unicode.Utf8View struct to create an iterator that iterates through the unicode points of your string.\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in this string is represented by three bytes. But the for loop iterates four times, one iteration for each character/unicode point in this string:\n\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n var iterator = utf8.iterator();\n while (iterator.nextCodepointSlice()) |codepoint| {\n try stdout.print(\n \"got codepoint {}\\n\",\n .{std.fmt.fmtSliceHexUpper(codepoint)},\n );\n }\n}\n\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n\n\n1.8.5 Some useful functions for strings\nIn this section, I just want to quickly describe some functions from the Zig Standard Library that are very useful to use when working with strings. Most notably:\n\nstd.mem.eql(): to compare if two strings are equal.\nstd.mem.splitScalar(): to split a string into an array of substrings given a delimiter value.\nstd.mem.splitSequence(): to split a string into an array of substrings given a substring delimiter.\nstd.mem.startsWith(): to check if string starts with substring.\nstd.mem.endsWith(): to check if string ends with substring.\nstd.mem.trim(): to remove specific values from both start and end of the string.\nstd.mem.concat(): to concatenate strings together.\nstd.mem.count(): to count the occurrences of substring in the string.\nstd.mem.replace(): to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the mem module of the Zig Standard Library. This module contains multiple functions and methods that are useful to work with memory and sequences of bytes in general.\nThe eql() function is used to check if two arrays of data are equal or not. Since strings are just arbitrary arrays of bytes, we can use this function to compare two strings together. This function returns a boolean value indicating if the two strings are equal or not. The first argument of this function is the data type of the elements of the arrays that are being compared.\n\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n\ntrue\n\n\nThe splitScalar() and splitSequence() functions are useful to split a string into multiple fragments, like the split() method from Python strings. The difference between these two methods is that the splitScalar() uses a single character as the separator to split the string, while splitSequence() uses a sequence of characters (a.k.a. a substring) as the separator. There is a practical example of these functions later in the book.\nThe startsWith() and endsWith() functions are pretty straightforward. They return a boolean value indicating if the string (or, more precisely, if the array of data) begins (startsWith) or ends (endsWith) with the sequence provided.\n\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n\ntrue\n\n\nThe concat() function, as the name suggests, concatenate two or more strings together. Because the process of concatenating the strings involves allocating enough space to accomodate all the strings together, this concat() function receives an allocator object as input.\n\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n\nAs you can imagine, the replace() function is used to replace substrings in a string by another substring. This function works very similarly to the replace() method from Python strings. Therefore, you provide a substring to search, and every time that the replace() function finds this substring within the input string, it replaces this substring with the “replacement substring” that you provided as input.\nIn the example below, we are taking the input string “Hello”, and replacing all occurrences of the substring “el” inside this input string with “34”, and saving the results inside the buffer object. As result, the replace() function returns an usize value that indicates how many replacements were performed.\n\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n\nNew string: H34lo\nN of replacements: 1", "crumbs": [ "1  Introducing Zig" ] From a2c0dfe6ae54055532eb7ce01d62bcd3ad068e61 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 25 May 2025 19:25:09 -0300 Subject: [PATCH 131/151] Add flake file from bengfrost --- flake.nix | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 flake.nix diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..ef0ddc39 --- /dev/null +++ b/flake.nix @@ -0,0 +1,86 @@ +{ + description = "Dev shell for zig-book (HTML only) with Quarto, R, and user's Zig"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + + # R packages needed by the book (from dependencies.R) + # and common ones for Quarto R execution. + rPkgsList = with pkgs.rPackages; [ + quarto # The R package 'quarto' + bslib + downlit + xml2 # Needs libxml2 + gistr # Might need curl + knitr # Usually needed for R chunks in Quarto + rmarkdown # Often a dependency for knitr/Quarto R features + # Add other R packages if the book's R code uses more: + # e.g., readr, stringr, dplyr, fs, jsonlite, hms + readr + stringr + dplyr + fs + jsonlite + hms + ]; + + # R environment with the specified packages + R_env = pkgs.rWrapper.override { + packages = rPkgsList; + }; + + # Native libraries that might be runtime dependencies for R packages + # or tools used by Quarto (excluding PDF-specific ones). + nativeDeps = with pkgs; [ + libxml2 # For rPackages.xml2 + curl # For rPackages.gistr or other http functionality + ]; + + # REMOVED: localeDefinitions = pkgs.glibcLocalesUtf8; + # C.UTF-8 is generally available without needing full glibcLocales. + + in { + devShells.default = pkgs.mkShell { + # Packages made available in the shell environment + buildInputs = [ + R_env # Provides R and Rscript + pkgs.quarto # The Quarto CLI + # REMOVED: localeDefinitions + ] ++ nativeDeps; + + shellHook = '' + # QUARTO_R: Point Quarto to the Rscript from our Nix-provided R environment + unset QUARTO_R # Clear any pre-existing value + export QUARTO_R="${R_env}/bin/Rscript" + + # --- GENERAL LOCALE SETUP --- + # Set a universally available, UTF-8 compatible locale. + # This prevents locale errors and ensures basic Unicode handling + # without imposing a specific language or requiring extra locale packages. + export LANG="C.UTF-8" + export LC_ALL="C.UTF-8" + # REMOVED: export LOCALE_ARCHIVE="${localeDefinitions}/lib/locale/locale-archive" + # C.UTF-8 does not need LOCALE_ARCHIVE to be explicitly set from glibcLocalesUtf8. + + echo "--- Nix Shell Environment (HTML Only) ---" + echo "Locale set to C.UTF-8 for broad compatibility." # Added this line for clarity + echo "Zig is assumed to be available via \$PATH: $(which zig || echo 'Not found in PATH')" + echo "R environment configured." + echo " To check R's library paths: R -e '.libPaths()'" + echo " To list R packages: R -e 'installed.packages()[,1]'" + echo "QUARTO_R set to: $QUARTO_R" + # REMOVED: echo "LOCALE_ARCHIVE set to: $LOCALE_ARCHIVE" + echo "" + echo "To build HTML: quarto render" + echo "-----------------------------------------" + ''; + }; + }); +} \ No newline at end of file From 40bfb6d9db0fcd854ced279014a8b6508ecd0545 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 25 May 2025 19:25:36 -0300 Subject: [PATCH 132/151] Add readme from bengfrost --- README.md | 297 +++++++++++++++++++++++++++++------------------------- 1 file changed, 157 insertions(+), 140 deletions(-) diff --git a/README.md b/README.md index b8eb409c..567773ed 100644 --- a/README.md +++ b/README.md @@ -1,140 +1,157 @@ -# Introduction to Zig - - - -Hey! This is the official repository for the book "Introduction to Zig: a project-based book", written by Pedro Duarte Faria. -To know more about the book, checkout the [About this book](#about-this-book) section below. -You can read the current version of the book in your web browser: . - -The book is built using the publishing system [Quarto](https://quarto.org) -in conjunction with a little bit of R code (`zig_engine.R`), that is responsible for calling -the Zig compiler to compile and run the Zig code examples. - - -## Support the project! - -If you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy -of the book, either at Amazon, or at Leanpub: - -- Amazon: -- Leanpub: - -### Sending donations directly - -You can also donate some amount directly to the author of the project via: - -- PayPal Donation. -- Revolut. - -These are good ways to support directly the author of the project, which helps to foster -more contents like this, and it makes possible for the author to keep writing helpful tools and -materials for the community. - -### PayPal - -[![PayPal](https://img.shields.io/badge/PayPal-003087?logo=paypal&logoColor=fff)](https://www.paypal.com/donate/?business=D58J5LFEERC3N&no_recurring=0&item_name=These+donations+make+it+possible+for+me+to+continue+writing+new+and+useful+content+for+our+community%F0%9F%98%89+Thank+you%21%E2%9D%A4%EF%B8%8F%F0%9F%A5%B3¤cy_code=USD) - - -### Revolut - -You can send money via Swift Payment with the following bank and Swift details: - -``` -Recipient: Pedro Duarte Faria -BIC/SWIFT Code: REVOSGS2 -Account number: 6124512226 -Name and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore -Corresponding BIC: CHASGB2L -``` - -If you do have a Revolut account, you can scan the following QR code: - - - - - - -## About this book - -This is an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/), -which is a new general purpose, and low-level programming language for building optimal and robust software. - -Official repository of the book: . - -This book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small -and simple projects (in a similar style to the famous "Python Crash Course" book from Eric Matthes). -Some of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter. - -As you work through the book, you will learn: - -- The syntax of the language, and how it compares to C, C++ and Rust. -- Data structures, memory allocators, filesystem and I/O. -- Optionals as a new paradigm to handle nullability. -- How to test and debug a Zig application. -- Errors as values, and how to handle them. -- How to build C and Zig code with the build system that is embedded into the language. -- Zig interoperability with C. -- Parallelism with threads and SIMD. -- And more. - - - -## How to build the book - -This book depends on the three main pieces of software: - -1. The [Zig compiler](https://ziglang.org/download/), which is responsible for compiling most of the code examples exposed in the book. -2. The [R programming language](https://cran.r-project.org/), which provides some useful tools to collect the code examples exposed across the book, and send them to the zig compiler to be compiled and executed, and also, collect the results back to include them in the book. -3. The [Quarto publishing system](https://quarto.org/docs/get-started/), which provides the useful tools to compile the book, creating internal links, references, a chapters structure, the HTML content of the book, etc. - -So, you first need to install these three pieces of software in your current machine. -You can find instructions on how to install these pieces of software by clicking in the above hyperlinks. - -### Install R packages - -After you installed the three pieces of software listed above, you should run the `dependencies.R` R script, to install -some R packages that are used across the book. Just run the command below in your terminal, and you should be fine. - -OBS: If you are on Linux or MacOS, this command will probably take some time to run, because every single dependency gets built from source. -In Windows, this usually doesn't take that long because pre-built binaries are usually available. - -```bash -Rscript dependencies.R -``` - -### Render the book - -If you installed Quarto correctly in your computer -, you should be able to build the book by simply executing -the following command in the terminal. - -```bash -quarto render -``` - -### How the Zig compiler is found - -Some R code (`zig_engine.R`) is used to collect the Zig code examples -found across the book, and send them to the Zig compiler, so that they -can be compiled and executed. - -But in order to do that, this R code needs to find the Zig compiler installed -in your machine. This search process is done in two stages. -First, it uses the [`Sys.which()` function](https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/Sys.which) -to find the path to the Zig compiler in your computer, which is just a R interface to the `which` command line tool. - -This is a fast and easy approach, but, it doesn't work in all situations, specially if -your Zig compiler is not installed in a "standard location" in your computer. That is -why, a second strategy is applied, which is to search through the PATH environment variable. - -It gets the value of your PATH environment variable, and iterates through the directories listed -in this variable, trying to find the Zig compiler in one of them. This approach is much -slower than the first one, but is more garanteed to work. - - - -## License - -Copyright © 2024 Pedro Duarte Faria. This book is licensed by the CC-BY 4.0 Creative Commons Attribution 4.0 International Public License. - -Creative Commons License +# Introduction to Zig + + + +Hey! This is the official repository for the book "Introduction to Zig: a project-based book", written by Pedro Duarte Faria. +To know more about the book, checkout the [About this book](#about-this-book) section below. +You can read the current version of the book in your web browser: . + +This book is crafted using a modern, reproducible publishing stack, leveraging the power of: + +

      + Zig +   + Quarto +   + R +   + Knitr +   + Pandoc +   + Nix +

      + +The core book content is built using the [Quarto](https://quarto.org) publishing system +in conjunction with a little bit of R code (`zig_engine.R`), that is responsible for calling +the Zig compiler to compile and run the Zig code examples. + + +## Support the project! + +If you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy +of the book, either at Amazon, or at Leanpub: + +- Amazon: +- Leanpub: + +### Sending donations directly + +You can also donate some amount directly to the author of the project via: + +- PayPal Donation. +- Revolut. + +These are good ways to support directly the author of the project, which helps to foster +more contents like this, and it makes possible for the author to keep writing helpful tools and +materials for the community. + +### PayPal + +[![PayPal](https://img.shields.io/badge/PayPal-003087?style=flat&logo=paypal&logoColor=fff)](https://www.paypal.com/donate/?business=D58J5LFEERC3N&no_recurring=0&item_name=These+donations+make+it+possible+for+me+to+continue+writing+new+and+useful+content+for+our+community%F0%9F%98%89+Thank+you%21%E2%9D%A4%EF%B8%8F%F0%9F%A5%B3¤cy_code=USD) + + +### Revolut + +You can send money via Swift Payment with the following bank and Swift details: + +``` +Recipient: Pedro Duarte Faria +BIC/SWIFT Code: REVOSGS2 +Account number: 6124512226 +Name and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore +Corresponding BIC: CHASGB2L +``` + +If you do have a Revolut account, you can scan the following QR code: + + + + + + +## About this book + +This is an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/), +which is a new general purpose, and low-level programming language for building optimal and robust software. + +Official repository of the book: . + +This book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small +and simple projects (in a similar style to the famous "Python Crash Course" book from Eric Matthes). +Some of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter. + +As you work through the book, you will learn: + +- The syntax of the language, and how it compares to C, C++ and Rust. +- Data structures, memory allocators, filesystem and I/O. +- Optionals as a new paradigm to handle nullability. +- How to test and debug a Zig application. +- Errors as values, and how to handle them. +- How to build C and Zig code with the build system that is embedded into the language. +- Zig interoperability with C. +- Parallelism with threads and SIMD. +- And more. + + + +## How to build the book + +This book's creation relies on a powerful stack of open-source tools. Understanding these helps in appreciating the build process: + +1. **The Zig Zig compiler**: The star of the show, responsible for compiling most of the code examples exposed in the book. +2. **The R R programming language**: Provides useful tools (via Knitr Knitr) to collect code examples, send them to the Zig compiler, and retrieve results. +3. **The Quarto Quarto publishing system**: Orchestrates the book compilation, leveraging Pandoc Pandoc under the hood for creating internal links, references, chapter structure, and the final HTML content. +4. Optionally, the development environment can be managed using Nix Nix for reproducible builds (if a `flake.nix` is provided). + +So, you first need to install these three primary pieces of software (Zig, R, Quarto) in your current machine. +You can find instructions on how to install these pieces of software by clicking in the above hyperlinks. + +### Install R packages + +After you installed the three pieces of software listed above, you should run the `dependencies.R` R script, to install +some R packages that are used across the book. Just run the command below in your terminal, and you should be fine. + +OBS: If you are on Linux or MacOS, this command will probably take some time to run, because every single dependency gets built from source. +In Windows, this usually doesn't take that long because pre-built binaries are usually available. + +```bash +Rscript dependencies.R +``` + +### Render the book + +If you installed Quarto correctly in your computer +, you should be able to build the book by simply executing +the following command in the terminal. + +```bash +quarto render +``` + +### How the Zig compiler is found + +Some R code (`zig_engine.R`) is used to collect the Zig code examples +found across the book, and send them to the Zig compiler, so that they +can be compiled and executed. + +But in order to do that, this R code needs to find the Zig compiler installed +in your machine. This search process is done in two stages. +First, it uses the [`Sys.which()` function](https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/Sys.which) +to find the path to the Zig compiler in your computer, which is just a R interface to the `which` command line tool. + +This is a fast and easy approach, but, it doesn't work in all situations, specially if +your Zig compiler is not installed in a "standard location" in your computer. That is +why, a second strategy is applied, which is to search through the PATH environment variable. + +It gets the value of your PATH environment variable, and iterates through the directories listed +in this variable, trying to find the Zig compiler in one of them. This approach is much +slower than the first one, but is more garanteed to work. + + + +## License + +Copyright © 2024 Pedro Duarte Faria. This book is licensed by the CC-BY 4.0 Creative Commons Attribution 4.0 International Public License. + +Creative Commons License From e0b83165e1661b3d8d0a968e4e39cea7e506d4f0 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 25 May 2025 19:36:28 -0300 Subject: [PATCH 133/151] Remove expression --- flake.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index ef0ddc39..1d6ede3f 100644 --- a/flake.nix +++ b/flake.nix @@ -66,7 +66,6 @@ # without imposing a specific language or requiring extra locale packages. export LANG="C.UTF-8" export LC_ALL="C.UTF-8" - # REMOVED: export LOCALE_ARCHIVE="${localeDefinitions}/lib/locale/locale-archive" # C.UTF-8 does not need LOCALE_ARCHIVE to be explicitly set from glibcLocalesUtf8. echo "--- Nix Shell Environment (HTML Only) ---" @@ -83,4 +82,4 @@ ''; }; }); -} \ No newline at end of file +} From 0e551421af8080021a076f34448b1c042d50cabb Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Sun, 25 May 2025 20:11:05 -0300 Subject: [PATCH 134/151] Build the book with Nix to make sure that the environment is working --- README.md | 51 ++++++++++++--- docs/Chapters/01-base64.html | 63 ++++++++----------- docs/Chapters/01-memory.html | 47 ++++++-------- docs/Chapters/01-zig-weird.html | 47 ++++++-------- docs/Chapters/02-debugging.html | 47 ++++++-------- docs/Chapters/03-structs.html | 47 ++++++-------- docs/Chapters/03-unittests.html | 47 ++++++-------- docs/Chapters/04-http-server.html | 53 +++++++--------- docs/Chapters/05-pointers.html | 47 ++++++-------- docs/Chapters/07-build-system.html | 47 ++++++-------- docs/Chapters/09-data-structures.html | 57 +++++++---------- docs/Chapters/09-error-handling.html | 47 ++++++-------- docs/Chapters/10-stack-project.html | 49 ++++++--------- docs/Chapters/12-file-op.html | 53 +++++++--------- docs/Chapters/13-image-filter.html | 55 +++++++--------- docs/Chapters/14-threads.html | 55 +++++++--------- docs/Chapters/14-zig-c-interop.html | 47 ++++++-------- docs/Chapters/15-vectors.html | 47 ++++++-------- docs/index.html | 49 ++++++--------- docs/references.html | 49 ++++++--------- .../bootstrap/bootstrap-dark.min.css | 4 +- docs/site_libs/bootstrap/bootstrap.min.css | 4 +- docs/site_libs/quarto-html/quarto.js | 15 +---- docs/site_libs/quarto-nav/quarto-nav.js | 36 ----------- docs/site_libs/quarto-search/quarto-search.js | 6 +- flake.lock | 61 ++++++++++++++++++ 26 files changed, 482 insertions(+), 648 deletions(-) create mode 100644 flake.lock diff --git a/README.md b/README.md index 567773ed..8d934611 100644 --- a/README.md +++ b/README.md @@ -46,9 +46,11 @@ These are good ways to support directly the author of the project, which helps t more contents like this, and it makes possible for the author to keep writing helpful tools and materials for the community. + + ### PayPal -[![PayPal](https://img.shields.io/badge/PayPal-003087?style=flat&logo=paypal&logoColor=fff)](https://www.paypal.com/donate/?business=D58J5LFEERC3N&no_recurring=0&item_name=These+donations+make+it+possible+for+me+to+continue+writing+new+and+useful+content+for+our+community%F0%9F%98%89+Thank+you%21%E2%9D%A4%EF%B8%8F%F0%9F%A5%B3¤cy_code=USD) +[![PayPal](https://img.shields.io/badge/PayPal-003087?logo=paypal&logoColor=fff)](https://www.paypal.com/donate/?business=D58J5LFEERC3N&no_recurring=0&item_name=These+donations+make+it+possible+for+me+to+continue+writing+new+and+useful+content+for+our+community%F0%9F%98%89+Thank+you%21%E2%9D%A4%EF%B8%8F%F0%9F%A5%B3¤cy_code=USD) ### Revolut @@ -97,17 +99,25 @@ As you work through the book, you will learn: ## How to build the book -This book's creation relies on a powerful stack of open-source tools. Understanding these helps in appreciating the build process: +First of all, you need to care about the dependencies of the project. This book is built using the following pieces of software: + +1. The [Zig compiler](https://ziglang.org/download/), which is responsible for compiling most of the code examples exposed in the book. +2. The [R programming language](https://cran.r-project.org/), which provides some useful tools, specially `knitr` and `rmarkdown`, which are responsible for collecting the code examples exposed across the book, and sending them to the zig compiler to be compiled and executed, and also, collecting the results back to include them in the book. +3. The [Quarto publishing system](https://quarto.org/docs/get-started/), which is responsible for compiling the book, creating internal links, references, a chapters structure, the HTML content of the book, etc. + +So, installing these three pieces of software (Zig, R, Quarto) in your current machine is the first step to build the book. +There are two strategies that you can take here: + +1. You can install these three pieces of software manually (you can find instructions on how to install each piece by clicking in the above hyperlinks). +2. Or, you can use the Nix Flake declared in the `flake.nix` file to create a reproducible environment that already comes with these pieces installed. -1. **The Zig Zig compiler**: The star of the show, responsible for compiling most of the code examples exposed in the book. -2. **The R R programming language**: Provides useful tools (via Knitr Knitr) to collect code examples, send them to the Zig compiler, and retrieve results. -3. **The Quarto Quarto publishing system**: Orchestrates the book compilation, leveraging Pandoc Pandoc under the hood for creating internal links, references, chapter structure, and the final HTML content. -4. Optionally, the development environment can be managed using Nix Nix for reproducible builds (if a `flake.nix` is provided). -So, you first need to install these three primary pieces of software (Zig, R, Quarto) in your current machine. -You can find instructions on how to install these pieces of software by clicking in the above hyperlinks. +### Building the book manually -### Install R packages +If you decide to install the dependencies of the book manually, then, follow the "install instructions" that are present in the above hyperlinks, +and, after you installed the three pieces (Zig, R and Quarto), follow the next instructions specified here. + +#### Install R packages After you installed the three pieces of software listed above, you should run the `dependencies.R` R script, to install some R packages that are used across the book. Just run the command below in your terminal, and you should be fine. @@ -119,7 +129,7 @@ In Windows, this usually doesn't take that long because pre-built binaries are u Rscript dependencies.R ``` -### Render the book +#### Render the book If you installed Quarto correctly in your computer , you should be able to build the book by simply executing @@ -129,6 +139,27 @@ the following command in the terminal. quarto render ``` + + +### Building the book with Nix Flake + +If you choose to use the Nix Flake to create an environment that comes with the necessary dependencies, then, you need +to open a terminal, and run the `nix develop` command on the root of the project: + +```bash +nix develop +``` + +With this command, Onix will download the necessary packages and libraries, and then create a new bash session that points +to a new environment that contains these packages and libraries in it. Then, inside this new bash session that is created +by Nix, all you need to do is to run the `quarto render` command, which will kickstart Quarto, and make it build the book +for you: + +```bash +quarto render +``` + + ### How the Zig compiler is found Some R code (`zig_engine.R`) is used to collect the Zig code examples diff --git a/docs/Chapters/01-base64.html b/docs/Chapters/01-base64.html index 131de842..4fa946ca 100644 --- a/docs/Chapters/01-base64.html +++ b/docs/Chapters/01-base64.html @@ -2,12 +2,12 @@ - + -4  Project 1 - Building a base64 encoder/decoder – Introduction to Zig +Introduction to Zig - 4  Project 1 - Building a base64 encoder/decoder \n\n\n\n \n\n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Senior Data Engineer at [DSM-Firmenich](https://www.dsm-firmenich.com)[^dsm], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^dsm]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n\n- System version: Linux, 6.11.0-21-generic, 24.04.1-Ubuntu, x86_64.\n- Zig version: 0.14.0-dev.3046+08d661fcf.\n- Quarto version: 1.5.57.\n\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion), glystik (\\@glystik), Michael Lynch (\\@mtlynch), Yashank (\\@stickyburn)\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy\nof the book, either at Amazon, or at Leanpub:\n\n\n\n\n\n \n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Senior Data Engineer at [DSM-Firmenich](https://www.dsm-firmenich.com)[^dsm], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^dsm]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n- System version: Linux, 6.12.21-4-MANJARO, NA, x86_64.\n- Zig version: 0.15.0-dev.635+7dbd21bd5.\n- Quarto version: 1.4.554.\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion), glystik (\\@glystik), Michael Lynch (\\@mtlynch), Yashank (\\@stickyburn), _blf_ (\\@bengtfrost)\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/contributors.txt b/contributors.txt index 73ae3ac2..e6f0f030 100644 --- a/contributors.txt +++ b/contributors.txt @@ -25,3 +25,4 @@ Niklas Johansson,@Raphexion glystik,@glystik Michael Lynch,@mtlynch Yashank,@stickyburn +_blf_,@bengtfrost diff --git a/docs/index.html b/docs/index.html index 224b605c..be6ab3c0 100644 --- a/docs/index.html +++ b/docs/index.html @@ -426,9 +426,9 @@

      License

      Book compilation metadata

      This book was compiled using the following versions of Zig and Quarto:

        -
      • System version: Linux, 6.11.0-21-generic, 24.04.1-Ubuntu, x86_64.
      • -
      • Zig version: 0.14.0-dev.3046+08d661fcf.
      • -
      • Quarto version: 1.5.57.
      • +
      • System version: Linux, 6.12.21-4-MANJARO, NA, x86_64.
      • +
      • Zig version: 0.15.0-dev.635+7dbd21bd5.
      • +
      • Quarto version: 1.4.554.

    @@ -454,7 +454,7 @@

    Acknowledgments

    This book is also a product of many conversations and exchanges that we had with different people from the Zig community. I (Pedro Duarte Faria) am incredibly grateful for these conversations, and also, for some direct contributions that we had. Below we have a list of the people involved (name of the person with their usename in GitHub):

    -

    Calin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m), Alexander (@alexwheezy), Maarten Coopens (@maarteNNNN), Niklas Johansson (@Raphexion), glystik (@glystik), Michael Lynch (@mtlynch), Yashank (@stickyburn)

    +

    Calin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m), Alexander (@alexwheezy), Maarten Coopens (@maarteNNNN), Niklas Johansson (@Raphexion), glystik (@glystik), Michael Lynch (@mtlynch), Yashank (@stickyburn), blf (@bengtfrost)

    diff --git a/docs/search.json b/docs/search.json index fbcaa66e..9fb32b5e 100644 --- a/docs/search.json +++ b/docs/search.json @@ -54,7 +54,7 @@ "href": "index.html#book-compilation-metadata", "title": "Introduction to Zig", "section": "Book compilation metadata", - "text": "Book compilation metadata\nThis book was compiled using the following versions of Zig and Quarto:\n\nSystem version: Linux, 6.11.0-21-generic, 24.04.1-Ubuntu, x86_64.\nZig version: 0.14.0-dev.3046+08d661fcf.\nQuarto version: 1.5.57.", + "text": "Book compilation metadata\nThis book was compiled using the following versions of Zig and Quarto:\n\nSystem version: Linux, 6.12.21-4-MANJARO, NA, x86_64.\nZig version: 0.15.0-dev.635+7dbd21bd5.\nQuarto version: 1.4.554.", "crumbs": [ "Welcome" ] @@ -84,7 +84,7 @@ "href": "index.html#acknowledgments", "title": "Introduction to Zig", "section": "Acknowledgments", - "text": "Acknowledgments\nThis book is also a product of many conversations and exchanges that we had with different people from the Zig community. I (Pedro Duarte Faria) am incredibly grateful for these conversations, and also, for some direct contributions that we had. Below we have a list of the people involved (name of the person with their usename in GitHub):\nCalin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m), Alexander (@alexwheezy), Maarten Coopens (@maarteNNNN), Niklas Johansson (@Raphexion), glystik (@glystik), Michael Lynch (@mtlynch), Yashank (@stickyburn)", + "text": "Acknowledgments\nThis book is also a product of many conversations and exchanges that we had with different people from the Zig community. I (Pedro Duarte Faria) am incredibly grateful for these conversations, and also, for some direct contributions that we had. Below we have a list of the people involved (name of the person with their usename in GitHub):\nCalin Martinconi (@martinconic), Steffen Roller (@sroller), Chris Boesch (@chrboesch), Lv Sihan (@Pokryton), saurabh sharma. (@esskayesss), slackline (@slackline), Markus Kurz (@kurz-m), Rubin Simons (@rubin55), Chris Boesch (@chrboesch), Bruno (@PoorlyDefinedBehaviour), Ilia Choly (@icholy), Korri Katti (@KorryKatti), Vedang Manerikar (@vedang), Tommaso Ricci (@Zorgatone), Primo Sabatini (@primos63), Santiago Fernandez (@santif), Hamza Wahed (@HamzaWahed), mwilbur (@mwilbur), Dima Budaragin (@dbud), Jorge Jímenez (@jorge-j1m), Alexander (@alexwheezy), Maarten Coopens (@maarteNNNN), Niklas Johansson (@Raphexion), glystik (@glystik), Michael Lynch (@mtlynch), Yashank (@stickyburn), blf (@bengtfrost)", "crumbs": [ "Welcome" ] diff --git a/flake.lock b/flake.lock index 2468070f..b12776a6 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,21 @@ { "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" @@ -18,6 +34,24 @@ "type": "github" } }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1705309234, + "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1735563628, @@ -34,10 +68,27 @@ "type": "github" } }, + "nixpkgs_2": { + "locked": { + "lastModified": 1708161998, + "narHash": "sha256-6KnemmUorCvlcAvGziFosAVkrlWZGIc6UNT9GUYr0jQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "84d981bae8b5e783b3b548de505b22880559515f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs", + "zig": "zig" } }, "systems": { @@ -54,6 +105,41 @@ "repo": "default", "type": "github" } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "zig": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1748175105, + "narHash": "sha256-IcT4UOp+K7lDjYuSzKGMzrv1dp1znK3YS7UPKkLDvQ0=", + "owner": "mitchellh", + "repo": "zig-overlay", + "rev": "d665bd0897e491db11e24a12213c7f2a3ded5c08", + "type": "github" + }, + "original": { + "owner": "mitchellh", + "repo": "zig-overlay", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 1d6ede3f..eff8a318 100644 --- a/flake.nix +++ b/flake.nix @@ -4,9 +4,10 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; flake-utils.url = "github:numtide/flake-utils"; + zig.url = "github:mitchellh/zig-overlay"; }; - outputs = { self, nixpkgs, flake-utils, ... }: + outputs = { self, nixpkgs, flake-utils, zig, ... } @ inputs: flake-utils.lib.eachDefaultSystem (system: let pkgs = nixpkgs.legacyPackages.${system}; @@ -52,13 +53,14 @@ buildInputs = [ R_env # Provides R and Rscript pkgs.quarto # The Quarto CLI + zig.packages.${system}.master # REMOVED: localeDefinitions ] ++ nativeDeps; shellHook = '' # QUARTO_R: Point Quarto to the Rscript from our Nix-provided R environment unset QUARTO_R # Clear any pre-existing value - export QUARTO_R="${R_env}/bin/Rscript" + export QUARTO_R=$(which Rscript) # --- GENERAL LOCALE SETUP --- # Set a universally available, UTF-8 compatible locale. @@ -66,14 +68,16 @@ # without imposing a specific language or requiring extra locale packages. export LANG="C.UTF-8" export LC_ALL="C.UTF-8" - # C.UTF-8 does not need LOCALE_ARCHIVE to be explicitly set from glibcLocalesUtf8. + echo "--- Nix Shell Environment (HTML Only) ---" echo "Locale set to C.UTF-8 for broad compatibility." # Added this line for clarity - echo "Zig is assumed to be available via \$PATH: $(which zig || echo 'Not found in PATH')" + echo "Zig is assumed to be available via \$PATH: $(which zig || echo 'Not found zig in PATH')" echo "R environment configured." echo " To check R's library paths: R -e '.libPaths()'" echo " To list R packages: R -e 'installed.packages()[,1]'" + echo "R environment is set to: $R_env" + echo "Rscript is at: $(which Rscript || echo 'Not found Rscript')" echo "QUARTO_R set to: $QUARTO_R" # REMOVED: echo "LOCALE_ARCHIVE set to: $LOCALE_ARCHIVE" echo "" From 33b6810dcd630fcec9d39a2db96a179caf884023 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Mon, 26 May 2025 19:23:07 -0300 Subject: [PATCH 137/151] Fix singly linked list examples --- Chapters/09-data-structures.qmd | 167 ++++++++++++++++++++------------ 1 file changed, 103 insertions(+), 64 deletions(-) diff --git a/Chapters/09-data-structures.qmd b/Chapters/09-data-structures.qmd index add3878e..044958c3 100644 --- a/Chapters/09-data-structures.qmd +++ b/Chapters/09-data-structures.qmd @@ -706,8 +706,11 @@ var ages = std.StringArrayHashMap(u8).init(allocator); ## Linked lists The Zig Standard Library provides an implementation for both singly and doubly linked lists. -A linked list is a linear data structure that looks like a chain, or, a rope. -The main advantage of this data structure is that you normally have very fast +More specifically, through the structs `SinglyLinkedList` and `DoublyLinkedList`, for "singly linked lists" and "doubly linked lists", +respectively. + +In case you are not familiar with these data structures, a linked list is a linear data structure that looks +like a chain, or, a rope. The main advantage of this data structure is that you normally have very fast insertion and deletion operations. But, as a disadvantage, iterating through this data structure is usually not so fast as iterating through an array. @@ -740,88 +743,124 @@ normally have only the `next` pointer in them. ![A diagram of a doubly linked list.](./../Figures/doubly-linked-list.png){#fig-linked-list2} -Linked lists are available in Zig through the functions `SinglyLinkedList()` and -`DoublyLinkedList()`, for "singly linked lists" and "doubly linked lists", respectively. These functions are -actually generic functions, which we are going to talk more about in @sec-generic-fun. -For now, just understand that, in order to create a linked list object, -we begin by providing a data type to these functions. This data type defines -the type of data that each node in this linked list will store. In the example below, -we are creating a singly linked list of `u32` values. -So each node in this linked list will store a `u32` value. +### Recent change in the API -Both the `SinglyLinkedList()` and `DoublyLinkedList()` functions returns a type, -i.e., a struct definition, as output. Therefore, the object `Lu32` is actually -a struct definition. It defines the type "singly linked list of `u32` values". +On previous versions of Zig, the `SinglyLinkedList` and `DoublyLinkedList` structures were initially implemented as "generics data structures". +Meaning that, you would use a generic function to create a singly (or doubly) linked list that could store +the specific data type that you wanted to use. In other words, you just tell Zig which data type that you are +going to store inside the nodes of the linked list, and Zig creates the structure with the appropriate attributes +for you. We will learn more about generics at @sec-generics, and also, how we can create a "generic data structure" +at @sec-generics-struct. -Now that we have the definition of the struct, we need to instantiate a `Lu32` object. -We normally instantiate struct objects in Zig by using an `init()` method. -But in this case, we are instantiating the struct directly, by using an empty -`struct` literal, in the expression `Lu32{}`. +However, on most recent versions of Zig, the structs `SinglyLinkedList` and `DoublyLinkedList` were altered to use a +"less generic API". This specific change was introduced on April 3, 2025. Therefore, check if your Zig version is one released after this +date. Just have in mind that if you don't have a very recent version of the Zig compiler, +you might have problems while trying to compile the next examples. -In this example, we first create multiple node objects, and after we create them, -we start to insert and connect these nodes to build the linked list, using the -`prepend()` and `insertAfter()` methods. Notice that the `prepend()` method -is a method from the linked list object, while the `insertAfter()` is a method -present in the node objects. -In essence, the `prepend()` method inserts a node at the beginning of the linked -list. In other words, the node that you provide to this method, becomes the new -"head node" of the linked list. It becomes the first node in the list (see @fig-linked-list). -On the other side, the `insertAfter()` method is used to basically connect two nodes together. -When you provide a node to this method, it creates a pointer to this input node, -and stores this pointer in the `next` attribute of the current node, from which the method was called from. +### How to use a singly linked list -Because doubly linked lists have both a `next` and a `prev` attributes in each node -(as described in @fig-linked-list2), a node object created from -a `DoublyLinkedList` object have both an `insertBefore()` (for `prev`) -and an `insertAfter()` (for `next`) methods available. +For example, consider that you are creating a singly linked list that is going to store `u32` values. +Given this scenario, the first thing that we need to do, is to create a "node type" that is capable +of storing a `u32` value. The `NodeU32` type exposed below demonstrates such "node type". -Thus, if we have used a doubly linked list, we can use the `insertBefore()` method -to store the pointer to the input node in the `prev` attribute. This would put the input -node as the "previous node", or, the node before the current node. In contrast, the `insertAfter()` method -puts the pointer created to the input node in the `next` attribute of the current node, -and as result, the input node becomes the "next node" of the current node. +Notice that the data type associated with the member named `data` is the most important part of this +custom "node type". It determines the data type that is going to be stored in each node. -Since we are using a singly linked list in this example, we have only the `insertAfter()` method -available in the node objects that we create from our `Lu32` type. +```{zig} +#| eval: false +const std = @import("std"); +const SinglyLinkedList = ; +const NodeU32 = struct { + data: u32, + node: std.SinglyLinkedList.Node = .{}, +}; +``` + +After we created our custom "node type" that can store the specific data type that we +want, we can just create a new and empty singly linked list, which will store our nodes. +To do that, we just create a new object with the type `SinglyLinkedList`, like this: ```{zig} -#| auto_main: false -const std = @import("std"); -const SinglyLinkedList = std.SinglyLinkedList; -const Lu32 = SinglyLinkedList(u32); +#| eval: false +var list: std.SinglyLinkedList = .{}; +``` -pub fn main() !void { - var list = Lu32{}; - var one = Lu32.Node{ .data = 1 }; - var two = Lu32.Node{ .data = 2 }; - var three = Lu32.Node{ .data = 3 }; - var four = Lu32.Node{ .data = 4 }; - var five = Lu32.Node{ .data = 5 }; - - list.prepend(&two); // {2} - two.insertAfter(&five); // {2, 5} - list.prepend(&one); // {1, 2, 5} - two.insertAfter(&three); // {1, 2, 3, 5} - three.insertAfter(&four); // {1, 2, 3, 4, 5} -} +Now, we have our linked list... But how can we insert nodes in it? Well, first of all, +we need to create our nodes. So let's focus on that first. The snippet exposed below demonstrates +how we could use our `NodeU32` struct to create such nodes. + +Notice in this snippet that we are just setting the `data` member of the struct for now. +We don't need to connect these nodes together in this first instance. This is why we ignore +the `node` member at first. But we are going to connect these nodes in a future point of the code, which is +why these objects are marked as "variable objects", so that we can alter them in the future. + +```{zig} +#| eval: false +var one: NodeU32 = .{ .data = 1 }; +var two: NodeU32 = .{ .data = 2 }; +var three: NodeU32 = .{ .data = 3 }; +var five: NodeU32 = .{ .data = 5 }; ``` +Now that we have both the linked list and also the nodes created, we can start to connect them together. +You can use the `prepend()` method from the linked list object to insert the first node in the list, which +is the "head" of the linked list. As the name suggests, this specific method prepends the input node to the linked list, +or, in other words, it transforms the input node into the first node of the list. + +After we added the "head node" of the list, we can start to add the "next nodes" in the list by using the `insertAfter()` method +from the `SinglyLinkedList.Node` type, which, in our case here, is accessible through the `node` member of our +`NodeU32` type. Thus, we can start to create the connections between the nodes by calling this method from the node objects +that are present in the list. Like in this example below: -There are other methods available from the linked list object, depending if this object is -a singly linked list or a doubly linked list, that might be very useful for you. You can find a +```{zig} +#| eval: false +list.prepend(&two.node); // {2} +two.node.insertAfter(&five.node); // {2, 5} +two.node.insertAfter(&three.node); // {2, 3, 5} +``` + +You can also call the `prepend()` method again to add new nodes to the beginning of the linked list, which +means, effectively, changing the "head node" of the list, like this: + +```{zig} +#| eval: false +list.prepend(&one.node); // {1, 2, 3, 5} +``` + + +There are other methods available from the singly linked list object that you might be interested. You can find a summary of them in the bullet points below: - `remove()` to remove a specific node from the linked list. -- if singly linked list, `len()` to count how many nodes there is in the linked list. -- if doubly linked list, checkout the `len` attribute to see how many nodes there is in the linked list. -- if singly linked list, `popFirst()` to remove the first node (i.e., the "head") from the linked list. -- if doubly linked list, `pop()` and `popFirst()` to remove the last and first nodes from the linked list, respectively. -- if doubly linked list, `append()` to add a new node to end of the linked list (i.e., inverse of `prepend()`). +- `len()` to count how many nodes there is in the linked list. +- `popFirst()` to remove the first node (i.e., the "head") from the linked list. + +So, that is how singly linked lists work in Zig in a nutshell. To sum up what we have exposed here, +this is all the source code that was exposed in this section inside the single cell: + +```{zig} +#| build_type: "run" +#| auto_main: true +const NodeU32 = struct { + data: u32, + node: std.SinglyLinkedList.Node = .{}, +}; +var list: std.SinglyLinkedList = .{}; +var one: NodeU32 = .{ .data = 1 }; +var two: NodeU32 = .{ .data = 2 }; +var three: NodeU32 = .{ .data = 3 }; +var five: NodeU32 = .{ .data = 5 }; + +list.prepend(&two.node); // {2} +two.node.insertAfter(&five.node); // {2, 5} +two.node.insertAfter(&three.node); // {2, 3, 5} +list.prepend(&one.node); // {1, 2, 3, 5} +``` ## Multi array structure From 3257bf035856aa6241ef805ae888a240ee3acc71 Mon Sep 17 00:00:00 2001 From: pedropark99 Date: Mon, 26 May 2025 19:31:33 -0300 Subject: [PATCH 138/151] Fix example --- Chapters/09-data-structures.qmd | 20 +- .../execute-results/html.json | 8 +- docs/Chapters/09-data-structures.html | 178 +++++++++++------- docs/index.html | 4 +- docs/search.json | 2 +- 5 files changed, 122 insertions(+), 90 deletions(-) diff --git a/Chapters/09-data-structures.qmd b/Chapters/09-data-structures.qmd index 044958c3..338b867e 100644 --- a/Chapters/09-data-structures.qmd +++ b/Chapters/09-data-structures.qmd @@ -706,8 +706,7 @@ var ages = std.StringArrayHashMap(u8).init(allocator); ## Linked lists The Zig Standard Library provides an implementation for both singly and doubly linked lists. -More specifically, through the structs `SinglyLinkedList` and `DoublyLinkedList`, for "singly linked lists" and "doubly linked lists", -respectively. +More specifically, through the structs `SinglyLinkedList` and `DoublyLinkedList`. In case you are not familiar with these data structures, a linked list is a linear data structure that looks like a chain, or, a rope. The main advantage of this data structure is that you normally have very fast @@ -746,17 +745,15 @@ normally have only the `next` pointer in them. ### Recent change in the API -On previous versions of Zig, the `SinglyLinkedList` and `DoublyLinkedList` structures were initially implemented as "generics data structures". +On previous versions of Zig, the `SinglyLinkedList` and `DoublyLinkedList` structs were initially implemented as "generics data structures". Meaning that, you would use a generic function to create a singly (or doubly) linked list that could store -the specific data type that you wanted to use. In other words, you just tell Zig which data type that you are -going to store inside the nodes of the linked list, and Zig creates the structure with the appropriate attributes -for you. We will learn more about generics at @sec-generics, and also, how we can create a "generic data structure" -at @sec-generics-struct. +the specific data type that you wanted to use. We will learn more about generics at @sec-generics, and also, +how we can create a "generic data structure" at @sec-generic-struct. -However, on most recent versions of Zig, the structs `SinglyLinkedList` and `DoublyLinkedList` were altered to use a +However, on the latest versions of Zig, the structs `SinglyLinkedList` and `DoublyLinkedList` were altered to use a "less generic API". This specific change was introduced on April 3, 2025. Therefore, check if your Zig version is one released after this date. Just have in mind that if you don't have a very recent version of the Zig compiler, -you might have problems while trying to compile the next examples. +you might have problems while trying to compile the next examples exposed here. @@ -772,7 +769,6 @@ custom "node type". It determines the data type that is going to be stored in ea ```{zig} #| eval: false const std = @import("std"); -const SinglyLinkedList = ; const NodeU32 = struct { data: u32, @@ -839,7 +835,7 @@ summary of them in the bullet points below: - `len()` to count how many nodes there is in the linked list. - `popFirst()` to remove the first node (i.e., the "head") from the linked list. -So, that is how singly linked lists work in Zig in a nutshell. To sum up what we have exposed here, +So, that is how singly linked lists work in Zig in a nutshell. To sum up, this is all the source code that was exposed in this section inside the single cell: ```{zig} @@ -860,6 +856,8 @@ list.prepend(&two.node); // {2} two.node.insertAfter(&five.node); // {2, 5} two.node.insertAfter(&three.node); // {2, 3, 5} list.prepend(&one.node); // {1, 2, 3, 5} + +try stdout.print("Number of nodes: {}", .{list.len()}); ``` diff --git a/_freeze/Chapters/09-data-structures/execute-results/html.json b/_freeze/Chapters/09-data-structures/execute-results/html.json index 3bbf890a..d48aede7 100644 --- a/_freeze/Chapters/09-data-structures/execute-results/html.json +++ b/_freeze/Chapters/09-data-structures/execute-results/html.json @@ -1,11 +1,9 @@ { - "hash": "ec46a394836e999ef1cdcb2a2a2407a2", + "hash": "b402250b83835ffcd41be6613f43fc78", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Data Structures\n\nIn this chapter, I want to present the most common Data Structures that are available from\nthe Zig Standard Library, especially `ArrayList` and also `HashMap`. These are generic Data Structures\nthat you can use to store and control any type of data that is produced by your application.\n\n## Dynamic Arrays {#sec-dynamic-array}\n\nIn high level languages, arrays are usually dynamic. They can easily grow\nin size when they have to, and you don't need to worry about it.\nIn contrast, arrays in low level languages are usually static by default.\nThis is the reality of C, C++, Rust and also Zig. Static arrays were presented at\n@sec-arrays, but in this section, we are going to talk about dynamic arrays in Zig.\n\nDynamic arrays are simply arrays that can grow in size during the runtime\nof your program. Most low level languages have some implementation of\na dynamic array in their standard library. C++ have `std::vector`, Rust have `Vec`,\nand Zig have `std.ArrayList`.\n\nThe `std.ArrayList` struct provides a contiguous and growable array for you.\nIt works like any other dynamic array, it allocates a contiguous block of memory, and when this block have no space left,\n`ArrayList` allocates another contiguous and bigger block of memory, copies the\nelements to this new location, and erases (or frees) the previous block of memory.\n\n\n### Capacity vs Length\n\nWhen we talk about dynamic arrays, we usually have two similar concepts that\nare very essential to how a dynamic array works behind the hood.\nThese concepts are *capacity* and *length*. In some contexts, especially\nin C++, *length* is also called of *size*.\n\nAlthough they look similar, these concepts represent different things\nin the context of a dynamic array. *Capacity* is the number of items (or elements)\nthat your dynamic array can currently hold without the need to allocate more memory.\n\nIn contrast, the *length* refers to how many elements in the array\nare currently being used, or, in other words, how many elements in this array\nthat you have assigned a value to. Every dynamic array works around\na block of allocated memory, which represents an array with total capacity for $n$ elements.\nHowever, only a portion of these $n$ elements are being used most of the time. This portion\nof $n$ is the *length* of the array. So every time you append a new value\nto the array, you are incrementing its *length* by one.\n\nThis means that a dynamic array usually works with an extra margin, or an extra space\nthat is currently empty, but waiting and ready to be used. This \"extra space\"\nis essentially the difference between *capacity* and *length*. *Capacity* represents\nthe total number of elements that the array can hold without the need to re-allocate\nor re-expand the array, while the *length* represents how much of this capacity\nis currently being used to hold/store values.\n\n@fig-capacity-length presents this idea visually. Notice that, at first,\nthe capacity of the array is greater than the length of the array.\nSo, the dynamic array have extra space that is currently empty, but it\nis ready to receive a value to be stored.\n\n![Difference between capacity and length in a dynamic array](./../Figures/dynamic-array.png){#fig-capacity-length}\n\nWe can also see in @fig-capacity-length that, when *length* and *capacity* are equal, it means that the array have no space left.\nWe have reached the ceiling of our capacity, and because of that, if we want to store more values\nin this array, we need to expand it. We need to get a bigger space that can hold more values\nthan what we currently have.\n\nA dynamic array works by expanding the underlying array, whenever the *length* becomes equal\nto the *capacity* of the array. It basically allocates a new contiguous block of memory that is bigger\nthan the previous one, then, it copies all values that are currently being stored to this new\nlocation (i.e., this new block of memory), then, it frees the previous block of\nmemory. At the end of this process, the new underlying array have a bigger *capacity*, and, therefore,\nthe *length* becomes, once again, smaller than the *capacity* of the array.\n\nThis is the cycle of a dynamic array. Notice that, throughout this cycle, the *capacity* is always\neither equal to or higher than the *length* of the array. If you have an `ArrayList` object (let's suppose\nyou named it `buffer`), you can check the current capacity of your array by accessing the `capacity`\nattribute of your `ArrayList` object, while the current *length* of it is available at the `items.len`\nattribute.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// Check capacity\nbuffer.capacity;\n// Check length\nbuffer.items.len;\n```\n:::\n\n\n\n\n\n### Creating an `ArrayList` object\n\nIn order to use `ArrayList`, you must provide an allocator object to it.\nRemember, Zig does not have a default memory allocator. And as I described in @sec-allocators, all memory\nallocations must be done by an allocator object that you define, that\nyou have control over. In our example here, I'm going to use\na general purpose allocator, but you can use any other allocator\nof your preference.\n\nWhen you initialize an `ArrayList` object, you must provide the data type of the elements of\nthe array. In other words, this defines the type of data that this array (or container) will\nstore. Therefore, if I provide the `u8` type to it, then, I will create a dynamic\narray of `u8` values. However, if I provide a struct that I have defined instead, like the struct `User`\nfrom @sec-structs-and-oop, then, a dynamic array of `User` values\nwill be created. In the example below, with the expression `ArrayList(u8)` we\nare creating a dynamic array of `u8` values.\n\nAfter you provide the data type of the elements of the array, you can initialize\nan `ArrayList` object by either using the `init()` or the `initCapacity()` methods.\nThe former method receives only the allocator object\nas input, while the latter method receives both the allocator object and a capacity number as inputs.\nWith the latter method, you not only initialize the struct, but you\nalso set the starting capacity of the allocated array.\n\nUsing the `initCapacity()` method is the preferred way to initialize your dynamic array.\nBecause reallocations, or, in other words, the process of expanding the capacity of the array,\nis always a high cost operation. You should take any possible opportunity to avoid reallocations in\nyour array. If you know how much space your array needs to occupy at the beginning,\nyou should always use `initCapacity()` to create your dynamic array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 100);\ndefer buffer.deinit();\n```\n:::\n\n\n\n\n\nIn the example above, the `buffer` object starts as an array of 100 elements. If this\n`buffer` object needs to create more space to accomodate more elements during the runtime of your program, the `ArrayList`\ninternals will perform the necessary actions for you automatically.\nAlso notice the `deinit()` method being used to destroy the `buffer` object at the\nend of the current scope, by freeing all the memory that was allocated for the dynamic\narray stored in this `buffer` object.\n\n\n### Adding new elements to the array\n\nNow that we have created our dynamic array, we can start to use it. You can append (a.k.a \"add\")\nnew values to this array by using the `append()` method. This method works the same way\nas the `append()` method from a Python list, or, the `emplace_back()` method from `std::vector` of C++.\nYou provide a single value to this method, and the method appends this value to the array.\n\nYou can also use the `appendSlice()` method to append multiple values at once. You provide\na slice (slices were described in @sec-arrays) to this method, and the method adds all values present\nin this slice to your dynamic array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry buffer.append('H');\ntry buffer.append('e');\ntry buffer.append('l');\ntry buffer.append('l');\ntry buffer.append('o');\ntry buffer.appendSlice(\" World!\");\n```\n:::\n\n\n\n\n### Removing elements from the array {#sec-dynamic-array-remove}\n\nYou can use the `pop()` method to \"pop\" or remove\nthe last element in the array. It's worth noting that this method\ndo not change the capacity of the array. It just deletes or erases\nthe last value stored in the array.\n\nAlso, this method returns as result the value that got deleted. That is, you can\nuse this method to both get the last value in the array, and also, remove\nit from the array. It's a \"get and remove value\" type of method.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exclamation_mark = buffer.pop();\n```\n:::\n\n\n\n\nNow, if you want to remove specific elements from specific positions\nof your array, you can use the `orderedRemove()` method from your\n`ArrayList` object. With this method, you can provide an index as input,\nthen, the method will delete the value that is at this index in the array.\nYou are effectively reducing the *length* of the array everytime you execute\nan `orderedRemove()` operation.\n\nIn the example below, we first create an `ArrayList` object, and we fill it\nwith numbers. Then, we use `orderedRemove()` to remove the value at\nindex 3 in the array, two consecutive times.\n\nAlso, notice that we are assigning the result of `orderedRemove()` to the\nunderscore character. So we are discarding the result value of this method.\nThe `orderedRemove()` method returns the value that got deleted, in a similar\nstyle to the `pop()` method.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 100);\ndefer buffer.deinit();\n\nfor (0..10) |i| {\n const index: u8 = @intCast(i);\n try buffer.append(index);\n}\n\nstd.debug.print(\n \"{any}\\n\", .{buffer.items}\n);\n_ = buffer.orderedRemove(3);\n_ = buffer.orderedRemove(3);\n\nstd.debug.print(\"{any}\\n\", .{buffer.items});\nstd.debug.print(\"{any}\\n\", .{buffer.items.len});\n```\n:::\n\n\n\n\n```\n{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }\n{ 0, 1, 2, 5, 6, 7, 8, 9 }\n8\n```\n\nOne key characteristic about `orderedRemove()` is that it preserves the order\nof the values in the array. So, it deletes the value that you asked it to\nremove, but it also makes sure that the order of the values that remain in the array\nstay the same as before.\n\nNow, if you don't care about the order of the values, for example, maybe you want to treat\nyour dynamic array as a set of values, like the `std::unordered_set`\nstructure from C++, you can use the `swapRemove()` method instead. This method\nworks similarly to the `orderedRemove()` method. You give an index to this\nmethod, then, it deletes the value that is at this index in the array.\nBut this method does not preserve the original order of the values that remain\nin the array. As a result, `swapRemove()` is, in general, faster than `orderedRemove()`.\n\n\n### Inserting elements at specific indexes\n\nWhen you need to insert values in the middle of your array,\ninstead of just appending them to the end of the array, you need to use\nthe `insert()` and `insertSlice()` methods, instead of\nthe `append()` and `appendSlice()` methods.\n\nThese two methods work very similarly to `insert()` and `insert_range()`\nfrom the C++ `std::vector` class. You provide an index to these methods,\nand they insert the values that you provide at that index in the array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 10);\ndefer buffer.deinit();\n\ntry buffer.appendSlice(\"My Pedro\");\ntry buffer.insert(4, '3');\ntry buffer.insertSlice(2, \" name\");\nfor (buffer.items) |char| {\n try stdout.print(\"{c}\", .{char});\n}\n```\n:::\n\n\n\n\n```\nMy name P3edro\n```\n\n\n### Conclusion\n\nIf you feel the lack of some other method, I recommend\nyou to read the [official documentation for the `ArrayListAligned`](https://ziglang.org/documentation/master/std/#std.array_list.ArrayListAligned)[^zig-array2]\nstruct, which describes most of the methods available\nthrough the `ArrayList` object.\n\nYou will notice that there is a lot of other methods in this page that\nI did not described here, and I recommend you to explore these methods,\nand understand how they work.\n\n[^zig-array2]: \n\n\n\n## Maps or HashTables {#sec-maps-hashtables}\n\nSome professionals know this type of data structure by different terms, like \"map\",\n\"hashmap\" or \"associative arrays\". But the most common term used is *hashtable*.\nEvery programming language normally have some implementation of a hashtable in their\nstandard libraries. Python have `dict()`, C++ have `std::map` and `std::unordered_map`, Rust\nhave `HashMap`, Javascript have `Object()` and `Map()`, etc.\n\n\n\n### What is a hashtable?\n\nA hashtable is a data structure based on key-value pairs.\nYou provide a key and a value to this structure, then, the hashtable will store\nthe input value at a location that can be identified by the input\nkey that you provided.\nIt does that by using an underlying array and a hash function.\nThese two components are essential to how a hashtable works.\n\nUnder the hood, the hashtable contains an array. This array is where the values\nare stored, and the elements of this array are usually called of *buckets*.\nSo the values that you provide to the hashtable are stored inside buckets,\nand you access each bucket by using an index.\n\nWhen you provide a key to a hashtable, it passes this key to the\nhash function. This hash function uses some sort of hashing algorithm to transform\nthis key into an index. This index is actually an array index. It's a position\nin the underlying array of the hashtable.\nThis is how a key identifies a specific position (or location) inside the hashtable\nstructure.\n\nTherefore, you provide a key to the hashtable, and this key identifies a specific location\ninside the hashtable, then, the hashtable takes the input value that you provided,\nand stores this value in the location identified by this input key.\nYou could say that the key maps to the value stored in the hashtable. You find\nthe value, by using the key that identifies the location where the value is stored.\nThe @fig-hashtable presents this process visually.\n\n\n![A diagram of a Hashtable. Source: Wikipedia, the free encyclopedia.](./../Figures/hashtable.svg){#fig-hashtable}\n\n\nThe operation described in the previous paragraph is normally called an *insertion* operation.\nBecause you are inserting new values into the hashtable.\nBut there are other types of operations in hashtables such as *delete* and *lookup*.\nDelete is self describing, it's when you delete (or remove) a value from the hashtable.\nWhile lookup corresponds to when you look at a value that is stored in\nthe hashtable, by using the key that identifies the location where this value is stored.\n\nSometimes, instead of storing the values directly, the underlying array of the hashtable might be an array of pointers,\ni.e., the buckets of the array stores pointers that points to the value,\nor also, may be an array of linked lists.\nThese cases are common on hashtables that allows duplicate keys, or, in other words,\non hashtables that effectively handle \"collisions\" that may arise from the hash function.\n\nDuplicate keys, or this \"collision\" thing that I'm talking about, is when you have two different keys\nthat points to the same location (i.e., to the same index)\nin the underlying array of the hashtable. This might happen depending on the characteristics of the hash function\nthat is being used in the hashtable. Some implementations of the hashtable will actively deal with collisions,\nmeaning that, they will handle this case in some way. For example, the hashtable\nmight transform all buckets into linked lists. Because with a linked list you can store\nmultiple values into a single bucket.\n\nThere are different techniques to handle collisions in hashtables, which I will not describe\nin this book, because it's not our main scope here. But you can find a good description of\nsome of the most common techniques at the Wikipedia page of hashtables [@wikipedia_hashtables].\n\n\n### Hashtables in Zig {#sec-hashmap}\n\nThe Zig Standard Library provides different implementations of a hashtable.\nEach implementation have its own cons and pros, which we will\ndiscuss later on, and all of them are available through the `std.hash_map` module.\n\nThe `HashMap` struct is a general-purpose hashtable,\nwhich have very fast operations (lookup, insertion, delete), and also,\nquite high load factors for low memory usage. You can create and provide a context object\nto the `HashMap` constructor. This context object allows you to tailor\nthe behaviour of the hashtable itself, because you can\nprovide a hash function implementation to be used by the hashtable\nthrough this context object.\n\nBut let's not worry about this context object now, because it's meant to be used\nby \"experts in the field of hashtables\". Since we are most likely not\nexperts in this field, we are going to take the easy way to create\na hashtable. Which is by using the `AutoHashMap()` function.\n\n\nThis `AutoHashMap()` function is essentially a \"create a hashtable object that uses the default settings\"\ntype of function. It automatically chooses a context object, and, therefore, a hash function implementation,\nfor you. This function receives two data types as input, the first input is the data type of the keys\nthat will be used in this hashtable, while the second input is the data type of the data that will be\nstored inside the hashtable, that is, the data type of the values to be stored.\n\nIn the example below, we are providing the data type `u32` in the first argument, and `u16` in the second argument of this\nfunction. This means that we are going to use `u32` values as keys in this hashtable, while `u16` values are the actual values\nthat are going to be stored into this hashtable.\nAt the end of this process, the `hash_table` object contains a `HashMap` object\nthat uses the default settings and context.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst AutoHashMap = std.hash_map.AutoHashMap;\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var hash_table = AutoHashMap(u32, u16).init(allocator);\n defer hash_table.deinit();\n\n try hash_table.put(54321, 89);\n try hash_table.put(50050, 55);\n try hash_table.put(57709, 41);\n std.debug.print(\n \"N of values stored: {d}\\n\",\n .{hash_table.count()}\n );\n std.debug.print(\n \"Value at key 50050: {d}\\n\",\n .{hash_table.get(50050).?}\n );\n\n if (hash_table.remove(57709)) {\n std.debug.print(\n \"Value at key 57709 successfully removed!\\n\",\n .{}\n );\n }\n std.debug.print(\n \"N of values stored: {d}\\n\",\n .{hash_table.count()}\n );\n}\n```\n:::\n\n\n\n\n```\nN of values stored: 3\nValue at key 50050: 55\nValue at key 57709 successfully removed!\nN of values stored: 2\n```\n\nYou can add/put new values into the hashtable by using the `put()` method. The first argument\nis the key to be used, and the second argument is the actual value that you want to store inside\nthe hashtable. In the example below, we first add the value 89 using the key 54321, next, we add\nthe value 55 using the key 50050, etc.\n\nNotice that we have used the method `count()` to see how many values are currently stored in the\nhashtable. After that, we also use the `get()` method to access (or look) at the value stored in\nthe position identified by the key 500050. The output of this `get()` method is an optional value.\nThis is why we use the `?` method at the end to get the actual value.\n\nAlso notice that we can remove (or delete) values from the hashtable by using the `remove()` method.\nYou provide the key that identifies the value that you want to delete, then, the method will\ndelete this value and return a `true` value as output. This `true` value essentially tells us\nthat the method successfully deleted the value.\n\nBut this delete operation might not be always successful. For example, you might provide the wrong\nkey to this method. I mean, maybe you provide\n(either intentionally or unintentionally) a key that points to an empty bucket,\ni.e., a bucket that still doesn't have a value in it.\nIn this case, the `remove()` method would return a `false` value.\n\n\n\n### Iterating through the hashtable\n\nIterating through the keys and values that are currently being stored in\nthe hashtable is a very common necessity.\nYou can do that in Zig by using an iterator object that can iterate\nthrough the elements of your hashtable object.\n\nThis iterator object works like any other iterator object that you would\nfind in languages such as C++ and Rust. It's basically a pointer object\nthat points to some value in the container, and has a `next()` method\nthat you can use to navigate (or iterate) through the values in the\ncontainer.\n\nYou can create such iterator object by using the `iterator()` method of the hashtable object.\nThis method returns an iterator object, from which you can use the `next()` method in conjunction\nwith a while loop to iterate through the elements of your hashtable. The `next()` method returns an optional\n`Entry` value, and therefore, you must unwrap this optional value to get the actual `Entry` value\nfrom which you can access the key and also the value identified by this key.\n\nWith this `Entry` value at hand, you can access the key of this current entry by using the `key_ptr`\nattribute and dereferencing the pointer that lives inside of it, while the value identified by this\nkey is accessed through the `value_ptr` attribute instead, which is also a pointer to be dereferenced.\nThe code example below demonstrates the use of these elements:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst AutoHashMap = std.hash_map.AutoHashMap;\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var hash_table = AutoHashMap(u32, u16).init(allocator);\n defer hash_table.deinit();\n\n try hash_table.put(54321, 89);\n try hash_table.put(50050, 55);\n try hash_table.put(57709, 41);\n\n var it = hash_table.iterator();\n while (it.next()) |kv| {\n // Access the current key\n std.debug.print(\"Key: {d} | \", .{kv.key_ptr.*});\n // Access the current value\n std.debug.print(\"Value: {d}\\n\", .{kv.value_ptr.*});\n }\n}\n```\n:::\n\n\n\n\n```\nKey: 54321 | Value: 89\nKey: 50050 | Value: 55\nKey: 57709 | Value: 41\n```\n\n\nIf you want to iterate specifically through the values or the keys of your hashtable,\nyou can create a key iterator or a value iterator object. These are also iterator\nobjects, which have the same `next()` method that you can use to iterate through the\nhashtable.\n\nKey iterators are created from the `keyIterator()` method of your\nhashtable object, while value iterators are created from the `valueIterator()` method.\nAll you have to do is to unwrap the value from the `next()` method and deference it\ndirectly to access the key or the value that you are iterating over.\nThe code example below demonstrates the use of a key iterator,\nbut you can replicate the same logic to a value iterator.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar kit = hash_table.keyIterator();\nwhile (kit.next()) |key| {\n std.debug.print(\"Key: {d}\\n\", .{key.*});\n}\n```\n:::\n\n\n\n\n```\nKey: 54321\nKey: 50050\nKey: 57709\n```\n\n\n### The `ArrayHashMap` hashtable {#sec-array-map}\n\nIf you need to iterate through the elements of your hashtable constantly,\nyou might want to use the `ArrayHashMap` struct for your specific case,\ninstead of going with the usual and general-purpose `HashMap` struct.\n\nThe `ArrayHashMap` struct creates a hashtable that is faster to iterate over.\nThat is why this specific type of hashtable might be valuable to you.\nSome other properties of a `ArrayHashMap` hashtable are:\n\n- the order of insertion is preserved, i.e., the order of the values that you find while iterating through this hashtable is actually the order in which these values were inserted in the hashtable.\n- the key-value pairs are stored sequentially, one after another.\n\n\nYou can create an `ArrayHashMap` object by using, once again, a helper function that\nchooses automatically for you a hash function implementation. This is the\n`AutoArrayHashMap()` function, which works very similarly to the `AutoHashMap()`\nfunction that we presented in @sec-hashmap.\n\nYou provide two data types to this function. The data type of the keys that will be\nused in this hashtable, and the data type of the values that will be stored in\nthis hashtable.\n\nAn `ArrayHashMap` object have essentially the exact same methods from the `HashMap` struct.\nSo you can insert new values into the hashtable by using the `put()` method, and you can look (or get)\na value from the hashtable by using the `get()` method. But the `remove()` method is not available\nin this specific type of hashtable.\n\nIn order to delete values from the hashtable, you would use the same methods that you find in\nan `ArrayList` object, i.e., a dynamic array. I presented these methods in @sec-dynamic-array-remove,\nwhich are the `swapRemove()` and `orderedRemove()` methods. These methods have the same meaning here, or,\nthe same effect that they have in an `ArrayList` object.\n\nThis means that, with `swapRemove()` you remove the value from the hashtable, but you do not preserve\nthe order in which the values were inserted into the structure. While `orderedRemove()` is able\nto retain the order in which these values were inserted.\n\nBut instead of providing an index as input to `swapRemove()` or `orderedRemove()`, like I described\nin @sec-dynamic-array-remove, these methods here in an `ArrayHashMap` take a key as input, like\nthe `remove()` method from a `HashMap` object. If you want to provide an index as input, instead\nof a key, you should use the `swapRemoveAt()` and `orderedRemoveAt()` methods.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar hash_table = AutoArrayHashMap(u32, u16)\n .init(allocator);\ndefer hash_table.deinit();\n```\n:::\n\n\n\n\n\n\n### The `StringHashMap` hashtable {#sec-string-hash-map}\n\nOne thing that you will notice in the other two types of hashtables that I have\npresented over the last sections, is that neither of them accepts a slice data type\nin their keys.\nWhat this means is that you cannot use a slice value to represent a key in\nthese types of hashtable.\n\nThe most obvious consequence of this, is that you cannot use strings as keys\nin these hashtables. But it's extremely common to use strings as keys\nin hashtables.\n\nTake this very simple Javascript code snippet as an example. We are creating\na simple hashtable object named `people`. Then, we add a new entry to this\nhashtable, which is identified by the string `'Pedro'`. This string is the\nkey in this case, while the object containing different personal information such as\nage, height and city, is the value to be stored in the hashtable.\n\n```js\nvar people = new Object();\npeople['Pedro'] = {\n 'age': 25,\n 'height': 1.67,\n 'city': 'Belo Horizonte'\n};\n```\n\nThis pattern of using strings as keys is very common in\nall sorts of situations. That is why the Zig Standard Library offers a\nspecific type of hashtable for this purpose, which is created through the `StringHashMap()` function.\nThis function creates a hashtable that uses strings as keys. The only input of this\nfunction is the data type of the values that will be stored into this hashtable.\n\nIn the example below, I'm creating a hashtable to store the ages of different people.\nEach key in this hashtable is represented by the name of each person, while the value stored in the\nhashtable is the age of this person identified by the key.\n\nThat is why I provide the `u8` data type (which is the data type used by the age values) as input to this `StringHashMap()` function.\nAs the result, it creates a hashtable that uses string values as keys, and, that stores\n`u8` values in it. Notice that an allocator object is provided at the `init()` method of the\nresulting object from the `StringHashMap()` function.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var ages = std.StringHashMap(u8).init(allocator);\n defer ages.deinit();\n\n try ages.put(\"Pedro\", 25);\n try ages.put(\"Matheus\", 21);\n try ages.put(\"Abgail\", 42);\n\n var it = ages.iterator();\n while (it.next()) |kv| {\n std.debug.print(\"Key: {s} | \", .{kv.key_ptr.*});\n std.debug.print(\"Age: {d}\\n\", .{kv.value_ptr.*});\n }\n}\n```\n:::\n\n\n\n\n```\nKey: Pedro | Age: 25\nKey: Abgail | Age: 42\nKey: Matheus | Age: 21\n```\n\n\n### The `StringArrayHashMap` hashtable\n\nThe Zig Standard Library also provides a type of hashtable that mix the cons and pros of the\n`StringHashMap` and `ArrayHashMap` together. That is, a hashtable\nthat uses strings as keys, but also have the advantages from `ArrayHashMap`.\nIn other words, you can have a hashtable that is fast to iterate over,\nthat preserves insertion order, and also, that uses strings as keys.\n\nYou can create such type of hashtable by using the `StringArrayHashMap()` function.\nThis function accepts a data type as input, which is the data type of the values that are\ngoing to be stored inside this hashtable, in the same style as the function presented\nin @sec-string-hash-map.\n\nYou can insert new values into this hashtable by using the same `put()` method that\nwe have discussed in @sec-string-hash-map. And you can also get values from the hashtable\nby using the same `get()` method.\nLike its `ArrayHashMap` brother, to delete values from this specific type of hashtable,\nwe also use the `orderedRemove()` and `swapRemove()` methods, with the same effects that\nI have described in @sec-array-map.\n\nIf we take the code example that was exposed in @sec-string-hash-map, we can\nachieve the exact same result with `StringArrayHashMap()`:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar ages = std.StringArrayHashMap(u8).init(allocator);\n```\n:::\n\n\n\n\n\n\n\n## Linked lists\n\nThe Zig Standard Library provides an implementation for both singly and doubly linked lists.\nA linked list is a linear data structure that looks like a chain, or, a rope.\nThe main advantage of this data structure is that you normally have very fast\ninsertion and deletion operations. But, as a disadvantage, iterating through\nthis data structure is usually not so fast as iterating through an array.\n\nThe idea behind a linked list is to build a structure that consists of a sequence of nodes\nconnected to each other by pointers. This means that linked lists are usually not contiguous\nin memory, because each node might be anywhere in memory. They do not need to be close to\none another.\n\nIn @fig-linked-list we can see a diagram of a singly linked list. We begin at the first node\n(which is usually called \"the head of the linked list\"). Then, from this\nfirst node we uncover the remaining nodes in the structure, by following the locations pointed\nby the pointers found in each node.\n\nEach node has two things in it. It has the value that is stored in the current node\n, and also, a pointer. This pointer points to the next node in the list. If this pointer\nis null, then, it means that we have reached the end of our linked list.\n\n![A diagram of a singly linked list.](./../Figures/linked-list.png){#fig-linked-list}\n\n\nIn @fig-linked-list2 we can see a diagram of a doubly linked list. The only thing that really\nchanges now is that every node in the linked list has both a pointer to the previous node,\nand, a pointer to the next node. So every node in a doubly linked list has two pointers in it. These are\nusually called the `prev` (for \"previous\") and the `next` (for \"next\") pointers of the node.\n\nIn the singly linked list example, we had only one single pointer in each node, and this singular\npointer was always pointing to the next node in the sequence. This means that singly linked lists\nnormally have only the `next` pointer in them.\n\n![A diagram of a doubly linked list.](./../Figures/doubly-linked-list.png){#fig-linked-list2}\n\n\nLinked lists are available in Zig through the functions `SinglyLinkedList()` and\n`DoublyLinkedList()`, for \"singly linked lists\" and \"doubly linked lists\", respectively. These functions are\nactually generic functions, which we are going to talk more about in @sec-generic-fun.\n\nFor now, just understand that, in order to create a linked list object,\nwe begin by providing a data type to these functions. This data type defines\nthe type of data that each node in this linked list will store. In the example below,\nwe are creating a singly linked list of `u32` values.\nSo each node in this linked list will store a `u32` value.\n\nBoth the `SinglyLinkedList()` and `DoublyLinkedList()` functions returns a type,\ni.e., a struct definition, as output. Therefore, the object `Lu32` is actually\na struct definition. It defines the type \"singly linked list of `u32` values\".\n\nNow that we have the definition of the struct, we need to instantiate a `Lu32` object.\nWe normally instantiate struct objects in Zig by using an `init()` method.\nBut in this case, we are instantiating the struct directly, by using an empty\n`struct` literal, in the expression `Lu32{}`.\n\nIn this example, we first create multiple node objects, and after we create them,\nwe start to insert and connect these nodes to build the linked list, using the\n`prepend()` and `insertAfter()` methods. Notice that the `prepend()` method\nis a method from the linked list object, while the `insertAfter()` is a method\npresent in the node objects.\n\nIn essence, the `prepend()` method inserts a node at the beginning of the linked\nlist. In other words, the node that you provide to this method, becomes the new\n\"head node\" of the linked list. It becomes the first node in the list (see @fig-linked-list).\n\nOn the other side, the `insertAfter()` method is used to basically connect two nodes together.\nWhen you provide a node to this method, it creates a pointer to this input node,\nand stores this pointer in the `next` attribute of the current node, from which the method was called from.\n\nBecause doubly linked lists have both a `next` and a `prev` attributes in each node\n(as described in @fig-linked-list2), a node object created from\na `DoublyLinkedList` object have both an `insertBefore()` (for `prev`)\nand an `insertAfter()` (for `next`) methods available.\n\nThus, if we have used a doubly linked list, we can use the `insertBefore()` method\nto store the pointer to the input node in the `prev` attribute. This would put the input\nnode as the \"previous node\", or, the node before the current node. In contrast, the `insertAfter()` method\nputs the pointer created to the input node in the `next` attribute of the current node,\nand as result, the input node becomes the \"next node\" of the current node.\n\nSince we are using a singly linked list in this example, we have only the `insertAfter()` method\navailable in the node objects that we create from our `Lu32` type.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SinglyLinkedList = std.SinglyLinkedList;\nconst Lu32 = SinglyLinkedList(u32);\n\npub fn main() !void {\n var list = Lu32{};\n var one = Lu32.Node{ .data = 1 };\n var two = Lu32.Node{ .data = 2 };\n var three = Lu32.Node{ .data = 3 };\n var four = Lu32.Node{ .data = 4 };\n var five = Lu32.Node{ .data = 5 };\n\n list.prepend(&two); // {2}\n two.insertAfter(&five); // {2, 5}\n list.prepend(&one); // {1, 2, 5}\n two.insertAfter(&three); // {1, 2, 3, 5}\n three.insertAfter(&four); // {1, 2, 3, 4, 5}\n}\n```\n:::\n\n\n\n\n\nThere are other methods available from the linked list object, depending if this object is\na singly linked list or a doubly linked list, that might be very useful for you. You can find a\nsummary of them in the bullet points below:\n\n- `remove()` to remove a specific node from the linked list.\n- if singly linked list, `len()` to count how many nodes there is in the linked list.\n- if doubly linked list, checkout the `len` attribute to see how many nodes there is in the linked list.\n- if singly linked list, `popFirst()` to remove the first node (i.e., the \"head\") from the linked list.\n- if doubly linked list, `pop()` and `popFirst()` to remove the last and first nodes from the linked list, respectively.\n- if doubly linked list, `append()` to add a new node to end of the linked list (i.e., inverse of `prepend()`).\n\n\n\n## Multi array structure\n\nZig introduces a new data structure called `MultiArrayList()`. It's a different version of the dynamic array\nthat we have introduced in @sec-dynamic-array. The difference between this structure and the `ArrayList()`\nthat we know from @sec-dynamic-array, is that `MultiArrayList()` creates a separate dynamic array\nfor each field of the struct that you provide as input.\n\nConsider the following code example. We create a new custom struct called `Person`. This\nstruct contains three different data members, or, three different fields. As consequence,\nwhen we provide this `Person` data type as input to `MultiArrayList()`, this\ncreates a \"struct of three different arrays\" called `PersonArray`. In other words,\nthis `PersonArray` is a struct that contains three internal dynamic arrays in it.\nOne array for each field found in the `Person` struct definition.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Person = struct {\n name: []const u8,\n age: u8,\n height: f32,\n};\nconst PersonArray = std.MultiArrayList(Person);\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var people = PersonArray{};\n defer people.deinit(allocator);\n\n try people.append(allocator, .{\n .name = \"Auguste\", .age = 15, .height = 1.54\n });\n try people.append(allocator, .{\n .name = \"Elena\", .age = 26, .height = 1.65\n });\n try people.append(allocator, .{\n .name = \"Michael\", .age = 64, .height = 1.87\n });\n}\n```\n:::\n\n\n\n\nIn other words, instead of creating an array of \"persons\", the `MultiArrayList()` function\ncreates a \"struct of arrays\". Each data member of this struct is a different array that stores\nthe values of a specific field from the `Person` values that were added (or, appended) to this \"struct of arrays\".\nOne important detail is that each of these separate internal arrays stored inside `PersonArray`\nare dynamic arrays. This means that these arrays can grow in capacity automatically as needed, to accomodate\nmore values.\n\nThe @fig-multi-array exposed below presents a diagram that describes the `PersonArray` struct\nthat we have created in the previous code example. Notice that the values of the data members\npresent in each of the three `Person` values that we have appended into the `PersonArray` object\n, are scattered across three different internal arrays of the `PersonArray` object.\n\n![A diagram of the `PersonArray` struct.](./../Figures/multi-array.png){#fig-multi-array}\n\nYou can easily access each of these arrays separately, and iterate over the values of each array.\nFor that, you will need to call the `items()` method from the `PersonArray` object, and provide as input\nto this method, the name of the field that you want to iterate over.\nIf you want to iterate through the `.age` array for example, then, you need to call `items(.age)` from\nthe `PersonArray` object, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (people.items(.age)) |*age| {\n try stdout.print(\"Age: {d}\\n\", .{age.*});\n}\n```\n:::\n\n\n\n\n```\nAge: 15\nAge: 26\nAge: 64\n```\n\n\nIn the above example, we are iterating over the values of the `.age` array, or,\nthe internal array of the `PersonArray` object that contains the values of the `age`\ndata member from the `Person` values that were added to the multi array struct.\n\nIn this example we are calling the `items()` method directly from the `PersonArray`\nobject. However, in most situations it's recommened to call this `items()` method\nfrom a \"slice object\", which you can create from the `slice()` method.\nThe reason for this is that calling `items()` multiple times have better performance\nif you use a slice object.\n\nTherefore, if you are planning to access only one of the\ninternal arrays from your \"multi array struct\", it's fine to call `items()` directly\nfrom the multi array object. But if you need to access many of the internal arrays\nfrom your \"multi array struct\", then, you will likely need to call `items()` more\nthan once, and, in such circumstance, is better to call `items()` through a slice object.\nThe example below demonstrates the use of such object:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar slice = people.slice();\nfor (slice.items(.age)) |*age| {\n age.* += 10;\n}\nfor (slice.items(.name), slice.items(.age)) |*n,*a| {\n try stdout.print(\n \"Name: {s}, Age: {d}\\n\", .{n.*, a.*}\n );\n}\n```\n:::\n\n\n\n\n```\nName: Auguste, Age: 25\nName: Elena, Age: 36\nName: Michael, Age: 74\n```\n\n\n## Conclusion\n\nThere are many other data structures that I haven't presented here.\nBut you can check them out at the official Zig Standard Library documentation page.\nActually, when you get into the [homepage of the documentation](https://ziglang.org/documentation/master/std/#)[^home], the first thing\nthat appears to you in this page, is a list of types and data structures that\nare available in the Zig Standard Library.\nThere are some very specific data structures in this list, like a\n[`BoundedArray` struct](https://ziglang.org/documentation/master/std/#std.bounded_array.BoundedArray)[^bounded]\n, but there is also some more general structures, such as a\n[`PriorityQueue` struct](https://ziglang.org/documentation/master/std/#std.priority_queue.PriorityQueue)[^priority].\n\n\n[^home]: \n[^priority]: .\n[^bounded]: \n", - "supporting": [ - "09-data-structures_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n# Data Structures\n\nIn this chapter, I want to present the most common Data Structures that are available from\nthe Zig Standard Library, especially `ArrayList` and also `HashMap`. These are generic Data Structures\nthat you can use to store and control any type of data that is produced by your application.\n\n## Dynamic Arrays {#sec-dynamic-array}\n\nIn high level languages, arrays are usually dynamic. They can easily grow\nin size when they have to, and you don't need to worry about it.\nIn contrast, arrays in low level languages are usually static by default.\nThis is the reality of C, C++, Rust and also Zig. Static arrays were presented at\n@sec-arrays, but in this section, we are going to talk about dynamic arrays in Zig.\n\nDynamic arrays are simply arrays that can grow in size during the runtime\nof your program. Most low level languages have some implementation of\na dynamic array in their standard library. C++ have `std::vector`, Rust have `Vec`,\nand Zig have `std.ArrayList`.\n\nThe `std.ArrayList` struct provides a contiguous and growable array for you.\nIt works like any other dynamic array, it allocates a contiguous block of memory, and when this block have no space left,\n`ArrayList` allocates another contiguous and bigger block of memory, copies the\nelements to this new location, and erases (or frees) the previous block of memory.\n\n\n### Capacity vs Length\n\nWhen we talk about dynamic arrays, we usually have two similar concepts that\nare very essential to how a dynamic array works behind the hood.\nThese concepts are *capacity* and *length*. In some contexts, especially\nin C++, *length* is also called of *size*.\n\nAlthough they look similar, these concepts represent different things\nin the context of a dynamic array. *Capacity* is the number of items (or elements)\nthat your dynamic array can currently hold without the need to allocate more memory.\n\nIn contrast, the *length* refers to how many elements in the array\nare currently being used, or, in other words, how many elements in this array\nthat you have assigned a value to. Every dynamic array works around\na block of allocated memory, which represents an array with total capacity for $n$ elements.\nHowever, only a portion of these $n$ elements are being used most of the time. This portion\nof $n$ is the *length* of the array. So every time you append a new value\nto the array, you are incrementing its *length* by one.\n\nThis means that a dynamic array usually works with an extra margin, or an extra space\nthat is currently empty, but waiting and ready to be used. This \"extra space\"\nis essentially the difference between *capacity* and *length*. *Capacity* represents\nthe total number of elements that the array can hold without the need to re-allocate\nor re-expand the array, while the *length* represents how much of this capacity\nis currently being used to hold/store values.\n\n@fig-capacity-length presents this idea visually. Notice that, at first,\nthe capacity of the array is greater than the length of the array.\nSo, the dynamic array have extra space that is currently empty, but it\nis ready to receive a value to be stored.\n\n![Difference between capacity and length in a dynamic array](./../Figures/dynamic-array.png){#fig-capacity-length}\n\nWe can also see in @fig-capacity-length that, when *length* and *capacity* are equal, it means that the array have no space left.\nWe have reached the ceiling of our capacity, and because of that, if we want to store more values\nin this array, we need to expand it. We need to get a bigger space that can hold more values\nthan what we currently have.\n\nA dynamic array works by expanding the underlying array, whenever the *length* becomes equal\nto the *capacity* of the array. It basically allocates a new contiguous block of memory that is bigger\nthan the previous one, then, it copies all values that are currently being stored to this new\nlocation (i.e., this new block of memory), then, it frees the previous block of\nmemory. At the end of this process, the new underlying array have a bigger *capacity*, and, therefore,\nthe *length* becomes, once again, smaller than the *capacity* of the array.\n\nThis is the cycle of a dynamic array. Notice that, throughout this cycle, the *capacity* is always\neither equal to or higher than the *length* of the array. If you have an `ArrayList` object (let's suppose\nyou named it `buffer`), you can check the current capacity of your array by accessing the `capacity`\nattribute of your `ArrayList` object, while the current *length* of it is available at the `items.len`\nattribute.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// Check capacity\nbuffer.capacity;\n// Check length\nbuffer.items.len;\n```\n:::\n\n\n\n### Creating an `ArrayList` object\n\nIn order to use `ArrayList`, you must provide an allocator object to it.\nRemember, Zig does not have a default memory allocator. And as I described in @sec-allocators, all memory\nallocations must be done by an allocator object that you define, that\nyou have control over. In our example here, I'm going to use\na general purpose allocator, but you can use any other allocator\nof your preference.\n\nWhen you initialize an `ArrayList` object, you must provide the data type of the elements of\nthe array. In other words, this defines the type of data that this array (or container) will\nstore. Therefore, if I provide the `u8` type to it, then, I will create a dynamic\narray of `u8` values. However, if I provide a struct that I have defined instead, like the struct `User`\nfrom @sec-structs-and-oop, then, a dynamic array of `User` values\nwill be created. In the example below, with the expression `ArrayList(u8)` we\nare creating a dynamic array of `u8` values.\n\nAfter you provide the data type of the elements of the array, you can initialize\nan `ArrayList` object by either using the `init()` or the `initCapacity()` methods.\nThe former method receives only the allocator object\nas input, while the latter method receives both the allocator object and a capacity number as inputs.\nWith the latter method, you not only initialize the struct, but you\nalso set the starting capacity of the allocated array.\n\nUsing the `initCapacity()` method is the preferred way to initialize your dynamic array.\nBecause reallocations, or, in other words, the process of expanding the capacity of the array,\nis always a high cost operation. You should take any possible opportunity to avoid reallocations in\nyour array. If you know how much space your array needs to occupy at the beginning,\nyou should always use `initCapacity()` to create your dynamic array.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 100);\ndefer buffer.deinit();\n```\n:::\n\n\n\nIn the example above, the `buffer` object starts as an array of 100 elements. If this\n`buffer` object needs to create more space to accomodate more elements during the runtime of your program, the `ArrayList`\ninternals will perform the necessary actions for you automatically.\nAlso notice the `deinit()` method being used to destroy the `buffer` object at the\nend of the current scope, by freeing all the memory that was allocated for the dynamic\narray stored in this `buffer` object.\n\n\n### Adding new elements to the array\n\nNow that we have created our dynamic array, we can start to use it. You can append (a.k.a \"add\")\nnew values to this array by using the `append()` method. This method works the same way\nas the `append()` method from a Python list, or, the `emplace_back()` method from `std::vector` of C++.\nYou provide a single value to this method, and the method appends this value to the array.\n\nYou can also use the `appendSlice()` method to append multiple values at once. You provide\na slice (slices were described in @sec-arrays) to this method, and the method adds all values present\nin this slice to your dynamic array.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry buffer.append('H');\ntry buffer.append('e');\ntry buffer.append('l');\ntry buffer.append('l');\ntry buffer.append('o');\ntry buffer.appendSlice(\" World!\");\n```\n:::\n\n\n### Removing elements from the array {#sec-dynamic-array-remove}\n\nYou can use the `pop()` method to \"pop\" or remove\nthe last element in the array. It's worth noting that this method\ndo not change the capacity of the array. It just deletes or erases\nthe last value stored in the array.\n\nAlso, this method returns as result the value that got deleted. That is, you can\nuse this method to both get the last value in the array, and also, remove\nit from the array. It's a \"get and remove value\" type of method.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exclamation_mark = buffer.pop();\n```\n:::\n\n\nNow, if you want to remove specific elements from specific positions\nof your array, you can use the `orderedRemove()` method from your\n`ArrayList` object. With this method, you can provide an index as input,\nthen, the method will delete the value that is at this index in the array.\nYou are effectively reducing the *length* of the array everytime you execute\nan `orderedRemove()` operation.\n\nIn the example below, we first create an `ArrayList` object, and we fill it\nwith numbers. Then, we use `orderedRemove()` to remove the value at\nindex 3 in the array, two consecutive times.\n\nAlso, notice that we are assigning the result of `orderedRemove()` to the\nunderscore character. So we are discarding the result value of this method.\nThe `orderedRemove()` method returns the value that got deleted, in a similar\nstyle to the `pop()` method.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 100);\ndefer buffer.deinit();\n\nfor (0..10) |i| {\n const index: u8 = @intCast(i);\n try buffer.append(index);\n}\n\nstd.debug.print(\n \"{any}\\n\", .{buffer.items}\n);\n_ = buffer.orderedRemove(3);\n_ = buffer.orderedRemove(3);\n\nstd.debug.print(\"{any}\\n\", .{buffer.items});\nstd.debug.print(\"{any}\\n\", .{buffer.items.len});\n```\n:::\n\n\n```\n{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }\n{ 0, 1, 2, 5, 6, 7, 8, 9 }\n8\n```\n\nOne key characteristic about `orderedRemove()` is that it preserves the order\nof the values in the array. So, it deletes the value that you asked it to\nremove, but it also makes sure that the order of the values that remain in the array\nstay the same as before.\n\nNow, if you don't care about the order of the values, for example, maybe you want to treat\nyour dynamic array as a set of values, like the `std::unordered_set`\nstructure from C++, you can use the `swapRemove()` method instead. This method\nworks similarly to the `orderedRemove()` method. You give an index to this\nmethod, then, it deletes the value that is at this index in the array.\nBut this method does not preserve the original order of the values that remain\nin the array. As a result, `swapRemove()` is, in general, faster than `orderedRemove()`.\n\n\n### Inserting elements at specific indexes\n\nWhen you need to insert values in the middle of your array,\ninstead of just appending them to the end of the array, you need to use\nthe `insert()` and `insertSlice()` methods, instead of\nthe `append()` and `appendSlice()` methods.\n\nThese two methods work very similarly to `insert()` and `insert_range()`\nfrom the C++ `std::vector` class. You provide an index to these methods,\nand they insert the values that you provide at that index in the array.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 10);\ndefer buffer.deinit();\n\ntry buffer.appendSlice(\"My Pedro\");\ntry buffer.insert(4, '3');\ntry buffer.insertSlice(2, \" name\");\nfor (buffer.items) |char| {\n try stdout.print(\"{c}\", .{char});\n}\n```\n:::\n\n\n```\nMy name P3edro\n```\n\n\n### Conclusion\n\nIf you feel the lack of some other method, I recommend\nyou to read the [official documentation for the `ArrayListAligned`](https://ziglang.org/documentation/master/std/#std.array_list.ArrayListAligned)[^zig-array2]\nstruct, which describes most of the methods available\nthrough the `ArrayList` object.\n\nYou will notice that there is a lot of other methods in this page that\nI did not described here, and I recommend you to explore these methods,\nand understand how they work.\n\n[^zig-array2]: \n\n\n\n## Maps or HashTables {#sec-maps-hashtables}\n\nSome professionals know this type of data structure by different terms, like \"map\",\n\"hashmap\" or \"associative arrays\". But the most common term used is *hashtable*.\nEvery programming language normally have some implementation of a hashtable in their\nstandard libraries. Python have `dict()`, C++ have `std::map` and `std::unordered_map`, Rust\nhave `HashMap`, Javascript have `Object()` and `Map()`, etc.\n\n\n\n### What is a hashtable?\n\nA hashtable is a data structure based on key-value pairs.\nYou provide a key and a value to this structure, then, the hashtable will store\nthe input value at a location that can be identified by the input\nkey that you provided.\nIt does that by using an underlying array and a hash function.\nThese two components are essential to how a hashtable works.\n\nUnder the hood, the hashtable contains an array. This array is where the values\nare stored, and the elements of this array are usually called of *buckets*.\nSo the values that you provide to the hashtable are stored inside buckets,\nand you access each bucket by using an index.\n\nWhen you provide a key to a hashtable, it passes this key to the\nhash function. This hash function uses some sort of hashing algorithm to transform\nthis key into an index. This index is actually an array index. It's a position\nin the underlying array of the hashtable.\nThis is how a key identifies a specific position (or location) inside the hashtable\nstructure.\n\nTherefore, you provide a key to the hashtable, and this key identifies a specific location\ninside the hashtable, then, the hashtable takes the input value that you provided,\nand stores this value in the location identified by this input key.\nYou could say that the key maps to the value stored in the hashtable. You find\nthe value, by using the key that identifies the location where the value is stored.\nThe @fig-hashtable presents this process visually.\n\n\n![A diagram of a Hashtable. Source: Wikipedia, the free encyclopedia.](./../Figures/hashtable.svg){#fig-hashtable}\n\n\nThe operation described in the previous paragraph is normally called an *insertion* operation.\nBecause you are inserting new values into the hashtable.\nBut there are other types of operations in hashtables such as *delete* and *lookup*.\nDelete is self describing, it's when you delete (or remove) a value from the hashtable.\nWhile lookup corresponds to when you look at a value that is stored in\nthe hashtable, by using the key that identifies the location where this value is stored.\n\nSometimes, instead of storing the values directly, the underlying array of the hashtable might be an array of pointers,\ni.e., the buckets of the array stores pointers that points to the value,\nor also, may be an array of linked lists.\nThese cases are common on hashtables that allows duplicate keys, or, in other words,\non hashtables that effectively handle \"collisions\" that may arise from the hash function.\n\nDuplicate keys, or this \"collision\" thing that I'm talking about, is when you have two different keys\nthat points to the same location (i.e., to the same index)\nin the underlying array of the hashtable. This might happen depending on the characteristics of the hash function\nthat is being used in the hashtable. Some implementations of the hashtable will actively deal with collisions,\nmeaning that, they will handle this case in some way. For example, the hashtable\nmight transform all buckets into linked lists. Because with a linked list you can store\nmultiple values into a single bucket.\n\nThere are different techniques to handle collisions in hashtables, which I will not describe\nin this book, because it's not our main scope here. But you can find a good description of\nsome of the most common techniques at the Wikipedia page of hashtables [@wikipedia_hashtables].\n\n\n### Hashtables in Zig {#sec-hashmap}\n\nThe Zig Standard Library provides different implementations of a hashtable.\nEach implementation have its own cons and pros, which we will\ndiscuss later on, and all of them are available through the `std.hash_map` module.\n\nThe `HashMap` struct is a general-purpose hashtable,\nwhich have very fast operations (lookup, insertion, delete), and also,\nquite high load factors for low memory usage. You can create and provide a context object\nto the `HashMap` constructor. This context object allows you to tailor\nthe behaviour of the hashtable itself, because you can\nprovide a hash function implementation to be used by the hashtable\nthrough this context object.\n\nBut let's not worry about this context object now, because it's meant to be used\nby \"experts in the field of hashtables\". Since we are most likely not\nexperts in this field, we are going to take the easy way to create\na hashtable. Which is by using the `AutoHashMap()` function.\n\n\nThis `AutoHashMap()` function is essentially a \"create a hashtable object that uses the default settings\"\ntype of function. It automatically chooses a context object, and, therefore, a hash function implementation,\nfor you. This function receives two data types as input, the first input is the data type of the keys\nthat will be used in this hashtable, while the second input is the data type of the data that will be\nstored inside the hashtable, that is, the data type of the values to be stored.\n\nIn the example below, we are providing the data type `u32` in the first argument, and `u16` in the second argument of this\nfunction. This means that we are going to use `u32` values as keys in this hashtable, while `u16` values are the actual values\nthat are going to be stored into this hashtable.\nAt the end of this process, the `hash_table` object contains a `HashMap` object\nthat uses the default settings and context.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst AutoHashMap = std.hash_map.AutoHashMap;\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var hash_table = AutoHashMap(u32, u16).init(allocator);\n defer hash_table.deinit();\n\n try hash_table.put(54321, 89);\n try hash_table.put(50050, 55);\n try hash_table.put(57709, 41);\n std.debug.print(\n \"N of values stored: {d}\\n\",\n .{hash_table.count()}\n );\n std.debug.print(\n \"Value at key 50050: {d}\\n\",\n .{hash_table.get(50050).?}\n );\n\n if (hash_table.remove(57709)) {\n std.debug.print(\n \"Value at key 57709 successfully removed!\\n\",\n .{}\n );\n }\n std.debug.print(\n \"N of values stored: {d}\\n\",\n .{hash_table.count()}\n );\n}\n```\n:::\n\n\n```\nN of values stored: 3\nValue at key 50050: 55\nValue at key 57709 successfully removed!\nN of values stored: 2\n```\n\nYou can add/put new values into the hashtable by using the `put()` method. The first argument\nis the key to be used, and the second argument is the actual value that you want to store inside\nthe hashtable. In the example below, we first add the value 89 using the key 54321, next, we add\nthe value 55 using the key 50050, etc.\n\nNotice that we have used the method `count()` to see how many values are currently stored in the\nhashtable. After that, we also use the `get()` method to access (or look) at the value stored in\nthe position identified by the key 500050. The output of this `get()` method is an optional value.\nThis is why we use the `?` method at the end to get the actual value.\n\nAlso notice that we can remove (or delete) values from the hashtable by using the `remove()` method.\nYou provide the key that identifies the value that you want to delete, then, the method will\ndelete this value and return a `true` value as output. This `true` value essentially tells us\nthat the method successfully deleted the value.\n\nBut this delete operation might not be always successful. For example, you might provide the wrong\nkey to this method. I mean, maybe you provide\n(either intentionally or unintentionally) a key that points to an empty bucket,\ni.e., a bucket that still doesn't have a value in it.\nIn this case, the `remove()` method would return a `false` value.\n\n\n\n### Iterating through the hashtable\n\nIterating through the keys and values that are currently being stored in\nthe hashtable is a very common necessity.\nYou can do that in Zig by using an iterator object that can iterate\nthrough the elements of your hashtable object.\n\nThis iterator object works like any other iterator object that you would\nfind in languages such as C++ and Rust. It's basically a pointer object\nthat points to some value in the container, and has a `next()` method\nthat you can use to navigate (or iterate) through the values in the\ncontainer.\n\nYou can create such iterator object by using the `iterator()` method of the hashtable object.\nThis method returns an iterator object, from which you can use the `next()` method in conjunction\nwith a while loop to iterate through the elements of your hashtable. The `next()` method returns an optional\n`Entry` value, and therefore, you must unwrap this optional value to get the actual `Entry` value\nfrom which you can access the key and also the value identified by this key.\n\nWith this `Entry` value at hand, you can access the key of this current entry by using the `key_ptr`\nattribute and dereferencing the pointer that lives inside of it, while the value identified by this\nkey is accessed through the `value_ptr` attribute instead, which is also a pointer to be dereferenced.\nThe code example below demonstrates the use of these elements:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst AutoHashMap = std.hash_map.AutoHashMap;\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var hash_table = AutoHashMap(u32, u16).init(allocator);\n defer hash_table.deinit();\n\n try hash_table.put(54321, 89);\n try hash_table.put(50050, 55);\n try hash_table.put(57709, 41);\n\n var it = hash_table.iterator();\n while (it.next()) |kv| {\n // Access the current key\n std.debug.print(\"Key: {d} | \", .{kv.key_ptr.*});\n // Access the current value\n std.debug.print(\"Value: {d}\\n\", .{kv.value_ptr.*});\n }\n}\n```\n:::\n\n\n```\nKey: 54321 | Value: 89\nKey: 50050 | Value: 55\nKey: 57709 | Value: 41\n```\n\n\nIf you want to iterate specifically through the values or the keys of your hashtable,\nyou can create a key iterator or a value iterator object. These are also iterator\nobjects, which have the same `next()` method that you can use to iterate through the\nhashtable.\n\nKey iterators are created from the `keyIterator()` method of your\nhashtable object, while value iterators are created from the `valueIterator()` method.\nAll you have to do is to unwrap the value from the `next()` method and deference it\ndirectly to access the key or the value that you are iterating over.\nThe code example below demonstrates the use of a key iterator,\nbut you can replicate the same logic to a value iterator.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar kit = hash_table.keyIterator();\nwhile (kit.next()) |key| {\n std.debug.print(\"Key: {d}\\n\", .{key.*});\n}\n```\n:::\n\n\n```\nKey: 54321\nKey: 50050\nKey: 57709\n```\n\n\n### The `ArrayHashMap` hashtable {#sec-array-map}\n\nIf you need to iterate through the elements of your hashtable constantly,\nyou might want to use the `ArrayHashMap` struct for your specific case,\ninstead of going with the usual and general-purpose `HashMap` struct.\n\nThe `ArrayHashMap` struct creates a hashtable that is faster to iterate over.\nThat is why this specific type of hashtable might be valuable to you.\nSome other properties of a `ArrayHashMap` hashtable are:\n\n- the order of insertion is preserved, i.e., the order of the values that you find while iterating through this hashtable is actually the order in which these values were inserted in the hashtable.\n- the key-value pairs are stored sequentially, one after another.\n\n\nYou can create an `ArrayHashMap` object by using, once again, a helper function that\nchooses automatically for you a hash function implementation. This is the\n`AutoArrayHashMap()` function, which works very similarly to the `AutoHashMap()`\nfunction that we presented in @sec-hashmap.\n\nYou provide two data types to this function. The data type of the keys that will be\nused in this hashtable, and the data type of the values that will be stored in\nthis hashtable.\n\nAn `ArrayHashMap` object have essentially the exact same methods from the `HashMap` struct.\nSo you can insert new values into the hashtable by using the `put()` method, and you can look (or get)\na value from the hashtable by using the `get()` method. But the `remove()` method is not available\nin this specific type of hashtable.\n\nIn order to delete values from the hashtable, you would use the same methods that you find in\nan `ArrayList` object, i.e., a dynamic array. I presented these methods in @sec-dynamic-array-remove,\nwhich are the `swapRemove()` and `orderedRemove()` methods. These methods have the same meaning here, or,\nthe same effect that they have in an `ArrayList` object.\n\nThis means that, with `swapRemove()` you remove the value from the hashtable, but you do not preserve\nthe order in which the values were inserted into the structure. While `orderedRemove()` is able\nto retain the order in which these values were inserted.\n\nBut instead of providing an index as input to `swapRemove()` or `orderedRemove()`, like I described\nin @sec-dynamic-array-remove, these methods here in an `ArrayHashMap` take a key as input, like\nthe `remove()` method from a `HashMap` object. If you want to provide an index as input, instead\nof a key, you should use the `swapRemoveAt()` and `orderedRemoveAt()` methods.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar hash_table = AutoArrayHashMap(u32, u16)\n .init(allocator);\ndefer hash_table.deinit();\n```\n:::\n\n\n\n\n### The `StringHashMap` hashtable {#sec-string-hash-map}\n\nOne thing that you will notice in the other two types of hashtables that I have\npresented over the last sections, is that neither of them accepts a slice data type\nin their keys.\nWhat this means is that you cannot use a slice value to represent a key in\nthese types of hashtable.\n\nThe most obvious consequence of this, is that you cannot use strings as keys\nin these hashtables. But it's extremely common to use strings as keys\nin hashtables.\n\nTake this very simple Javascript code snippet as an example. We are creating\na simple hashtable object named `people`. Then, we add a new entry to this\nhashtable, which is identified by the string `'Pedro'`. This string is the\nkey in this case, while the object containing different personal information such as\nage, height and city, is the value to be stored in the hashtable.\n\n```js\nvar people = new Object();\npeople['Pedro'] = {\n 'age': 25,\n 'height': 1.67,\n 'city': 'Belo Horizonte'\n};\n```\n\nThis pattern of using strings as keys is very common in\nall sorts of situations. That is why the Zig Standard Library offers a\nspecific type of hashtable for this purpose, which is created through the `StringHashMap()` function.\nThis function creates a hashtable that uses strings as keys. The only input of this\nfunction is the data type of the values that will be stored into this hashtable.\n\nIn the example below, I'm creating a hashtable to store the ages of different people.\nEach key in this hashtable is represented by the name of each person, while the value stored in the\nhashtable is the age of this person identified by the key.\n\nThat is why I provide the `u8` data type (which is the data type used by the age values) as input to this `StringHashMap()` function.\nAs the result, it creates a hashtable that uses string values as keys, and, that stores\n`u8` values in it. Notice that an allocator object is provided at the `init()` method of the\nresulting object from the `StringHashMap()` function.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var ages = std.StringHashMap(u8).init(allocator);\n defer ages.deinit();\n\n try ages.put(\"Pedro\", 25);\n try ages.put(\"Matheus\", 21);\n try ages.put(\"Abgail\", 42);\n\n var it = ages.iterator();\n while (it.next()) |kv| {\n std.debug.print(\"Key: {s} | \", .{kv.key_ptr.*});\n std.debug.print(\"Age: {d}\\n\", .{kv.value_ptr.*});\n }\n}\n```\n:::\n\n\n```\nKey: Pedro | Age: 25\nKey: Abgail | Age: 42\nKey: Matheus | Age: 21\n```\n\n\n### The `StringArrayHashMap` hashtable\n\nThe Zig Standard Library also provides a type of hashtable that mix the cons and pros of the\n`StringHashMap` and `ArrayHashMap` together. That is, a hashtable\nthat uses strings as keys, but also have the advantages from `ArrayHashMap`.\nIn other words, you can have a hashtable that is fast to iterate over,\nthat preserves insertion order, and also, that uses strings as keys.\n\nYou can create such type of hashtable by using the `StringArrayHashMap()` function.\nThis function accepts a data type as input, which is the data type of the values that are\ngoing to be stored inside this hashtable, in the same style as the function presented\nin @sec-string-hash-map.\n\nYou can insert new values into this hashtable by using the same `put()` method that\nwe have discussed in @sec-string-hash-map. And you can also get values from the hashtable\nby using the same `get()` method.\nLike its `ArrayHashMap` brother, to delete values from this specific type of hashtable,\nwe also use the `orderedRemove()` and `swapRemove()` methods, with the same effects that\nI have described in @sec-array-map.\n\nIf we take the code example that was exposed in @sec-string-hash-map, we can\nachieve the exact same result with `StringArrayHashMap()`:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar ages = std.StringArrayHashMap(u8).init(allocator);\n```\n:::\n\n\n\n\n\n## Linked lists\n\nThe Zig Standard Library provides an implementation for both singly and doubly linked lists.\nMore specifically, through the structs `SinglyLinkedList` and `DoublyLinkedList`.\n\nIn case you are not familiar with these data structures, a linked list is a linear data structure that looks\nlike a chain, or, a rope. The main advantage of this data structure is that you normally have very fast\ninsertion and deletion operations. But, as a disadvantage, iterating through\nthis data structure is usually not so fast as iterating through an array.\n\nThe idea behind a linked list is to build a structure that consists of a sequence of nodes\nconnected to each other by pointers. This means that linked lists are usually not contiguous\nin memory, because each node might be anywhere in memory. They do not need to be close to\none another.\n\nIn @fig-linked-list we can see a diagram of a singly linked list. We begin at the first node\n(which is usually called \"the head of the linked list\"). Then, from this\nfirst node we uncover the remaining nodes in the structure, by following the locations pointed\nby the pointers found in each node.\n\nEach node has two things in it. It has the value that is stored in the current node\n, and also, a pointer. This pointer points to the next node in the list. If this pointer\nis null, then, it means that we have reached the end of our linked list.\n\n![A diagram of a singly linked list.](./../Figures/linked-list.png){#fig-linked-list}\n\n\nIn @fig-linked-list2 we can see a diagram of a doubly linked list. The only thing that really\nchanges now is that every node in the linked list has both a pointer to the previous node,\nand, a pointer to the next node. So every node in a doubly linked list has two pointers in it. These are\nusually called the `prev` (for \"previous\") and the `next` (for \"next\") pointers of the node.\n\nIn the singly linked list example, we had only one single pointer in each node, and this singular\npointer was always pointing to the next node in the sequence. This means that singly linked lists\nnormally have only the `next` pointer in them.\n\n![A diagram of a doubly linked list.](./../Figures/doubly-linked-list.png){#fig-linked-list2}\n\n\n\n### Recent change in the API\n\nOn previous versions of Zig, the `SinglyLinkedList` and `DoublyLinkedList` structs were initially implemented as \"generics data structures\".\nMeaning that, you would use a generic function to create a singly (or doubly) linked list that could store\nthe specific data type that you wanted to use. We will learn more about generics at @sec-generics, and also,\nhow we can create a \"generic data structure\" at @sec-generic-struct.\n\nHowever, on the latest versions of Zig, the structs `SinglyLinkedList` and `DoublyLinkedList` were altered to use a\n\"less generic API\". This specific change was introduced on April 3, 2025. Therefore, check if your Zig version is one released after this\ndate. Just have in mind that if you don't have a very recent version of the Zig compiler,\nyou might have problems while trying to compile the next examples exposed here.\n\n\n\n### How to use a singly linked list\n\nFor example, consider that you are creating a singly linked list that is going to store `u32` values.\nGiven this scenario, the first thing that we need to do, is to create a \"node type\" that is capable\nof storing a `u32` value. The `NodeU32` type exposed below demonstrates such \"node type\".\n\nNotice that the data type associated with the member named `data` is the most important part of this\ncustom \"node type\". It determines the data type that is going to be stored in each node.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\nconst NodeU32 = struct {\n data: u32,\n node: std.SinglyLinkedList.Node = .{},\n};\n```\n:::\n\n\nAfter we created our custom \"node type\" that can store the specific data type that we\nwant, we can just create a new and empty singly linked list, which will store our nodes.\nTo do that, we just create a new object with the type `SinglyLinkedList`, like this:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar list: std.SinglyLinkedList = .{};\n```\n:::\n\n\nNow, we have our linked list... But how can we insert nodes in it? Well, first of all,\nwe need to create our nodes. So let's focus on that first. The snippet exposed below demonstrates\nhow we could use our `NodeU32` struct to create such nodes.\n\nNotice in this snippet that we are just setting the `data` member of the struct for now.\nWe don't need to connect these nodes together in this first instance. This is why we ignore\nthe `node` member at first. But we are going to connect these nodes in a future point of the code, which is\nwhy these objects are marked as \"variable objects\", so that we can alter them in the future.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar one: NodeU32 = .{ .data = 1 };\nvar two: NodeU32 = .{ .data = 2 };\nvar three: NodeU32 = .{ .data = 3 };\nvar five: NodeU32 = .{ .data = 5 };\n```\n:::\n\n\nNow that we have both the linked list and also the nodes created, we can start to connect them together.\nYou can use the `prepend()` method from the linked list object to insert the first node in the list, which\nis the \"head\" of the linked list. As the name suggests, this specific method prepends the input node to the linked list,\nor, in other words, it transforms the input node into the first node of the list.\n\nAfter we added the \"head node\" of the list, we can start to add the \"next nodes\" in the list by using the `insertAfter()` method\nfrom the `SinglyLinkedList.Node` type, which, in our case here, is accessible through the `node` member of our\n`NodeU32` type. Thus, we can start to create the connections between the nodes by calling this method from the node objects\nthat are present in the list. Like in this example below:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nlist.prepend(&two.node); // {2}\ntwo.node.insertAfter(&five.node); // {2, 5}\ntwo.node.insertAfter(&three.node); // {2, 3, 5}\n```\n:::\n\n\nYou can also call the `prepend()` method again to add new nodes to the beginning of the linked list, which\nmeans, effectively, changing the \"head node\" of the list, like this:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nlist.prepend(&one.node); // {1, 2, 3, 5}\n```\n:::\n\n\n\nThere are other methods available from the singly linked list object that you might be interested. You can find a\nsummary of them in the bullet points below:\n\n- `remove()` to remove a specific node from the linked list.\n- `len()` to count how many nodes there is in the linked list.\n- `popFirst()` to remove the first node (i.e., the \"head\") from the linked list.\n\nSo, that is how singly linked lists work in Zig in a nutshell. To sum up what we have exposed here,\nthis is all the source code that was exposed in this section inside the single cell:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst NodeU32 = struct {\n data: u32,\n node: std.SinglyLinkedList.Node = .{},\n};\n\nvar list: std.SinglyLinkedList = .{};\nvar one: NodeU32 = .{ .data = 1 };\nvar two: NodeU32 = .{ .data = 2 };\nvar three: NodeU32 = .{ .data = 3 };\nvar five: NodeU32 = .{ .data = 5 };\n\nlist.prepend(&two.node); // {2}\ntwo.node.insertAfter(&five.node); // {2, 5}\ntwo.node.insertAfter(&three.node); // {2, 3, 5}\nlist.prepend(&one.node); // {1, 2, 3, 5}\n\ntry stdout.print(\"Number of nodes: {}\", .{list.len()});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nNumber of nodes: 4\n```\n\n\n:::\n:::\n\n\n\n## Multi array structure\n\nZig introduces a new data structure called `MultiArrayList()`. It's a different version of the dynamic array\nthat we have introduced in @sec-dynamic-array. The difference between this structure and the `ArrayList()`\nthat we know from @sec-dynamic-array, is that `MultiArrayList()` creates a separate dynamic array\nfor each field of the struct that you provide as input.\n\nConsider the following code example. We create a new custom struct called `Person`. This\nstruct contains three different data members, or, three different fields. As consequence,\nwhen we provide this `Person` data type as input to `MultiArrayList()`, this\ncreates a \"struct of three different arrays\" called `PersonArray`. In other words,\nthis `PersonArray` is a struct that contains three internal dynamic arrays in it.\nOne array for each field found in the `Person` struct definition.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Person = struct {\n name: []const u8,\n age: u8,\n height: f32,\n};\nconst PersonArray = std.MultiArrayList(Person);\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var people = PersonArray{};\n defer people.deinit(allocator);\n\n try people.append(allocator, .{\n .name = \"Auguste\", .age = 15, .height = 1.54\n });\n try people.append(allocator, .{\n .name = \"Elena\", .age = 26, .height = 1.65\n });\n try people.append(allocator, .{\n .name = \"Michael\", .age = 64, .height = 1.87\n });\n}\n```\n:::\n\n\nIn other words, instead of creating an array of \"persons\", the `MultiArrayList()` function\ncreates a \"struct of arrays\". Each data member of this struct is a different array that stores\nthe values of a specific field from the `Person` values that were added (or, appended) to this \"struct of arrays\".\nOne important detail is that each of these separate internal arrays stored inside `PersonArray`\nare dynamic arrays. This means that these arrays can grow in capacity automatically as needed, to accomodate\nmore values.\n\nThe @fig-multi-array exposed below presents a diagram that describes the `PersonArray` struct\nthat we have created in the previous code example. Notice that the values of the data members\npresent in each of the three `Person` values that we have appended into the `PersonArray` object\n, are scattered across three different internal arrays of the `PersonArray` object.\n\n![A diagram of the `PersonArray` struct.](./../Figures/multi-array.png){#fig-multi-array}\n\nYou can easily access each of these arrays separately, and iterate over the values of each array.\nFor that, you will need to call the `items()` method from the `PersonArray` object, and provide as input\nto this method, the name of the field that you want to iterate over.\nIf you want to iterate through the `.age` array for example, then, you need to call `items(.age)` from\nthe `PersonArray` object, like in the example below:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (people.items(.age)) |*age| {\n try stdout.print(\"Age: {d}\\n\", .{age.*});\n}\n```\n:::\n\n\n```\nAge: 15\nAge: 26\nAge: 64\n```\n\n\nIn the above example, we are iterating over the values of the `.age` array, or,\nthe internal array of the `PersonArray` object that contains the values of the `age`\ndata member from the `Person` values that were added to the multi array struct.\n\nIn this example we are calling the `items()` method directly from the `PersonArray`\nobject. However, in most situations it's recommened to call this `items()` method\nfrom a \"slice object\", which you can create from the `slice()` method.\nThe reason for this is that calling `items()` multiple times have better performance\nif you use a slice object.\n\nTherefore, if you are planning to access only one of the\ninternal arrays from your \"multi array struct\", it's fine to call `items()` directly\nfrom the multi array object. But if you need to access many of the internal arrays\nfrom your \"multi array struct\", then, you will likely need to call `items()` more\nthan once, and, in such circumstance, is better to call `items()` through a slice object.\nThe example below demonstrates the use of such object:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar slice = people.slice();\nfor (slice.items(.age)) |*age| {\n age.* += 10;\n}\nfor (slice.items(.name), slice.items(.age)) |*n,*a| {\n try stdout.print(\n \"Name: {s}, Age: {d}\\n\", .{n.*, a.*}\n );\n}\n```\n:::\n\n\n```\nName: Auguste, Age: 25\nName: Elena, Age: 36\nName: Michael, Age: 74\n```\n\n\n## Conclusion\n\nThere are many other data structures that I haven't presented here.\nBut you can check them out at the official Zig Standard Library documentation page.\nActually, when you get into the [homepage of the documentation](https://ziglang.org/documentation/master/std/#)[^home], the first thing\nthat appears to you in this page, is a list of types and data structures that\nare available in the Zig Standard Library.\nThere are some very specific data structures in this list, like a\n[`BoundedArray` struct](https://ziglang.org/documentation/master/std/#std.bounded_array.BoundedArray)[^bounded]\n, but there is also some more general structures, such as a\n[`PriorityQueue` struct](https://ziglang.org/documentation/master/std/#std.priority_queue.PriorityQueue)[^priority].\n\n\n[^home]: \n[^priority]: .\n[^bounded]: \n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/docs/Chapters/09-data-structures.html b/docs/Chapters/09-data-structures.html index 5f70ae35..4cf9c0a3 100644 --- a/docs/Chapters/09-data-structures.html +++ b/docs/Chapters/09-data-structures.html @@ -345,7 +345,11 @@

    Table of contents

  • 11.2.5 The StringHashMap hashtable
  • 11.2.6 The StringArrayHashMap hashtable
  • -
  • 11.3 Linked lists
  • +
  • 11.3 Linked lists +
  • 11.4 Multi array structure
  • 11.5 Conclusion
  • @@ -685,7 +689,8 @@

    11.3 Linked lists

    -

    The Zig Standard Library provides an implementation for both singly and doubly linked lists. A linked list is a linear data structure that looks like a chain, or, a rope. The main advantage of this data structure is that you normally have very fast insertion and deletion operations. But, as a disadvantage, iterating through this data structure is usually not so fast as iterating through an array.

    +

    The Zig Standard Library provides an implementation for both singly and doubly linked lists. More specifically, through the structs SinglyLinkedList and DoublyLinkedList.

    +

    In case you are not familiar with these data structures, a linked list is a linear data structure that looks like a chain, or, a rope. The main advantage of this data structure is that you normally have very fast insertion and deletion operations. But, as a disadvantage, iterating through this data structure is usually not so fast as iterating through an array.

    The idea behind a linked list is to build a structure that consists of a sequence of nodes connected to each other by pointers. This means that linked lists are usually not contiguous in memory, because each node might be anywhere in memory. They do not need to be close to one another.

    In Figure 11.3 we can see a diagram of a singly linked list. We begin at the first node (which is usually called “the head of the linked list”). Then, from this first node we uncover the remaining nodes in the structure, by following the locations pointed by the pointers found in each node.

    Each node has two things in it. It has the value that is stored in the current node , and also, a pointer. This pointer points to the next node in the list. If this pointer is null, then, it means that we have reached the end of our linked list.

    @@ -711,75 +716,106 @@

    -

    Linked lists are available in Zig through the functions SinglyLinkedList() and DoublyLinkedList(), for “singly linked lists” and “doubly linked lists”, respectively. These functions are actually generic functions, which we are going to talk more about in Section 12.2.1.

    -

    For now, just understand that, in order to create a linked list object, we begin by providing a data type to these functions. This data type defines the type of data that each node in this linked list will store. In the example below, we are creating a singly linked list of u32 values. So each node in this linked list will store a u32 value.

    -

    Both the SinglyLinkedList() and DoublyLinkedList() functions returns a type, i.e., a struct definition, as output. Therefore, the object Lu32 is actually a struct definition. It defines the type “singly linked list of u32 values”.

    -

    Now that we have the definition of the struct, we need to instantiate a Lu32 object. We normally instantiate struct objects in Zig by using an init() method. But in this case, we are instantiating the struct directly, by using an empty struct literal, in the expression Lu32{}.

    -

    In this example, we first create multiple node objects, and after we create them, we start to insert and connect these nodes to build the linked list, using the prepend() and insertAfter() methods. Notice that the prepend() method is a method from the linked list object, while the insertAfter() is a method present in the node objects.

    -

    In essence, the prepend() method inserts a node at the beginning of the linked list. In other words, the node that you provide to this method, becomes the new “head node” of the linked list. It becomes the first node in the list (see Figure 11.3).

    -

    On the other side, the insertAfter() method is used to basically connect two nodes together. When you provide a node to this method, it creates a pointer to this input node, and stores this pointer in the next attribute of the current node, from which the method was called from.

    -

    Because doubly linked lists have both a next and a prev attributes in each node (as described in Figure 11.4), a node object created from a DoublyLinkedList object have both an insertBefore() (for prev) and an insertAfter() (for next) methods available.

    -

    Thus, if we have used a doubly linked list, we can use the insertBefore() method to store the pointer to the input node in the prev attribute. This would put the input node as the “previous node”, or, the node before the current node. In contrast, the insertAfter() method puts the pointer created to the input node in the next attribute of the current node, and as result, the input node becomes the “next node” of the current node.

    -

    Since we are using a singly linked list in this example, we have only the insertAfter() method available in the node objects that we create from our Lu32 type.

    +
    +

    11.3.1 Recent change in the API

    +

    On previous versions of Zig, the SinglyLinkedList and DoublyLinkedList structs were initially implemented as “generics data structures”. Meaning that, you would use a generic function to create a singly (or doubly) linked list that could store the specific data type that you wanted to use. We will learn more about generics at Section 12.2, and also, how we can create a “generic data structure” at Section 12.2.2.

    +

    However, on the latest versions of Zig, the structs SinglyLinkedList and DoublyLinkedList were altered to use a “less generic API”. This specific change was introduced on April 3, 2025. Therefore, check if your Zig version is one released after this date. Just have in mind that if you don’t have a very recent version of the Zig compiler, you might have problems while trying to compile the next examples exposed here.

    +
    +
    +

    11.3.2 How to use a singly linked list

    +

    For example, consider that you are creating a singly linked list that is going to store u32 values. Given this scenario, the first thing that we need to do, is to create a “node type” that is capable of storing a u32 value. The NodeU32 type exposed below demonstrates such “node type”.

    +

    Notice that the data type associated with the member named data is the most important part of this custom “node type”. It determines the data type that is going to be stored in each node.

    const std = @import("std");
    -const SinglyLinkedList = std.SinglyLinkedList;
    -const Lu32 = SinglyLinkedList(u32);
    -
    -pub fn main() !void {
    -    var list = Lu32{};
    -    var one = Lu32.Node{ .data = 1 };
    -    var two = Lu32.Node{ .data = 2 };
    -    var three = Lu32.Node{ .data = 3 };
    -    var four = Lu32.Node{ .data = 4 };
    -    var five = Lu32.Node{ .data = 5 };
    -
    -    list.prepend(&two); // {2}
    -    two.insertAfter(&five); // {2, 5}
    -    list.prepend(&one); // {1, 2, 5}
    -    two.insertAfter(&three); // {1, 2, 3, 5}
    -    three.insertAfter(&four); // {1, 2, 3, 4, 5}
    -}
    + +const NodeU32 = struct { + data: u32, + node: std.SinglyLinkedList.Node = .{}, +};
    + +

    After we created our custom “node type” that can store the specific data type that we want, we can just create a new and empty singly linked list, which will store our nodes. To do that, we just create a new object with the type SinglyLinkedList, like this:

    +
    +
    var list: std.SinglyLinkedList = .{};
    +
    +

    Now, we have our linked list… But how can we insert nodes in it? Well, first of all, we need to create our nodes. So let’s focus on that first. The snippet exposed below demonstrates how we could use our NodeU32 struct to create such nodes.

    +

    Notice in this snippet that we are just setting the data member of the struct for now. We don’t need to connect these nodes together in this first instance. This is why we ignore the node member at first. But we are going to connect these nodes in a future point of the code, which is why these objects are marked as “variable objects”, so that we can alter them in the future.

    +
    +
    var one: NodeU32 = .{ .data = 1 };
    +var two: NodeU32 = .{ .data = 2 };
    +var three: NodeU32 = .{ .data = 3 };
    +var five: NodeU32 = .{ .data = 5 };
    -

    There are other methods available from the linked list object, depending if this object is a singly linked list or a doubly linked list, that might be very useful for you. You can find a summary of them in the bullet points below:

    +

    Now that we have both the linked list and also the nodes created, we can start to connect them together. You can use the prepend() method from the linked list object to insert the first node in the list, which is the “head” of the linked list. As the name suggests, this specific method prepends the input node to the linked list, or, in other words, it transforms the input node into the first node of the list.

    +

    After we added the “head node” of the list, we can start to add the “next nodes” in the list by using the insertAfter() method from the SinglyLinkedList.Node type, which, in our case here, is accessible through the node member of our NodeU32 type. Thus, we can start to create the connections between the nodes by calling this method from the node objects that are present in the list. Like in this example below:

    +
    +
    list.prepend(&two.node); // {2}
    +two.node.insertAfter(&five.node); // {2, 5}
    +two.node.insertAfter(&three.node); // {2, 3, 5}
    +
    +

    You can also call the prepend() method again to add new nodes to the beginning of the linked list, which means, effectively, changing the “head node” of the list, like this:

    +
    +
    list.prepend(&one.node); // {1, 2, 3, 5}
    +
    +

    There are other methods available from the singly linked list object that you might be interested. You can find a summary of them in the bullet points below:

    • remove() to remove a specific node from the linked list.
    • -
    • if singly linked list, len() to count how many nodes there is in the linked list.
    • -
    • if doubly linked list, checkout the len attribute to see how many nodes there is in the linked list.
    • -
    • if singly linked list, popFirst() to remove the first node (i.e., the “head”) from the linked list.
    • -
    • if doubly linked list, pop() and popFirst() to remove the last and first nodes from the linked list, respectively.
    • -
    • if doubly linked list, append() to add a new node to end of the linked list (i.e., inverse of prepend()).
    • +
    • len() to count how many nodes there is in the linked list.
    • +
    • popFirst() to remove the first node (i.e., the “head”) from the linked list.
    +

    So, that is how singly linked lists work in Zig in a nutshell. To sum up what we have exposed here, this is all the source code that was exposed in this section inside the single cell:

    +
    +
    const NodeU32 = struct {
    +    data: u32,
    +    node: std.SinglyLinkedList.Node = .{},
    +};
    +
    +var list: std.SinglyLinkedList = .{};
    +var one: NodeU32 = .{ .data = 1 };
    +var two: NodeU32 = .{ .data = 2 };
    +var three: NodeU32 = .{ .data = 3 };
    +var five: NodeU32 = .{ .data = 5 };
    +
    +list.prepend(&two.node); // {2}
    +two.node.insertAfter(&five.node); // {2, 5}
    +two.node.insertAfter(&three.node); // {2, 3, 5}
    +list.prepend(&one.node); // {1, 2, 3, 5}
    +
    +try stdout.print("Number of nodes: {}", .{list.len()});
    +
    +
    Number of nodes: 4
    +
    +
    +

    11.4 Multi array structure

    Zig introduces a new data structure called MultiArrayList(). It’s a different version of the dynamic array that we have introduced in Section 11.1. The difference between this structure and the ArrayList() that we know from Section 11.1, is that MultiArrayList() creates a separate dynamic array for each field of the struct that you provide as input.

    Consider the following code example. We create a new custom struct called Person. This struct contains three different data members, or, three different fields. As consequence, when we provide this Person data type as input to MultiArrayList(), this creates a “struct of three different arrays” called PersonArray. In other words, this PersonArray is a struct that contains three internal dynamic arrays in it. One array for each field found in the Person struct definition.

    -
    const std = @import("std");
    -const Person = struct {
    -    name: []const u8,
    -    age: u8,
    -    height: f32,
    -};
    -const PersonArray = std.MultiArrayList(Person);
    -
    -pub fn main() !void {
    -    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    -    const allocator = gpa.allocator();
    -    var people = PersonArray{};
    -    defer people.deinit(allocator);
    -
    -    try people.append(allocator, .{
    -        .name = "Auguste", .age = 15, .height = 1.54
    -    });
    -    try people.append(allocator, .{
    -        .name = "Elena", .age = 26, .height = 1.65
    -    });
    -    try people.append(allocator, .{
    -        .name = "Michael", .age = 64, .height = 1.87
    -    });
    -}
    +
    const std = @import("std");
    +const Person = struct {
    +    name: []const u8,
    +    age: u8,
    +    height: f32,
    +};
    +const PersonArray = std.MultiArrayList(Person);
    +
    +pub fn main() !void {
    +    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    +    const allocator = gpa.allocator();
    +    var people = PersonArray{};
    +    defer people.deinit(allocator);
    +
    +    try people.append(allocator, .{
    +        .name = "Auguste", .age = 15, .height = 1.54
    +    });
    +    try people.append(allocator, .{
    +        .name = "Elena", .age = 26, .height = 1.65
    +    });
    +    try people.append(allocator, .{
    +        .name = "Michael", .age = 64, .height = 1.87
    +    });
    +}

    In other words, instead of creating an array of “persons”, the MultiArrayList() function creates a “struct of arrays”. Each data member of this struct is a different array that stores the values of a specific field from the Person values that were added (or, appended) to this “struct of arrays”. One important detail is that each of these separate internal arrays stored inside PersonArray are dynamic arrays. This means that these arrays can grow in capacity automatically as needed, to accomodate more values.

    The Figure 11.5 exposed below presents a diagram that describes the PersonArray struct that we have created in the previous code example. Notice that the values of the data members present in each of the three Person values that we have appended into the PersonArray object , are scattered across three different internal arrays of the PersonArray object.

    @@ -795,9 +831,9 @@

    <

    You can easily access each of these arrays separately, and iterate over the values of each array. For that, you will need to call the items() method from the PersonArray object, and provide as input to this method, the name of the field that you want to iterate over. If you want to iterate through the .age array for example, then, you need to call items(.age) from the PersonArray object, like in the example below:

    -
    for (people.items(.age)) |*age| {
    -    try stdout.print("Age: {d}\n", .{age.*});
    -}
    +
    for (people.items(.age)) |*age| {
    +    try stdout.print("Age: {d}\n", .{age.*});
    +}
    Age: 15
     Age: 26
    @@ -806,15 +842,15 @@ 

    <

    In this example we are calling the items() method directly from the PersonArray object. However, in most situations it’s recommened to call this items() method from a “slice object”, which you can create from the slice() method. The reason for this is that calling items() multiple times have better performance if you use a slice object.

    Therefore, if you are planning to access only one of the internal arrays from your “multi array struct”, it’s fine to call items() directly from the multi array object. But if you need to access many of the internal arrays from your “multi array struct”, then, you will likely need to call items() more than once, and, in such circumstance, is better to call items() through a slice object. The example below demonstrates the use of such object:

    -
    var slice = people.slice();
    -for (slice.items(.age)) |*age| {
    -    age.* += 10;
    -}
    -for (slice.items(.name), slice.items(.age)) |*n,*a| {
    -    try stdout.print(
    -        "Name: {s}, Age: {d}\n", .{n.*, a.*}
    -    );
    -}
    +
    var slice = people.slice();
    +for (slice.items(.age)) |*age| {
    +    age.* += 10;
    +}
    +for (slice.items(.name), slice.items(.age)) |*n,*a| {
    +    try stdout.print(
    +        "Name: {s}, Age: {d}\n", .{n.*, a.*}
    +    );
    +}
    Name: Auguste, Age: 25
     Name: Elena, Age: 36
    diff --git a/docs/index.html b/docs/index.html
    index be6ab3c0..6a8a4913 100644
    --- a/docs/index.html
    +++ b/docs/index.html
    @@ -7,7 +7,7 @@
     
     
     
    -
    +
     
     Introduction to Zig
     \n\n\n\n    \n\n\n\n\n\n\n    \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n  \n  \n  \n      \n  \n  \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n  \n  \n  \n      \n  \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Senior Data Engineer at [DSM-Firmenich](https://www.dsm-firmenich.com)[^dsm], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^dsm]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n- System version: Linux, 6.12.21-4-MANJARO, NA, x86_64.\n- Zig version: 0.15.0-dev.635+7dbd21bd5.\n- Quarto version: 1.4.554.\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n    author = {Pedro Duarte Faria},\n    title = {Introduction to Zig},\n    subtitle = {a project-based book},\n    month = {October},\n    edition = {1},\n    year = {2024},\n    address = {Belo Horizonte},\n    url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion), glystik (\\@glystik), Michael Lynch (\\@mtlynch), Yashank (\\@stickyburn), _blf_ (\\@bengtfrost)\n",
    +    "supporting": [
    +      "index_files"
    +    ],
    +    "filters": [
    +      "rmarkdown/pagebreak.lua"
    +    ],
    +    "includes": {},
    +    "engineDependencies": {
    +      "knitr": [
    +        "{\"type\":\"list\",\"attributes\":{},\"value\":[]}"
    +      ]
    +    },
    +    "preserve": null,
    +    "postProcess": false
    +  }
    +}
    \ No newline at end of file
    diff --git a/_freeze/references/execute-results/epub.json b/_freeze/references/execute-results/epub.json
    new file mode 100644
    index 00000000..eb15b841
    --- /dev/null
    +++ b/_freeze/references/execute-results/epub.json
    @@ -0,0 +1,21 @@
    +{
    +  "hash": "b3fb07f33430db017c1afb683e34205a",
    +  "result": {
    +    "engine": "knitr",
    +    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n::::: {.content-visible when-format=\"html\"}\n\n# References {.unnumbered}\n\n::: {#refs}\n:::\n\n:::::\n",
    +    "supporting": [
    +      "references_files"
    +    ],
    +    "filters": [
    +      "rmarkdown/pagebreak.lua"
    +    ],
    +    "includes": {},
    +    "engineDependencies": {
    +      "knitr": [
    +        "{\"type\":\"list\",\"attributes\":{},\"value\":[]}"
    +      ]
    +    },
    +    "preserve": null,
    +    "postProcess": false
    +  }
    +}
    \ No newline at end of file
    
    From 8a4289d99b1aee75b559328af54ab4c9bd6a7d40 Mon Sep 17 00:00:00 2001
    From: Pedro Faria <69123925+pedropark99@users.noreply.github.com>
    Date: Tue, 27 May 2025 18:24:36 -0300
    Subject: [PATCH 142/151] Update README.md
    
    ---
     README.md | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/README.md b/README.md
    index 249cc212..ab93cf22 100644
    --- a/README.md
    +++ b/README.md
    @@ -150,7 +150,7 @@ to open a terminal, and run the `nix develop` command on the root of the project
     nix develop
     ```
     
    -With this command, Onix will download the necessary packages and libraries, and then create a new bash session that points
    +With this command, Nix will download the necessary packages and libraries, and then create a new bash session that points
     to a new environment that contains these packages and libraries in it. Then, inside this new bash session that is created
     by Nix, all you need to do is to run the `quarto render` command, which will kickstart Quarto, and make it build the book
     for you:
    
    From 332e3b0138cf66612123425d1b51a69d33dd8d95 Mon Sep 17 00:00:00 2001
    From: pedropark99 
    Date: Wed, 28 May 2025 17:22:14 -0300
    Subject: [PATCH 143/151] Compare zig defer with go defer
    
    ---
     Chapters/03-structs.qmd                       | 19 ++++++++++++++---
     Chapters/05-pointers.qmd                      |  7 ++++---
     .../01-base64/execute-results/epub.json       | 21 -------------------
     .../01-base64/execute-results/html.json       |  6 ++----
     .../01-memory/execute-results/epub.json       | 21 -------------------
     .../01-memory/execute-results/html.json       |  6 ++----
     .../01-zig-weird/execute-results/epub.json    | 21 -------------------
     .../01-zig-weird/execute-results/html.json    |  2 +-
     .../02-debugging/execute-results/epub.json    | 21 -------------------
     .../02-debugging/execute-results/html.json    |  6 ++----
     .../03-structs/execute-results/epub.json      | 21 -------------------
     .../03-structs/execute-results/html.json      |  4 ++--
     .../03-unittests/execute-results/epub.json    | 21 -------------------
     .../03-unittests/execute-results/html.json    |  6 ++----
     .../04-http-server/execute-results/epub.json  | 21 -------------------
     .../04-http-server/execute-results/html.json  |  6 ++----
     .../05-pointers/execute-results/html.json     |  4 ++--
     .../07-build-system/execute-results/epub.json | 21 -------------------
     .../07-build-system/execute-results/html.json |  6 ++----
     .../execute-results/epub.json                 | 21 -------------------
     .../execute-results/epub.json                 | 21 -------------------
     .../execute-results/html.json                 |  6 ++----
     .../execute-results/epub.json                 | 21 -------------------
     .../execute-results/html.json                 |  2 +-
     .../12-file-op/execute-results/epub.json      | 21 -------------------
     .../12-file-op/execute-results/html.json      |  6 ++----
     .../13-image-filter/execute-results/epub.json | 21 -------------------
     .../13-image-filter/execute-results/html.json |  6 ++----
     .../14-threads/execute-results/epub.json      | 21 -------------------
     .../14-threads/execute-results/html.json      |  6 ++----
     .../execute-results/epub.json                 | 21 -------------------
     .../execute-results/html.json                 |  6 ++----
     .../15-vectors/execute-results/epub.json      | 21 -------------------
     .../15-vectors/execute-results/html.json      |  6 ++----
     _freeze/index/execute-results/epub.json       | 21 -------------------
     _freeze/index/execute-results/html.json       |  4 ++--
     _freeze/references/execute-results/epub.json  | 21 -------------------
     _freeze/references/execute-results/html.json  |  2 +-
     _quarto.yml                                   |  5 ++++-
     docs/Chapters/03-structs.html                 | 11 ++++++----
     docs/Chapters/03-unittests.html               |  8 +++----
     docs/Chapters/05-pointers.html                |  4 ++--
     docs/Chapters/09-error-handling.html          |  2 +-
     docs/Chapters/10-stack-project.html           |  6 +++---
     docs/index.html                               |  4 ++--
     docs/search.json                              | 16 +++++++-------
     index.qmd                                     |  4 +++-
     47 files changed, 87 insertions(+), 467 deletions(-)
     delete mode 100644 _freeze/Chapters/01-base64/execute-results/epub.json
     delete mode 100644 _freeze/Chapters/01-memory/execute-results/epub.json
     delete mode 100644 _freeze/Chapters/01-zig-weird/execute-results/epub.json
     delete mode 100644 _freeze/Chapters/02-debugging/execute-results/epub.json
     delete mode 100644 _freeze/Chapters/03-structs/execute-results/epub.json
     delete mode 100644 _freeze/Chapters/03-unittests/execute-results/epub.json
     delete mode 100644 _freeze/Chapters/04-http-server/execute-results/epub.json
     delete mode 100644 _freeze/Chapters/07-build-system/execute-results/epub.json
     delete mode 100644 _freeze/Chapters/09-data-structures/execute-results/epub.json
     delete mode 100644 _freeze/Chapters/09-error-handling/execute-results/epub.json
     delete mode 100644 _freeze/Chapters/10-stack-project/execute-results/epub.json
     delete mode 100644 _freeze/Chapters/12-file-op/execute-results/epub.json
     delete mode 100644 _freeze/Chapters/13-image-filter/execute-results/epub.json
     delete mode 100644 _freeze/Chapters/14-threads/execute-results/epub.json
     delete mode 100644 _freeze/Chapters/14-zig-c-interop/execute-results/epub.json
     delete mode 100644 _freeze/Chapters/15-vectors/execute-results/epub.json
     delete mode 100644 _freeze/index/execute-results/epub.json
     delete mode 100644 _freeze/references/execute-results/epub.json
    
    diff --git a/Chapters/03-structs.qmd b/Chapters/03-structs.qmd
    index 56c67e00..3c1676e4 100644
    --- a/Chapters/03-structs.qmd
    +++ b/Chapters/03-structs.qmd
    @@ -301,9 +301,22 @@ xsw: switch (@as(u8, 1)) {
     
     ### The `defer` keyword {#sec-defer}
     
    -With the `defer` keyword you can register an expression to be executed when you exit the current scope.
    -Therefore, this keyword has a similar functionality as the `on.exit()` function from R.
    -Take the `foo()` function below as an example. When we execute this `foo()` function, the expression
    +Zig has a `defer` keyword, which plays a very important role in control flow, and also, in releasing resources.
    +In summary, the `defer` keyword allows you to register an expression to be executed when you exit the current scope.
    +
    +At this point, you might attempt to compare the Zig `defer` keyword to it's sibling in the Go language
    +(i.e. [Go also has a `defer` keyword](https://go.dev/tour/flowcontrol/12)).
    +However, the Go `defer` keyword behaves slightly different
    +than it's sibling in Zig. More specifically, the `defer` keyword in Go always move an expression to be
    +executed at the **exit of the current function**.
    +
    +If you think deeply about this statement, you will notice that the "exit of the current function" is something
    +slightly different than the "exit of the current scope". So, just be careful when comparing the two
    +keywords together. A single function in Zig might contain many different scopes inside of it, and, therefore,
    +the `defer` input expression might be executed at different places of the function, depending on which scope you
    +are currently in.
    +
    +As a first example, consider the `foo()` function exposed below. When we execute this `foo()` function, the expression
     that prints the message "Exiting function ..." is getting executed only when the function exits
     its scope.
     
    diff --git a/Chapters/05-pointers.qmd b/Chapters/05-pointers.qmd
    index f75cbe85..f82966d0 100644
    --- a/Chapters/05-pointers.qmd
    +++ b/Chapters/05-pointers.qmd
    @@ -307,7 +307,7 @@ might point to a null value. This is a common source of undefined behaviour in C
     When programmers work with pointers in C, they have to constantly check if
     their pointers are pointing to null values or not.
     
    -If for some reason, your Zig code produces a null value somewhere, and, this null
    +In contrast, when working in Zig, if for some reason, your Zig code produces a null value somewhere, and, this null
     value ends up in an object that is non-nullable, a runtime error is always
     raised by your Zig program. Take the program below as an example.
     The `zig` compiler can see the `null` value at compile time, and, as result,
    @@ -347,8 +347,9 @@ Ok, we know now that all objects are non-nullable by default in Zig.
     But what if we actually need to use an object that might receive a null value?
     Here is where optionals come in.
     
    -An optional object in Zig is an object that can be null.
    -To mark an object as optional, we use the `?` operator. When you put
    +An optional object in Zig is rather similar to a [`std::optional` object in C++](https://en.cppreference.com/w/cpp/utility/optional.html).
    +It is an object that can either contain a value, or nothing at all (a.k.a. the object can be null).
    +To mark an object in our Zig code as "optional", we use the `?` operator. When you put
     this `?` operator right before the data type of an object, you transform
     this data type into an optional data type, and the object becomes an optional object.
     
    diff --git a/_freeze/Chapters/01-base64/execute-results/epub.json b/_freeze/Chapters/01-base64/execute-results/epub.json
    deleted file mode 100644
    index 7dbf61d0..00000000
    --- a/_freeze/Chapters/01-base64/execute-results/epub.json
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -{
    -  "hash": "378ceb7f207e1c24d8ca75cf94cd22bf",
    -  "result": {
    -    "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n# Project 1 - Building a base64 encoder/decoder {#sec-base64}\n\nAs our first small project, I want to implement a base64 encoder/decoder with you.\nBase64 is an encoding system which translates binary data to text.\nA big chunk of the web uses base64 to deliver binary data to systems\nthat can only read text data.\n\nThe most common example of a modern use case for base64 is essentially any email system,\nlike GMail, Outlook, etc. Because email systems normally use\nthe Simple Mail Transfer Protocol (SMTP), which is a web protocol\nthat supports only text data. So, if you need, for any reason, to\nsend a binary file (like for example, a PDF, or an Excel file) as\nan attachment in your email, these binary files are normally\nconverted to base64, before they are included in the SMTP message.\nSo, the base64 encoding is largely used in these email systems to include\nbinary data into the SMTP message.\n\n\n\n\n\n\n## How the base64 algorithm work?\n\nBut how exactly does the algorithm behind the base64 encoding work? Let's discuss that. First, I will\nexplain the base64 scale, which is the 64-character scale that is the basis for\nthe base64 encoding system.\n\nAfter that, I explain the algorithm behind a base64 encoder, which is the part of the algorithm that is responsible for encoding messages\ninto the base64 encoding system. Then, after that, I explain the algorithm behind a base64 decoder, which is\nthe part of the algorithm that is responsible for translating base64 messages back into their original meaning.\n\nIf you are unsure about the differences between an \"encoder\" and a \"decoder\",\ntake a look at @sec-encode-vs-decode.\n\n\n### The base64 scale {#sec-base64-scale}\n\nThe base64 encoding system is based on a scale that goes from 0 to 63 (hence the name).\nEach index in this scale is represented by a character (it's a scale of 64 characters).\nSo, in order to convert some binary data, to the base64 encoding, we need to convert each binary number to the corresponding\ncharacter in this \"scale of 64 characters\".\n\nThe base64 scale starts with all ASCII uppercase letters (A to Z) which represents\nthe first 25 indexes in this scale (0 to 25). After that, we have all ASCII lowercase letters\n(a to z), which represents the range 26 to 51 in the scale. After that, we\nhave the one digit numbers (0 to 9), which represents the indexes from 52 to 61 in the scale.\nFinally, the last two indexes in the scale (62 and 63) are represented by the characters `+` and `/`,\nrespectively.\n\nThese are the 64 characters that compose the base64 scale. The equal sign character (`=`) is not part of the scale itself,\nbut it is a special character in the base64 encoding system. This character is used solely as a suffix, to mark the end of the character sequence,\nor, to mark the end of meaningful characters in the sequence.\n\nThe bullet points below summarises the base64 scale:\n\n- range 0 to 25 is represented by: ASCII uppercase letters `-> [A-Z]`;\n- range 26 to 51 is represented by: ASCII lowercase letters `-> [a-z]`;\n- range 52 to 61 is represented by: one digit numbers `-> [0-9]`;\n- index 62 and 63 are represented by the characters `+` and `/`, respectively;\n- the character `=` represents the end of meaningful characters in the sequence;\n\n\n\n\n### Creating the scale as a lookup table {#sec-base64-table}\n\nThe best way to represent this scale in code, is to represent it as a *lookup table*.\nLookup tables are a classic strategy in computer science to speed up calculations. The basic idea\nis to replace a runtime calculation (which can take a long time to be done) with a basic array indexing\noperation.\n\nInstead of calculating the results everytime you need them, you calculate all possible results at once, and then, you store them in an array\n(which behaves lake a \"table\"). Then, every time you need to use one of the characters in the base64 scale, instead of\nusing many resources to calculate the exact character to be used, you simply retrieve this character\nfrom the array where you stored all the possible characters in the base64 scale.\nWe retrieve the character that we need directly from memory.\n\nWe can start building a Zig struct to store our base64 decoder/encoder logic.\nWe start with the `Base64` struct below. For now, we only have one single data member in this\nstruct, i.e., the member `_table`, which represents our lookup table. We also have an `init()` method,\nto create a new instance of a `Base64` object, and, a `_char_at()` method, which is a\n\"get character at index $x$\" type of function.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Base64 = struct {\n    _table: *const [64]u8,\n\n    pub fn init() Base64 {\n        const upper = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n        const lower = \"abcdefghijklmnopqrstuvwxyz\";\n        const numbers_symb = \"0123456789+/\";\n        return Base64{\n            ._table = upper ++ lower ++ numbers_symb,\n        };\n    }\n\n    pub fn _char_at(self: Base64, index: usize) u8 {\n        return self._table[index];\n    }\n};\n```\n:::\n\n\n\n\nIn other words, the `_char_at()` method is responsible for getting the character in the lookup\ntable (i.e., the `_table` struct data member) that corresponds to a particular index in the\n\"base64 scale\". So, in the example below, we know that the character that corresponds to the\nindex 28 in the \"base64 scale\" is the character \"c\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst base64 = Base64.init();\ntry stdout.print(\n    \"Character at index 28: {c}\\n\",\n    .{base64._char_at(28)}\n);\n```\n:::\n\n\n\n```\nCharacter at index 28: c\n```\n\n\n\n### A base64 encoder {#sec-base64-encoder-algo}\n\nThe algorithm behind a base64 encoder usually works on a window of 3 bytes. Because each byte has\n8 bits, so, 3 bytes forms a set of $8 \\times 3 = 24$ bits. This is desirable for the base64 algorithm, because\n24 bits is divisible by 6, which forms $24 / 6 = 4$ groups of 6 bits each.\n\nTherefore, the base64 algorithm works by converting 3 bytes at a time\ninto 4 characters from the base64 scale. It keeps iterating through the input string,\n3 bytes at a time, and converting them into the base64 scale, producing 4 characters\nper iteration. It keeps iterating, and producing these \"new characters\"\nuntil it hits the end of the input string.\n\nNow you may think, what if you have a particular string that has a number of bytes\nthat is not divisible by 3 - what happens? For example, if you have a string\nthat contains only two characters/bytes, such as \"Hi\". How would the algorithm\nbehave in such situation? You find the answer in @fig-base64-algo1.\nYou can see in @fig-base64-algo1 that the string \"Hi\", when converted to base64,\nbecomes the string \"SGk=\":\n\n![The logic behind a base64 encoder](./../Figures/base64-encoder-flow.png){#fig-base64-algo1}\n\nTaking the string \"Hi\" as an example, we have 2 bytes, or, 16 bits in total. So, we lack a full byte (8 bits)\nto complete the window of 24 bits that the base64 algorithm likes to work on. The first thing that\nthe algorithm does, is to check how to divide the input bytes into groups of 6 bits.\n\nIf the algorithm notices that there is a group of 6 bits that it's not complete, meaning that, this group contains $nbits$, where $0 < nbits < 6$,\n\nthe algorithm simply adds extra zeros in this group to fill the space that it needs.\nThat is why in @fig-base64-algo1, in the third group after the 6-bit transformation,\n2 extra zeros were added to fill the gap.\n\nWhen we have a 6-bit group that is not completely full, like the third group, extra zeros\nare added to fill the gap. But what about when an entire 6-bit group is empty, or, it\nsimply doesn't exist? This is the case of the fourth 6-bit group exposed at\n@fig-base64-algo1.\n\nThis fourth group is necessary, because the algorithm works on 4 groups of 6 bits.\nBut the input string does not have enough bytes to create a fourth 6-bit group.\nEvery time this happens, where an entire group of 6 bits is empty,\nthis group becomes a \"padding group\". Every \"padding group\" is mapped to\nthe character `=` (equal sign), which represents \"null\", or, the end\nof meaningful characters in the sequence. Hence, everytime that the algorithm produces a\n\"padding group\", this group is automatically mapped to `=`.\n\nAs another example, if you give the string \"0\" as input to a base64 encoder, this string is\ntranslated into the base64 sequence \"MA==\".\nThe character \"0\" is, in binary, the sequence `00110000`[^zero-note]. So, with the 6-bit transformation\nexposed in @fig-base64-algo1, this single character would produce these two 6-bit groups: `001100`, `000000`.\nThe remaining two 6-bit groups become \"padding groups\". That is why the last\ntwo characters in the output sequence (MA==) are `==`.\n\n\n[^zero-note]: Notice that, the character \"0\" is different than the actual number 0, which is simply zero in binary.\n\n### A base64 decoder {#sec-base64-decoder-algo}\n\nThe algorithm behind a base64 decoder is essentially the inverse process of a base64 encoder.\nA base64 decoder needs to translate base64 messages back into their original meaning,\ni.e., into the original sequence of binary data.\n\nA base64 decoder usually works on a window of 4 bytes. Because it wants to convert these 4 bytes\nback into the original sequence of 3 bytes, that was converted into 4 groups of 6 bits by the\nbase64 encoder. Remember, in a base64 decoder we are essentially reverting the process made\nby the base64 encoder.\n\nEach byte in the input string (the base64 encoded string) normally contributes to re-create\ntwo different bytes in the output (the original binary data).\nIn other words, each byte that comes out of a base64 decoder is created by transforming merging two different\nbytes in the input together. You can visualize this relationship in @fig-base64-algo2:\n\n![The logic behind a base64 decoder](./../Figures/base64-decoder-flow.png){#fig-base64-algo2}\n\nThe exact transformations, or, the exact steps applied to each byte from the input to transform them\ninto the bytes of the output, are a bit tricky to visualize in a figure like this. Because of that, I have\nsummarized these transformations as \"Some bit shifting and additions ...\" in the figure. These transformations\nwill be described in depth later.\n\nBesides that, if you look again in @fig-base64-algo2, you will notice that the character `=` was completely\nignored by the algorithm. Remember, this is just a special character that marks the end of meaningful characters\nin the base64 sequence. So, every `=` character in a base64 encoded sequence should be ignored by a base64 decoder.\n\n\n## Difference between encode and decode {#sec-encode-vs-decode}\n\nIf you don't have any previous experience with base64, you might not understand the differences\nbetween \"encode\" and \"decode\". Essentially, the terms \"encode\" and \"decode\" here\nhave the exact same meaning as they have in the field of encryption (i.e., they mean the same thing as \"encode\" and \"decode\" in hashing\nalgorithms, like the MD5 algorithm).\n\nThus, \"encode\" means that we want to encode, or, in other words, we want to translate some message into\nthe base64 encoding system. We want to produce the sequence of base64 characters that represent this\noriginal message in the base64 encoding system.\n\nIn contrast, \"decode\" represents the inverse process.\nWe want to decode, or, in other words, translate a base64 message back to its original content.\nSo, in this process we get a sequence of base64 characters as input, and produce as output,\nthe binary data that is represented by this sequence of base64 characters.\n\nAny base64 library is normally composed of these two parts: 1) the encoder, which is a function that encodes\n(i.e., it converts) any sequence of binary data into a sequence of base64 characters; 2) the decoder, which is a function\nthat converts a sequence of base64 characters back into the original sequence of binary data.\n\n\n\n## Calculating the size of the output {#sec-base64-length-out}\n\nOne task that we need to do is to calculate how much space we need to reserve for the\noutput, both of the encoder and decoder. This is simple math, and can be done easily in Zig\nbecause every array has its length (its number of elements) easily accesible by consulting\nthe `.len` property of the array.\n\nFor the encoder, the logic is the following: for each 3 bytes that we find in the input,\n4 new bytes are created in the output. So, we take the number of bytes in the input, divide it\nby 3, use a ceiling function, then, we multiply the result by 4. That way, we get the total\nnumber of bytes that will be produced by the encoder in its output.\n\nThe `_calc_encode_length()` function below encapsulates this logic.\nInside this function, we take the length of the input array,\nwe divide it by 3, and apply a ceil operation over the result by using the\n`divCeil()` function from the Zig Standard Library. Lastly, we multiply\nthe end result by 4 to get the answer we need.\n\nAlso, you might have notice that, if the input length is less than 3 bytes, then, the output length of the encoder is\nalways 4 bytes. This is the case for every input with less than 3 bytes, because, as I described in @sec-base64-encoder-algo,\nthe algorithm always produces enough \"padding-groups\" in the end result, to complete the 4 bytes window.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_encode_length(input: []const u8) !usize {\n    if (input.len < 3) {\n        return 4;\n    }\n    const n_groups: usize = try std.math.divCeil(\n        usize, input.len, 3\n    );\n    return n_groups * 4;\n}\n```\n:::\n\n\n\n\nNow, the logic to calculate the length of the output from the decoder is a little bit more complicated. But, it is basically\njust the inverse logic that we've used for the encoder: for each 4 bytes in the input, 3 bytes\nwill be produced in the output of the decoder. However, this time we need to\ntake the `=` character into account, which is always ignored by the decoder, as we described in @sec-base64-decoder-algo, and,\nin @fig-base64-algo2.\n\nIn essence, we take the length of the input and divide it by 4, then we apply a floor function on the result, then\nwe multiply the result by 3, and then, we subtract from the result how much times the character `=` is found\nin the input.\n\nThe function `_calc_decode_length()` exposed below summarizes this logic that we described. It's similar\nto the function `_calc_encode_length()`. Notice that the division part is twisted. Also notice that this time, we apply\na floor operation over the output of the division, by using the `divFloor()`\nfunction (instead of a ceiling operation with `divCeil()`).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_decode_length(input: []const u8) !usize {\n    if (input.len < 4) {\n        return 3;\n    }\n\n    const n_groups: usize = try std.math.divFloor(\n        usize, input.len, 4\n    );\n    var multiple_groups: usize = n_groups * 3;\n    var i: usize = input.len - 1;\n    while (i > 0) : (i -= 1) {\n        if (input[i] == '=') {\n            multiple_groups -= 1;\n        } else {\n            break;\n        }\n    }\n\n    return multiple_groups;\n}\n```\n:::\n\n\n\n\n## Building the encoder logic {#sec-encoder-logic}\n\nIn this section, we can start building the logic behind the `encode()` function, which\nwill be responsible for encoding messages into the base64 encoding system.\nIf you are an anxious person, and you want to see now the full source code of the implementation\nfor this base64 encoder/decoder, you can find it at the `ZigExamples` folder in the official repository of\nthis book[^zig-base64-algo].\n\n[^zig-base64-algo]: .\n\n\n\n### The 6-bit transformation {#sec-6bit-transf}\n\nThe 6-bit transformation presented in @fig-base64-algo1 is the core part of the base64 encoder algorithm.\nBy understanding how this transformation is made in code, the rest of the algorithm becomes much simpler\nto comprehend.\n\nIn essence, this 6-bit transformation is made with the help of bitwise operators.\nBitwise operators are essential to any type of low-level operation that is done at the bit-level. For the specific case of the base64 algorithm,\nthe operators *bif shift to the left* (`<<`), *bit shift to the right* (`>>`), and the *bitwise and* (`&`) are used. They\nare the core solution for the 6-bit transformation.\n\nThere are 3 different scenarios that we need to take into account in this transformation. First, is the perfect scenario,\nwhere we have the perfect window of 3 bytes to work on. Second, we have the scenario where we have a window of only\ntwo bytes to work with. And last, we have the scenario where we have a window of one single byte.\n\nIn each of these 3 scenarios, the 6-bit transformation works a bit differently. To make the explanation\neasier, I will use the variable `output` to refer to the bytes in the output of the base64 encoder,\nand the variable `input` to refer to the bytes in the input of the encoder.\n\n\nSo, if you have the perfect window of 3 bytes, these are steps for the 6-bit transformation:\n\n1. `output[0]` is produced by moving the bits from `input[0]` two positions to the right.\n1. `output[1]` is produced by summing two components. First, take the last two bits from `input[0]`, then, move them four positions to the left. Second, move the bits from `input[1]` four positions to the right. Sum these two components.\n1. `output[2]` is produced by summing two components. First, take the last four bits from `input[1]`, then, move them two positions to the left. Second, move the bits from `input[2]` six positions to the right. Sum these two components.\n1. `output[3]` is produced by taking the last six bits from `input[2]`.\n\n\nThis is the perfect scenario, where we have a full window of 3 bytes to work on.\nJust to make things as clear as possible, the @fig-encoder-bitshift demonstrates visually how\nthe step 2 mentioned above works. So the 2nd byte in the `output` of the encoder, is made by taking the 1st byte (dark purple)\nand the 2nd byte (orange) from the input. You can see that, at the end of the process, we get a new\nbyte that contains the last 2 bits from the 1st byte in the `input`, and the first 4 bits\nfrom the 2nd byte in the `input`.\n\n![How the 2nd byte in the output of the encoder is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input.](../Figures/base64-encoder-bit-shift.png){#fig-encoder-bitshift}\n\nOn the other hand, we must be prepared for the instances where we do not have the perfect window of 3 bytes.\nIf you have a window of 2 bytes, then, the steps 3 and 4, which produces the bytes `output[2]` and `output[3]`, change a little bit,\nand they become:\n\n- `output[2]` is produced by taking the last 4 bits from `input[1]`, then, move them two positions to the left.\n- `output[3]` is the character `'='`.\n\n\nFinally, if you have a window of a single byte, then, the steps 2 to 4, which produces the bytes `output[1]`, `output[2]` and `output[3]` change,\nbecoming:\n\n- `output[1]` is produced by taking the last two bits from `input[0]`, then, move them four positions to the left.\n- `output[2]` and `output[3]` are the character `=`.\n\n\nIf these bullet points were a bit confusing for you, you may find the @tbl-transf-6bit more intuitive.\nThis table unifies all this logic into a simple table. Notice that\nthis table also provides the exact expression in Zig that creates the corresponding\nbyte in the output.\n\n\n::: {#tbl-transf-6bit}\n\n| Number of bytes in the window | Byte index in the output | In code                                    |\n|-------------------------------|--------------------------|--------------------------------------------|\n| 3                             | 0                        | input[0] >> 2                              |\n| 3                             | 1                        | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 3                             | 2                        | ((input[1] & 0x0f) << 2) + (input[2] >> 6) |\n| 3                             | 3                        | input[2] & 0x3f                            |\n| 2                             | 0                        | input[0] >> 2                              |\n| 2                             | 1                        | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 2                             | 2                        | ((input[1] & 0x0f) << 2)                   |\n| 2                             | 3                        | '='                                        |\n| 1                             | 0                        | input[0] >> 2                              |\n| 1                             | 1                        | ((input[0] & 0x03) << 4)                   |\n| 1                             | 2                        | '='                                        |\n| 1                             | 3                        | '='                                        |\n\n: How the 6-bit transformation translates into code in different window settings.\n\n:::\n\n\n\n\n\n\n### Bit-shifting in Zig\n\nBit-shifting in Zig works similarly to bit-shifting in C.\nAll bitwise operators that exist in C are available in Zig.\nHere, in the base64 encoder algorithm, they are essential\nto produce the result we want.\n\nFor those who are not familiar with these operators, they are\noperators that operates at the bit-level of your values.\nThis means that these operators takes the bits that form the value\nyou have, and change them in some way. This ultimately also changes\nthe value itself, because the binary representation of this value\nchanges.\n\nWe have already seen in @fig-encoder-bitshift the effect produced by a bit-shift.\nBut let's use the first byte in the output of the base64 encoder as another example of what\nbit-shifting means. This is the easiest byte of the 4 bytes in the output\nto build. Because we only need to move the bits from the first byte in the input two positions to the right,\nwith the *bit shift to the right* (`>>`) operator.\n\nIf we take the string \"Hi\" that we used in @fig-base64-algo1 as an example, the first byte in\nthis string is \"H\", which is the sequence `01001000` in binary.\nIf we move the bits of this byte, two places to the right, we get the sequence `00010010` as result.\nThis binary sequence is the value `18` in decimal, and also, the value `0x12` in hexadecimal.\nNotice that the first 6 bits of \"H\" were moved to the end of the byte.\nWith this operation, we get the first byte of the output.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const input = \"Hi\";\n    try stdout.print(\"{d}\\n\", .{input[0] >> 2});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n18\n```\n\n\n:::\n:::\n\n\n\nIf you recall @fig-base64-algo1, the first byte present in the output should\nbe equivalent to the 6-bit group `010010`. Although being visually different, the\nsequences `010010` and `00010010` are semantically equal. They mean the same thing.\nThey both represent the number 18 in decimal, and the value `0x12` in hexadecimal.\n\nSo, don't take the \"6-bit group\" factor so seriously. We do not need necessarily to\nget a 6-bit sequence as result. As long as the meaning of the 8-bit sequence we get is the same\nof the 6-bit sequence, we are in the clear.\n\n\n\n### Selecting specific bits with the `&` operator\n\nIf you comeback to @sec-6bit-transf, you will see that, in order to produce\nthe second and third bytes in the output, we need to select specific\nbits from the first and second bytes in the input string. But how\ncan we do that? The answer relies on the *bitwise and* (`&`) operator.\n\nThe @fig-encoder-bitshift already showed you what effect this `&` operator\nproduces in the bits of its operands. But let's make a clear description of it.\n\nIn summary, the `&` operator performs a logical conjunction operation\nbetween the bits of its operands. In more details, the operator `&`\ncompares each bit of the first operand to the corresponding bit of the second operand.\nIf both bits are 1, the corresponding result bit is set to 1.\nOtherwise, the corresponding result bit is set to 0 [@microsoftbitwiseand].\n\nSo, if we apply this operator to the binary sequences `1000100` and `00001101`\nthe result of this operation is the binary sequence `00000100`. Because only\nat the sixth position in both binary sequences we had a 1 value. So any\nposition where we do not have both binary sequences setted to 1, we get\na 0 bit in the resulting binary sequence.\n\nWe lose information about the original bit values\nfrom both sequences in this case. Because we no longer know\nif this 0 bit in the resulting binary sequence was produced by\ncombining 0 with 0, or 1 with 0, or 0 with 1.\n\nAs an example, suppose you have the binary sequence `10010111`, which is the number 151 in decimal. How\ncan we get a new binary sequence which contains only the third and\nfourth bits of this sequence?\n\nWe just need to combine this sequence with `00110000` (is `0x30` in hexadecimal) using the `&` operator.\nNotice that only the third and fourth positions in this binary sequence is setted to 1. As a consequence, only the\nthird and fourth values of both binary sequences are potentially preserved in the output. All the remaining positions\nare setted to zero in the output sequence, which is `00010000` (is the number 16 in decimal).\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const bits = 0b10010111;\n    try stdout.print(\"{d}\\n\", .{bits & 0b00110000});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n16\n```\n\n\n:::\n:::\n\n\n\n\n\n### Allocating space for the output\n\nAs I described in @sec-stack, to store an object in the stack,\nthis object needs to have a known and fixed length at compile-time. This is an important\nlimitation for our base64 encoder/decoder case. Because the size of\nthe output (from both the encoder and decoder) depends\ndirectly on the size of the input.\n\nHaving this in mind, we cannot know at compile time which is\nthe size of the output for both the encoder and decoder.\nSo, if we can't know the size of the output at compile time,\nthis means that we cannot store the output for both the encoder\nand decoder in the stack.\n\nConsequently, we need to store this output on the heap,\nand, as I commented in @sec-heap, we can only\nstore objects in the heap by using allocator objects.\nSo, one the arguments to both the `encode()` and `decode()`\nfunctions, needs to be an allocator object, because\nwe know for sure that, at some point inside the body of these\nfunctions, we need to allocate space on the heap to\nstore the output of these functions.\n\nThat is why, both the `encode()` and `decode()` functions that I\npresent in this book, have an argument called `allocator`,\nwhich receives a allocator object as input, identified by\nthe type `std.mem.Allocator` from the Zig Standard Library.\n\n\n\n### Writing the `encode()` function\n\nNow that we have a basic understanding on how the bitwise operators work, and how\nexactly they help us to achieve the result we want to achieve. We can now encapsulate\nall the logic that we have described in @fig-base64-algo1 and @tbl-transf-6bit into a nice\nfunction that we can add to our `Base64` struct definition, that we started in @sec-base64-table.\n\nYou can find the `encode()` function below. Notice that the first argument of this function,\nis the `Base64` struct itself. Therefore, this argument clearly signals\nthat this function is a method from the `Base64` struct.\n\nBecause the `encode()` function itself is fairly long,\nI intentionally omitted the `Base64` struct definition in this source code,\njust for brevity reasons. So, just remember that this function is a public function (or a public method) from the\n`Base64` struct.\n\nFurthermore, this `encode()` function has two other arguments:\n\n1. `input` is the input sequence of characters that you want to encode in base64;\n1. `allocator` is an allocator object to use in the necessary memory allocations.\n\nI described everything you need to know about allocator objects in @sec-allocators.\nSo, if you are not familiar with them, I highly recommend you to comeback to\nthat section, and read it.\nBy looking at the `encode()` function, you will see that we use this\nallocator object to allocate enough memory to store the output of\nthe encoding process.\n\nThe main for loop in the function is responsible for iterating through the entire input string.\nIn every iteration, we use a `count` variable to count how many iterations we had at the\nmoment. When `count` reaches 3, then, we try to encode the 3 characters (or bytes) that we have accumulated\nin the temporary buffer object (`buf`).\n\nAfter encoding these 3 characters and storing the result in the `output` variable, we reset\nthe `count` variable to zero, and start to count again on the next iteration of the loop.\nIf the loop hits the end of the string, and, the `count` variable is less than 3, then, it means that\nthe temporary buffer contains the last 1 or 2 bytes from the input.\nThat is why we have two `if` statements after the for loop. To deal which each possible case.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn encode(self: Base64,\n              allocator: std.mem.Allocator,\n              input: []const u8) ![]u8 {\n\n    if (input.len == 0) {\n        return \"\";\n    }\n\n    const n_out = try _calc_encode_length(input);\n    var out = try allocator.alloc(u8, n_out);\n    var buf = [3]u8{ 0, 0, 0 };\n    var count: u8 = 0;\n    var iout: u64 = 0;\n\n    for (input, 0..) |_, i| {\n        buf[count] = input[i];\n        count += 1;\n        if (count == 3) {\n            out[iout] = self._char_at(buf[0] >> 2);\n            out[iout + 1] = self._char_at(\n                ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n            );\n            out[iout + 2] = self._char_at(\n                ((buf[1] & 0x0f) << 2) + (buf[2] >> 6)\n            );\n            out[iout + 3] = self._char_at(buf[2] & 0x3f);\n            iout += 4;\n            count = 0;\n        }\n    }\n\n    if (count == 1) {\n        out[iout] = self._char_at(buf[0] >> 2);\n        out[iout + 1] = self._char_at(\n            (buf[0] & 0x03) << 4\n        );\n        out[iout + 2] = '=';\n        out[iout + 3] = '=';\n    }\n\n    if (count == 2) {\n        out[iout] = self._char_at(buf[0] >> 2);\n        out[iout + 1] = self._char_at(\n            ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n        );\n        out[iout + 2] = self._char_at(\n            (buf[1] & 0x0f) << 2\n        );\n        out[iout + 3] = '=';\n        iout += 4;\n    }\n\n    return out;\n}\n```\n:::\n\n\n\n\n\n## Building the decoder logic {#sec-decoder-logic}\n\nNow, we can focus on writing the base64 decoder logic. Remember from @fig-base64-algo2 that,\na base64 decoder does the inverse process of an encoder. So, all we need to do, is to\nwrite a `decode()` function that performs the inverse process that I exposed in @sec-encoder-logic.\n\n\n### Mapping base64 characters to their indexes {#sec-map-base64-index}\n\nOne thing that we need to do, in order to decode a base64-encoded message, is to calculate\nthe index in the base64 scale of every base64 character that we encounter in the decoder input.\n\nIn other words, the decoder receives as input, a sequence of base64 characters. We need\nto translate this sequence of characters into a sequence of indexes. These indexes\nare the index of each character in the base64 scale. This way, we get the value/byte\nthat was calculated in the 6-bit transformation step of the encoder process.\n\nThere are probably better/faster ways to calculate this, especially using a \"divide and conquer\"\ntype of strategy. But for now, I am satisfied with a simple and \"brute force\" type of strategy.\nThe `_char_index()` function below contains this strategy.\n\nWe are essentially looping through the *lookup table* with the base64 scale,\nand comparing the character we got with each character in the base64 scale.\nIf these characters match, then, we return the index of this character in the\nbase64 scale as the result.\n\nNotice that, if the input character is `'='`, the function returns the index 64, which is\n\"out of range\" in the scale. But, as I described in @sec-base64-scale,\nthe character `'='` does not belong to the base64 scale itself.\nIt's a special and meaningless character in base64.\n\nAlso notice that this `_char_index()` function is a method from our `Base64` struct,\nbecause of the `self` argument. Again, I have omitted the `Base64` struct definition in this example\nfor brevity reasons.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn _char_index(self: Base64, char: u8) u8 {\n    if (char == '=')\n        return 64;\n    var index: u8 = 0;\n    for (0..63) |i| {\n        if (self._char_at(i) == char)\n            break;\n        index += 1;\n    }\n\n    return index;\n}\n```\n:::\n\n\n\n\n\n### The 6-bit transformation\n\nOnce again, the core part of the algorithm is the 6-bit transformation.\nIf we understand the necessary steps to perform this transformation, the rest\nof the algorithm becomes much easier.\n\nFirst of all, before we actually go to the 6-bit transformation,\nwe need to make sure that we use `_char_index()` to convert the sequence of base64 characters\ninto a sequence of indexes. So the snippet below is important for the job that will be done.\nThe result of `_char_index()` is stored in a temporary buffer, and this temporary buffer\nis what we are going to use in the 6-bit transformation, instead of the actual `input` object.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (0..input.len) |i| {\n    buf[i] = self._char_index(input[i]);\n}\n```\n:::\n\n\n\nNow, instead of producing 4 bytes (or 4 characters) as output per each window of 3 characters in the input,\na base64 decoder produces 3 bytes (or 3 characters) as output per each window of 4 characters in the input.\nOnce again, is the inverse process.\n\nSo, the steps to produce the 3 bytes in the output are:\n\n1. `output[0]` is produced by summing two components. First, move the bits from `buf[0]` two positions to the left. Second, move the bits from `buf[1]` 4 positions to the right. Then, sum these two components.\n1. `output[1]` is produced by summing two components. First, move the bits from `buf[1]` four positions to the left. Second, move the bits from `buf[2]` 2 positions to the right. Then, sum these two components.\n1. `output[2]` is produced by summing two components. First, move the bits from `buf[2]` six positions to the left. Then, you sum the result with `buf[3]`.\n\n\nBefore we continue, let's try to visualize how these transformations make the original bytes that we had\nbefore the encoding process. First, think back to the 6-bit transformation performed by the encoder exposed in @sec-encoder-logic.\nThe first byte in the output of the encoder is produced by moving the bits in the first byte of the input two positions to the right.\n\nIf for example the first byte in the input of the encoder was the sequence `ABCDEFGH`, then, the first byte in the output of the encoder would be\n`00ABCDEF` (this sequence would be the first byte in the input of the decoder). Now, if the second byte in the input of the encoder was the sequence\n`IJKLMNOP`, then, the second byte in the encoder output would be `00GHIJKL` (as we demonstrated in @fig-encoder-bitshift).\n\nHence, if the sequences `00ABCDEF` and `00GHIJKL` are the first and second bytes, respectively, in the input of the decoder, the\n@fig-decoder-bitshift demonstrates visually how these two bytes are transformed into the first byte of the output of the decoder.\nNotice that the output byte is the sequence `ABCDEFGH`, which is the original byte from the input of the encoder.\n\n![How the 1st byte in the decoder output is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input](../Figures/base64-decoder-bit-shift.png){#fig-decoder-bitshift}\n\nThe @tbl-6bit-decode presents how the three steps described earlier translate into Zig code:\n\n\n\n::: {#tbl-6bit-decode}\n\n| Byte index in the output | In code                       |\n|--------------------------|-------------------------------|\n| 0                        | (buf[0] << 2) + (buf[1] >> 4) |\n| 1                        | (buf[1] << 4) + (buf[2] >> 2) |\n| 2                        | (buf[2] << 6) + buf[3]        |\n\n: The necessary steps for the 6-transformation in the decode process.\n\n\n:::\n\n\n\n\n\n\n\n### Writing the `decode()` function\n\nThe `decode()` function below contains the entire decoding process.\nWe first calculate the size of the output, with\n`_calc_decode_length()`, then, we allocate enough memory for this output with\nthe allocator object.\n\nThree temporary variables are created: 1) `count`, to hold the window count\nin each iteration of the for loop; 2) `iout`, to hold the current index in the output;\n3) `buf`, which is the temporary buffer that holds the base64 indexes to be\nconverted through the 6-bit transformation.\n\nThen, in each iteration of the for loop we fill the temporary buffer with the current\nwindow of bytes. When `count` hits the number 4, then, we have a full window of\nindexes in `buf` to be converted, and then, we apply the 6-bit transformation\nover the temporary buffer.\n\nNotice that we check if the indexes 2 and 3 in the temporary buffer are the number 64, which, if you recall\nfrom @sec-map-base64-index, is when the `_calc_index()` function receives a `'='` character\nas input. So, if these indexes are equal to the number 64, the `decode()` function knows\nthat it can simply ignore these indexes. They are not converted because, as I described before,\nthe character `'='` has no meaning, despite being the end of meaningful characters in the sequence.\nSo we can safely ignore them when they appear in the sequence.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn decode(self: Base64,\n          allocator: std.mem.Allocator,\n          input: []const u8) ![]u8 {\n\n    if (input.len == 0) {\n        return \"\";\n    }\n    const n_output = try _calc_decode_length(input);\n    var output = try allocator.alloc(u8, n_output);\n    var count: u8 = 0;\n    var iout: u64 = 0;\n    var buf = [4]u8{ 0, 0, 0, 0 };\n\n    for (0..input.len) |i| {\n        buf[count] = self._char_index(input[i]);\n        count += 1;\n        if (count == 4) {\n            output[iout] = (buf[0] << 2) + (buf[1] >> 4);\n            if (buf[2] != 64) {\n                output[iout + 1] = (buf[1] << 4) + (buf[2] >> 2);\n            }\n            if (buf[3] != 64) {\n                output[iout + 2] = (buf[2] << 6) + buf[3];\n            }\n            iout += 3;\n            count = 0;\n        }\n    }\n\n    return output;\n}\n```\n:::\n\n\n\n\n## The end result\n\nNow that we have both `decode()` and `encode()` implemented. We have a fully functioning\nbase64 encoder/decoder implemented in Zig. Here is an usage example of our\n`Base64` struct with the `encode()` and `decode()` methods that we have implemented.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar memory_buffer: [1000]u8 = undefined;\nvar fba = std.heap.FixedBufferAllocator.init(\n    &memory_buffer\n);\nconst allocator = fba.allocator();\n\nconst text = \"Testing some more stuff\";\nconst etext = \"VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=\";\nconst base64 = Base64.init();\nconst encoded_text = try base64.encode(\n    allocator, text\n);\nconst decoded_text = try base64.decode(\n    allocator, etext\n);\ntry stdout.print(\n    \"Encoded text: {s}\\n\", .{encoded_text}\n);\ntry stdout.print(\n    \"Decoded text: {s}\\n\", .{decoded_text}\n);\n```\n:::\n\n\n\n```\nEncoded text: VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=\nDecoded text: Testing some more stuff\n```\n\nYou can also see the full source code at once, by visiting the official repository of this book[^repo].\nMore precisely inside the `ZigExamples` folder[^zig-base64-algo].\n\n[^repo]: \n",
    -    "supporting": [
    -      "01-base64_files"
    -    ],
    -    "filters": [
    -      "rmarkdown/pagebreak.lua"
    -    ],
    -    "includes": {},
    -    "engineDependencies": {
    -      "knitr": [
    -        "{\"type\":\"list\",\"attributes\":{},\"value\":[]}"
    -      ]
    -    },
    -    "preserve": null,
    -    "postProcess": false
    -  }
    -}
    \ No newline at end of file
    diff --git a/_freeze/Chapters/01-base64/execute-results/html.json b/_freeze/Chapters/01-base64/execute-results/html.json
    index 7f1a2b90..875237c5 100644
    --- a/_freeze/Chapters/01-base64/execute-results/html.json
    +++ b/_freeze/Chapters/01-base64/execute-results/html.json
    @@ -2,10 +2,8 @@
       "hash": "378ceb7f207e1c24d8ca75cf94cd22bf",
       "result": {
         "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 1 - Building a base64 encoder/decoder {#sec-base64}\n\nAs our first small project, I want to implement a base64 encoder/decoder with you.\nBase64 is an encoding system which translates binary data to text.\nA big chunk of the web uses base64 to deliver binary data to systems\nthat can only read text data.\n\nThe most common example of a modern use case for base64 is essentially any email system,\nlike GMail, Outlook, etc. Because email systems normally use\nthe Simple Mail Transfer Protocol (SMTP), which is a web protocol\nthat supports only text data. So, if you need, for any reason, to\nsend a binary file (like for example, a PDF, or an Excel file) as\nan attachment in your email, these binary files are normally\nconverted to base64, before they are included in the SMTP message.\nSo, the base64 encoding is largely used in these email systems to include\nbinary data into the SMTP message.\n\n\n\n\n\n\n## How the base64 algorithm work?\n\nBut how exactly does the algorithm behind the base64 encoding work? Let's discuss that. First, I will\nexplain the base64 scale, which is the 64-character scale that is the basis for\nthe base64 encoding system.\n\nAfter that, I explain the algorithm behind a base64 encoder, which is the part of the algorithm that is responsible for encoding messages\ninto the base64 encoding system. Then, after that, I explain the algorithm behind a base64 decoder, which is\nthe part of the algorithm that is responsible for translating base64 messages back into their original meaning.\n\nIf you are unsure about the differences between an \"encoder\" and a \"decoder\",\ntake a look at @sec-encode-vs-decode.\n\n\n### The base64 scale {#sec-base64-scale}\n\nThe base64 encoding system is based on a scale that goes from 0 to 63 (hence the name).\nEach index in this scale is represented by a character (it's a scale of 64 characters).\nSo, in order to convert some binary data, to the base64 encoding, we need to convert each binary number to the corresponding\ncharacter in this \"scale of 64 characters\".\n\nThe base64 scale starts with all ASCII uppercase letters (A to Z) which represents\nthe first 25 indexes in this scale (0 to 25). After that, we have all ASCII lowercase letters\n(a to z), which represents the range 26 to 51 in the scale. After that, we\nhave the one digit numbers (0 to 9), which represents the indexes from 52 to 61 in the scale.\nFinally, the last two indexes in the scale (62 and 63) are represented by the characters `+` and `/`,\nrespectively.\n\nThese are the 64 characters that compose the base64 scale. The equal sign character (`=`) is not part of the scale itself,\nbut it is a special character in the base64 encoding system. This character is used solely as a suffix, to mark the end of the character sequence,\nor, to mark the end of meaningful characters in the sequence.\n\nThe bullet points below summarises the base64 scale:\n\n- range 0 to 25 is represented by: ASCII uppercase letters `-> [A-Z]`;\n- range 26 to 51 is represented by: ASCII lowercase letters `-> [a-z]`;\n- range 52 to 61 is represented by: one digit numbers `-> [0-9]`;\n- index 62 and 63 are represented by the characters `+` and `/`, respectively;\n- the character `=` represents the end of meaningful characters in the sequence;\n\n\n\n\n### Creating the scale as a lookup table {#sec-base64-table}\n\nThe best way to represent this scale in code, is to represent it as a *lookup table*.\nLookup tables are a classic strategy in computer science to speed up calculations. The basic idea\nis to replace a runtime calculation (which can take a long time to be done) with a basic array indexing\noperation.\n\nInstead of calculating the results everytime you need them, you calculate all possible results at once, and then, you store them in an array\n(which behaves lake a \"table\"). Then, every time you need to use one of the characters in the base64 scale, instead of\nusing many resources to calculate the exact character to be used, you simply retrieve this character\nfrom the array where you stored all the possible characters in the base64 scale.\nWe retrieve the character that we need directly from memory.\n\nWe can start building a Zig struct to store our base64 decoder/encoder logic.\nWe start with the `Base64` struct below. For now, we only have one single data member in this\nstruct, i.e., the member `_table`, which represents our lookup table. We also have an `init()` method,\nto create a new instance of a `Base64` object, and, a `_char_at()` method, which is a\n\"get character at index $x$\" type of function.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Base64 = struct {\n    _table: *const [64]u8,\n\n    pub fn init() Base64 {\n        const upper = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n        const lower = \"abcdefghijklmnopqrstuvwxyz\";\n        const numbers_symb = \"0123456789+/\";\n        return Base64{\n            ._table = upper ++ lower ++ numbers_symb,\n        };\n    }\n\n    pub fn _char_at(self: Base64, index: usize) u8 {\n        return self._table[index];\n    }\n};\n```\n:::\n\n\n\n\n\nIn other words, the `_char_at()` method is responsible for getting the character in the lookup\ntable (i.e., the `_table` struct data member) that corresponds to a particular index in the\n\"base64 scale\". So, in the example below, we know that the character that corresponds to the\nindex 28 in the \"base64 scale\" is the character \"c\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst base64 = Base64.init();\ntry stdout.print(\n    \"Character at index 28: {c}\\n\",\n    .{base64._char_at(28)}\n);\n```\n:::\n\n\n\n\n```\nCharacter at index 28: c\n```\n\n\n\n### A base64 encoder {#sec-base64-encoder-algo}\n\nThe algorithm behind a base64 encoder usually works on a window of 3 bytes. Because each byte has\n8 bits, so, 3 bytes forms a set of $8 \\times 3 = 24$ bits. This is desirable for the base64 algorithm, because\n24 bits is divisible by 6, which forms $24 / 6 = 4$ groups of 6 bits each.\n\nTherefore, the base64 algorithm works by converting 3 bytes at a time\ninto 4 characters from the base64 scale. It keeps iterating through the input string,\n3 bytes at a time, and converting them into the base64 scale, producing 4 characters\nper iteration. It keeps iterating, and producing these \"new characters\"\nuntil it hits the end of the input string.\n\nNow you may think, what if you have a particular string that has a number of bytes\nthat is not divisible by 3 - what happens? For example, if you have a string\nthat contains only two characters/bytes, such as \"Hi\". How would the algorithm\nbehave in such situation? You find the answer in @fig-base64-algo1.\nYou can see in @fig-base64-algo1 that the string \"Hi\", when converted to base64,\nbecomes the string \"SGk=\":\n\n![The logic behind a base64 encoder](./../Figures/base64-encoder-flow.png){#fig-base64-algo1}\n\nTaking the string \"Hi\" as an example, we have 2 bytes, or, 16 bits in total. So, we lack a full byte (8 bits)\nto complete the window of 24 bits that the base64 algorithm likes to work on. The first thing that\nthe algorithm does, is to check how to divide the input bytes into groups of 6 bits.\n\nIf the algorithm notices that there is a group of 6 bits that it's not complete, meaning that, this group contains $nbits$, where $0 < nbits < 6$,\n\nthe algorithm simply adds extra zeros in this group to fill the space that it needs.\nThat is why in @fig-base64-algo1, in the third group after the 6-bit transformation,\n2 extra zeros were added to fill the gap.\n\nWhen we have a 6-bit group that is not completely full, like the third group, extra zeros\nare added to fill the gap. But what about when an entire 6-bit group is empty, or, it\nsimply doesn't exist? This is the case of the fourth 6-bit group exposed at\n@fig-base64-algo1.\n\nThis fourth group is necessary, because the algorithm works on 4 groups of 6 bits.\nBut the input string does not have enough bytes to create a fourth 6-bit group.\nEvery time this happens, where an entire group of 6 bits is empty,\nthis group becomes a \"padding group\". Every \"padding group\" is mapped to\nthe character `=` (equal sign), which represents \"null\", or, the end\nof meaningful characters in the sequence. Hence, everytime that the algorithm produces a\n\"padding group\", this group is automatically mapped to `=`.\n\nAs another example, if you give the string \"0\" as input to a base64 encoder, this string is\ntranslated into the base64 sequence \"MA==\".\nThe character \"0\" is, in binary, the sequence `00110000`[^zero-note]. So, with the 6-bit transformation\nexposed in @fig-base64-algo1, this single character would produce these two 6-bit groups: `001100`, `000000`.\nThe remaining two 6-bit groups become \"padding groups\". That is why the last\ntwo characters in the output sequence (MA==) are `==`.\n\n\n[^zero-note]: Notice that, the character \"0\" is different than the actual number 0, which is simply zero in binary.\n\n### A base64 decoder {#sec-base64-decoder-algo}\n\nThe algorithm behind a base64 decoder is essentially the inverse process of a base64 encoder.\nA base64 decoder needs to translate base64 messages back into their original meaning,\ni.e., into the original sequence of binary data.\n\nA base64 decoder usually works on a window of 4 bytes. Because it wants to convert these 4 bytes\nback into the original sequence of 3 bytes, that was converted into 4 groups of 6 bits by the\nbase64 encoder. Remember, in a base64 decoder we are essentially reverting the process made\nby the base64 encoder.\n\nEach byte in the input string (the base64 encoded string) normally contributes to re-create\ntwo different bytes in the output (the original binary data).\nIn other words, each byte that comes out of a base64 decoder is created by transforming merging two different\nbytes in the input together. You can visualize this relationship in @fig-base64-algo2:\n\n![The logic behind a base64 decoder](./../Figures/base64-decoder-flow.png){#fig-base64-algo2}\n\nThe exact transformations, or, the exact steps applied to each byte from the input to transform them\ninto the bytes of the output, are a bit tricky to visualize in a figure like this. Because of that, I have\nsummarized these transformations as \"Some bit shifting and additions ...\" in the figure. These transformations\nwill be described in depth later.\n\nBesides that, if you look again in @fig-base64-algo2, you will notice that the character `=` was completely\nignored by the algorithm. Remember, this is just a special character that marks the end of meaningful characters\nin the base64 sequence. So, every `=` character in a base64 encoded sequence should be ignored by a base64 decoder.\n\n\n## Difference between encode and decode {#sec-encode-vs-decode}\n\nIf you don't have any previous experience with base64, you might not understand the differences\nbetween \"encode\" and \"decode\". Essentially, the terms \"encode\" and \"decode\" here\nhave the exact same meaning as they have in the field of encryption (i.e., they mean the same thing as \"encode\" and \"decode\" in hashing\nalgorithms, like the MD5 algorithm).\n\nThus, \"encode\" means that we want to encode, or, in other words, we want to translate some message into\nthe base64 encoding system. We want to produce the sequence of base64 characters that represent this\noriginal message in the base64 encoding system.\n\nIn contrast, \"decode\" represents the inverse process.\nWe want to decode, or, in other words, translate a base64 message back to its original content.\nSo, in this process we get a sequence of base64 characters as input, and produce as output,\nthe binary data that is represented by this sequence of base64 characters.\n\nAny base64 library is normally composed of these two parts: 1) the encoder, which is a function that encodes\n(i.e., it converts) any sequence of binary data into a sequence of base64 characters; 2) the decoder, which is a function\nthat converts a sequence of base64 characters back into the original sequence of binary data.\n\n\n\n## Calculating the size of the output {#sec-base64-length-out}\n\nOne task that we need to do is to calculate how much space we need to reserve for the\noutput, both of the encoder and decoder. This is simple math, and can be done easily in Zig\nbecause every array has its length (its number of elements) easily accesible by consulting\nthe `.len` property of the array.\n\nFor the encoder, the logic is the following: for each 3 bytes that we find in the input,\n4 new bytes are created in the output. So, we take the number of bytes in the input, divide it\nby 3, use a ceiling function, then, we multiply the result by 4. That way, we get the total\nnumber of bytes that will be produced by the encoder in its output.\n\nThe `_calc_encode_length()` function below encapsulates this logic.\nInside this function, we take the length of the input array,\nwe divide it by 3, and apply a ceil operation over the result by using the\n`divCeil()` function from the Zig Standard Library. Lastly, we multiply\nthe end result by 4 to get the answer we need.\n\nAlso, you might have notice that, if the input length is less than 3 bytes, then, the output length of the encoder is\nalways 4 bytes. This is the case for every input with less than 3 bytes, because, as I described in @sec-base64-encoder-algo,\nthe algorithm always produces enough \"padding-groups\" in the end result, to complete the 4 bytes window.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_encode_length(input: []const u8) !usize {\n    if (input.len < 3) {\n        return 4;\n    }\n    const n_groups: usize = try std.math.divCeil(\n        usize, input.len, 3\n    );\n    return n_groups * 4;\n}\n```\n:::\n\n\n\n\n\nNow, the logic to calculate the length of the output from the decoder is a little bit more complicated. But, it is basically\njust the inverse logic that we've used for the encoder: for each 4 bytes in the input, 3 bytes\nwill be produced in the output of the decoder. However, this time we need to\ntake the `=` character into account, which is always ignored by the decoder, as we described in @sec-base64-decoder-algo, and,\nin @fig-base64-algo2.\n\nIn essence, we take the length of the input and divide it by 4, then we apply a floor function on the result, then\nwe multiply the result by 3, and then, we subtract from the result how much times the character `=` is found\nin the input.\n\nThe function `_calc_decode_length()` exposed below summarizes this logic that we described. It's similar\nto the function `_calc_encode_length()`. Notice that the division part is twisted. Also notice that this time, we apply\na floor operation over the output of the division, by using the `divFloor()`\nfunction (instead of a ceiling operation with `divCeil()`).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_decode_length(input: []const u8) !usize {\n    if (input.len < 4) {\n        return 3;\n    }\n\n    const n_groups: usize = try std.math.divFloor(\n        usize, input.len, 4\n    );\n    var multiple_groups: usize = n_groups * 3;\n    var i: usize = input.len - 1;\n    while (i > 0) : (i -= 1) {\n        if (input[i] == '=') {\n            multiple_groups -= 1;\n        } else {\n            break;\n        }\n    }\n\n    return multiple_groups;\n}\n```\n:::\n\n\n\n\n\n## Building the encoder logic {#sec-encoder-logic}\n\nIn this section, we can start building the logic behind the `encode()` function, which\nwill be responsible for encoding messages into the base64 encoding system.\nIf you are an anxious person, and you want to see now the full source code of the implementation\nfor this base64 encoder/decoder, you can find it at the `ZigExamples` folder in the official repository of\nthis book[^zig-base64-algo].\n\n[^zig-base64-algo]: .\n\n\n\n### The 6-bit transformation {#sec-6bit-transf}\n\nThe 6-bit transformation presented in @fig-base64-algo1 is the core part of the base64 encoder algorithm.\nBy understanding how this transformation is made in code, the rest of the algorithm becomes much simpler\nto comprehend.\n\nIn essence, this 6-bit transformation is made with the help of bitwise operators.\nBitwise operators are essential to any type of low-level operation that is done at the bit-level. For the specific case of the base64 algorithm,\nthe operators *bif shift to the left* (`<<`), *bit shift to the right* (`>>`), and the *bitwise and* (`&`) are used. They\nare the core solution for the 6-bit transformation.\n\nThere are 3 different scenarios that we need to take into account in this transformation. First, is the perfect scenario,\nwhere we have the perfect window of 3 bytes to work on. Second, we have the scenario where we have a window of only\ntwo bytes to work with. And last, we have the scenario where we have a window of one single byte.\n\nIn each of these 3 scenarios, the 6-bit transformation works a bit differently. To make the explanation\neasier, I will use the variable `output` to refer to the bytes in the output of the base64 encoder,\nand the variable `input` to refer to the bytes in the input of the encoder.\n\n\nSo, if you have the perfect window of 3 bytes, these are steps for the 6-bit transformation:\n\n1. `output[0]` is produced by moving the bits from `input[0]` two positions to the right.\n1. `output[1]` is produced by summing two components. First, take the last two bits from `input[0]`, then, move them four positions to the left. Second, move the bits from `input[1]` four positions to the right. Sum these two components.\n1. `output[2]` is produced by summing two components. First, take the last four bits from `input[1]`, then, move them two positions to the left. Second, move the bits from `input[2]` six positions to the right. Sum these two components.\n1. `output[3]` is produced by taking the last six bits from `input[2]`.\n\n\nThis is the perfect scenario, where we have a full window of 3 bytes to work on.\nJust to make things as clear as possible, the @fig-encoder-bitshift demonstrates visually how\nthe step 2 mentioned above works. So the 2nd byte in the `output` of the encoder, is made by taking the 1st byte (dark purple)\nand the 2nd byte (orange) from the input. You can see that, at the end of the process, we get a new\nbyte that contains the last 2 bits from the 1st byte in the `input`, and the first 4 bits\nfrom the 2nd byte in the `input`.\n\n![How the 2nd byte in the output of the encoder is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input.](../Figures/base64-encoder-bit-shift.png){#fig-encoder-bitshift}\n\nOn the other hand, we must be prepared for the instances where we do not have the perfect window of 3 bytes.\nIf you have a window of 2 bytes, then, the steps 3 and 4, which produces the bytes `output[2]` and `output[3]`, change a little bit,\nand they become:\n\n- `output[2]` is produced by taking the last 4 bits from `input[1]`, then, move them two positions to the left.\n- `output[3]` is the character `'='`.\n\n\nFinally, if you have a window of a single byte, then, the steps 2 to 4, which produces the bytes `output[1]`, `output[2]` and `output[3]` change,\nbecoming:\n\n- `output[1]` is produced by taking the last two bits from `input[0]`, then, move them four positions to the left.\n- `output[2]` and `output[3]` are the character `=`.\n\n\nIf these bullet points were a bit confusing for you, you may find the @tbl-transf-6bit more intuitive.\nThis table unifies all this logic into a simple table. Notice that\nthis table also provides the exact expression in Zig that creates the corresponding\nbyte in the output.\n\n\n::: {#tbl-transf-6bit}\n\n| Number of bytes in the window | Byte index in the output | In code                                    |\n|-------------------------------|--------------------------|--------------------------------------------|\n| 3                             | 0                        | input[0] >> 2                              |\n| 3                             | 1                        | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 3                             | 2                        | ((input[1] & 0x0f) << 2) + (input[2] >> 6) |\n| 3                             | 3                        | input[2] & 0x3f                            |\n| 2                             | 0                        | input[0] >> 2                              |\n| 2                             | 1                        | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 2                             | 2                        | ((input[1] & 0x0f) << 2)                   |\n| 2                             | 3                        | '='                                        |\n| 1                             | 0                        | input[0] >> 2                              |\n| 1                             | 1                        | ((input[0] & 0x03) << 4)                   |\n| 1                             | 2                        | '='                                        |\n| 1                             | 3                        | '='                                        |\n\n: How the 6-bit transformation translates into code in different window settings.\n\n:::\n\n\n\n\n\n\n### Bit-shifting in Zig\n\nBit-shifting in Zig works similarly to bit-shifting in C.\nAll bitwise operators that exist in C are available in Zig.\nHere, in the base64 encoder algorithm, they are essential\nto produce the result we want.\n\nFor those who are not familiar with these operators, they are\noperators that operates at the bit-level of your values.\nThis means that these operators takes the bits that form the value\nyou have, and change them in some way. This ultimately also changes\nthe value itself, because the binary representation of this value\nchanges.\n\nWe have already seen in @fig-encoder-bitshift the effect produced by a bit-shift.\nBut let's use the first byte in the output of the base64 encoder as another example of what\nbit-shifting means. This is the easiest byte of the 4 bytes in the output\nto build. Because we only need to move the bits from the first byte in the input two positions to the right,\nwith the *bit shift to the right* (`>>`) operator.\n\nIf we take the string \"Hi\" that we used in @fig-base64-algo1 as an example, the first byte in\nthis string is \"H\", which is the sequence `01001000` in binary.\nIf we move the bits of this byte, two places to the right, we get the sequence `00010010` as result.\nThis binary sequence is the value `18` in decimal, and also, the value `0x12` in hexadecimal.\nNotice that the first 6 bits of \"H\" were moved to the end of the byte.\nWith this operation, we get the first byte of the output.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const input = \"Hi\";\n    try stdout.print(\"{d}\\n\", .{input[0] >> 2});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n18\n```\n\n\n:::\n:::\n\n\n\n\nIf you recall @fig-base64-algo1, the first byte present in the output should\nbe equivalent to the 6-bit group `010010`. Although being visually different, the\nsequences `010010` and `00010010` are semantically equal. They mean the same thing.\nThey both represent the number 18 in decimal, and the value `0x12` in hexadecimal.\n\nSo, don't take the \"6-bit group\" factor so seriously. We do not need necessarily to\nget a 6-bit sequence as result. As long as the meaning of the 8-bit sequence we get is the same\nof the 6-bit sequence, we are in the clear.\n\n\n\n### Selecting specific bits with the `&` operator\n\nIf you comeback to @sec-6bit-transf, you will see that, in order to produce\nthe second and third bytes in the output, we need to select specific\nbits from the first and second bytes in the input string. But how\ncan we do that? The answer relies on the *bitwise and* (`&`) operator.\n\nThe @fig-encoder-bitshift already showed you what effect this `&` operator\nproduces in the bits of its operands. But let's make a clear description of it.\n\nIn summary, the `&` operator performs a logical conjunction operation\nbetween the bits of its operands. In more details, the operator `&`\ncompares each bit of the first operand to the corresponding bit of the second operand.\nIf both bits are 1, the corresponding result bit is set to 1.\nOtherwise, the corresponding result bit is set to 0 [@microsoftbitwiseand].\n\nSo, if we apply this operator to the binary sequences `1000100` and `00001101`\nthe result of this operation is the binary sequence `00000100`. Because only\nat the sixth position in both binary sequences we had a 1 value. So any\nposition where we do not have both binary sequences setted to 1, we get\na 0 bit in the resulting binary sequence.\n\nWe lose information about the original bit values\nfrom both sequences in this case. Because we no longer know\nif this 0 bit in the resulting binary sequence was produced by\ncombining 0 with 0, or 1 with 0, or 0 with 1.\n\nAs an example, suppose you have the binary sequence `10010111`, which is the number 151 in decimal. How\ncan we get a new binary sequence which contains only the third and\nfourth bits of this sequence?\n\nWe just need to combine this sequence with `00110000` (is `0x30` in hexadecimal) using the `&` operator.\nNotice that only the third and fourth positions in this binary sequence is setted to 1. As a consequence, only the\nthird and fourth values of both binary sequences are potentially preserved in the output. All the remaining positions\nare setted to zero in the output sequence, which is `00010000` (is the number 16 in decimal).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const bits = 0b10010111;\n    try stdout.print(\"{d}\\n\", .{bits & 0b00110000});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n16\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Allocating space for the output\n\nAs I described in @sec-stack, to store an object in the stack,\nthis object needs to have a known and fixed length at compile-time. This is an important\nlimitation for our base64 encoder/decoder case. Because the size of\nthe output (from both the encoder and decoder) depends\ndirectly on the size of the input.\n\nHaving this in mind, we cannot know at compile time which is\nthe size of the output for both the encoder and decoder.\nSo, if we can't know the size of the output at compile time,\nthis means that we cannot store the output for both the encoder\nand decoder in the stack.\n\nConsequently, we need to store this output on the heap,\nand, as I commented in @sec-heap, we can only\nstore objects in the heap by using allocator objects.\nSo, one the arguments to both the `encode()` and `decode()`\nfunctions, needs to be an allocator object, because\nwe know for sure that, at some point inside the body of these\nfunctions, we need to allocate space on the heap to\nstore the output of these functions.\n\nThat is why, both the `encode()` and `decode()` functions that I\npresent in this book, have an argument called `allocator`,\nwhich receives a allocator object as input, identified by\nthe type `std.mem.Allocator` from the Zig Standard Library.\n\n\n\n### Writing the `encode()` function\n\nNow that we have a basic understanding on how the bitwise operators work, and how\nexactly they help us to achieve the result we want to achieve. We can now encapsulate\nall the logic that we have described in @fig-base64-algo1 and @tbl-transf-6bit into a nice\nfunction that we can add to our `Base64` struct definition, that we started in @sec-base64-table.\n\nYou can find the `encode()` function below. Notice that the first argument of this function,\nis the `Base64` struct itself. Therefore, this argument clearly signals\nthat this function is a method from the `Base64` struct.\n\nBecause the `encode()` function itself is fairly long,\nI intentionally omitted the `Base64` struct definition in this source code,\njust for brevity reasons. So, just remember that this function is a public function (or a public method) from the\n`Base64` struct.\n\nFurthermore, this `encode()` function has two other arguments:\n\n1. `input` is the input sequence of characters that you want to encode in base64;\n1. `allocator` is an allocator object to use in the necessary memory allocations.\n\nI described everything you need to know about allocator objects in @sec-allocators.\nSo, if you are not familiar with them, I highly recommend you to comeback to\nthat section, and read it.\nBy looking at the `encode()` function, you will see that we use this\nallocator object to allocate enough memory to store the output of\nthe encoding process.\n\nThe main for loop in the function is responsible for iterating through the entire input string.\nIn every iteration, we use a `count` variable to count how many iterations we had at the\nmoment. When `count` reaches 3, then, we try to encode the 3 characters (or bytes) that we have accumulated\nin the temporary buffer object (`buf`).\n\nAfter encoding these 3 characters and storing the result in the `output` variable, we reset\nthe `count` variable to zero, and start to count again on the next iteration of the loop.\nIf the loop hits the end of the string, and, the `count` variable is less than 3, then, it means that\nthe temporary buffer contains the last 1 or 2 bytes from the input.\nThat is why we have two `if` statements after the for loop. To deal which each possible case.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn encode(self: Base64,\n              allocator: std.mem.Allocator,\n              input: []const u8) ![]u8 {\n\n    if (input.len == 0) {\n        return \"\";\n    }\n\n    const n_out = try _calc_encode_length(input);\n    var out = try allocator.alloc(u8, n_out);\n    var buf = [3]u8{ 0, 0, 0 };\n    var count: u8 = 0;\n    var iout: u64 = 0;\n\n    for (input, 0..) |_, i| {\n        buf[count] = input[i];\n        count += 1;\n        if (count == 3) {\n            out[iout] = self._char_at(buf[0] >> 2);\n            out[iout + 1] = self._char_at(\n                ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n            );\n            out[iout + 2] = self._char_at(\n                ((buf[1] & 0x0f) << 2) + (buf[2] >> 6)\n            );\n            out[iout + 3] = self._char_at(buf[2] & 0x3f);\n            iout += 4;\n            count = 0;\n        }\n    }\n\n    if (count == 1) {\n        out[iout] = self._char_at(buf[0] >> 2);\n        out[iout + 1] = self._char_at(\n            (buf[0] & 0x03) << 4\n        );\n        out[iout + 2] = '=';\n        out[iout + 3] = '=';\n    }\n\n    if (count == 2) {\n        out[iout] = self._char_at(buf[0] >> 2);\n        out[iout + 1] = self._char_at(\n            ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n        );\n        out[iout + 2] = self._char_at(\n            (buf[1] & 0x0f) << 2\n        );\n        out[iout + 3] = '=';\n        iout += 4;\n    }\n\n    return out;\n}\n```\n:::\n\n\n\n\n\n\n## Building the decoder logic {#sec-decoder-logic}\n\nNow, we can focus on writing the base64 decoder logic. Remember from @fig-base64-algo2 that,\na base64 decoder does the inverse process of an encoder. So, all we need to do, is to\nwrite a `decode()` function that performs the inverse process that I exposed in @sec-encoder-logic.\n\n\n### Mapping base64 characters to their indexes {#sec-map-base64-index}\n\nOne thing that we need to do, in order to decode a base64-encoded message, is to calculate\nthe index in the base64 scale of every base64 character that we encounter in the decoder input.\n\nIn other words, the decoder receives as input, a sequence of base64 characters. We need\nto translate this sequence of characters into a sequence of indexes. These indexes\nare the index of each character in the base64 scale. This way, we get the value/byte\nthat was calculated in the 6-bit transformation step of the encoder process.\n\nThere are probably better/faster ways to calculate this, especially using a \"divide and conquer\"\ntype of strategy. But for now, I am satisfied with a simple and \"brute force\" type of strategy.\nThe `_char_index()` function below contains this strategy.\n\nWe are essentially looping through the *lookup table* with the base64 scale,\nand comparing the character we got with each character in the base64 scale.\nIf these characters match, then, we return the index of this character in the\nbase64 scale as the result.\n\nNotice that, if the input character is `'='`, the function returns the index 64, which is\n\"out of range\" in the scale. But, as I described in @sec-base64-scale,\nthe character `'='` does not belong to the base64 scale itself.\nIt's a special and meaningless character in base64.\n\nAlso notice that this `_char_index()` function is a method from our `Base64` struct,\nbecause of the `self` argument. Again, I have omitted the `Base64` struct definition in this example\nfor brevity reasons.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn _char_index(self: Base64, char: u8) u8 {\n    if (char == '=')\n        return 64;\n    var index: u8 = 0;\n    for (0..63) |i| {\n        if (self._char_at(i) == char)\n            break;\n        index += 1;\n    }\n\n    return index;\n}\n```\n:::\n\n\n\n\n\n\n### The 6-bit transformation\n\nOnce again, the core part of the algorithm is the 6-bit transformation.\nIf we understand the necessary steps to perform this transformation, the rest\nof the algorithm becomes much easier.\n\nFirst of all, before we actually go to the 6-bit transformation,\nwe need to make sure that we use `_char_index()` to convert the sequence of base64 characters\ninto a sequence of indexes. So the snippet below is important for the job that will be done.\nThe result of `_char_index()` is stored in a temporary buffer, and this temporary buffer\nis what we are going to use in the 6-bit transformation, instead of the actual `input` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (0..input.len) |i| {\n    buf[i] = self._char_index(input[i]);\n}\n```\n:::\n\n\n\n\nNow, instead of producing 4 bytes (or 4 characters) as output per each window of 3 characters in the input,\na base64 decoder produces 3 bytes (or 3 characters) as output per each window of 4 characters in the input.\nOnce again, is the inverse process.\n\nSo, the steps to produce the 3 bytes in the output are:\n\n1. `output[0]` is produced by summing two components. First, move the bits from `buf[0]` two positions to the left. Second, move the bits from `buf[1]` 4 positions to the right. Then, sum these two components.\n1. `output[1]` is produced by summing two components. First, move the bits from `buf[1]` four positions to the left. Second, move the bits from `buf[2]` 2 positions to the right. Then, sum these two components.\n1. `output[2]` is produced by summing two components. First, move the bits from `buf[2]` six positions to the left. Then, you sum the result with `buf[3]`.\n\n\nBefore we continue, let's try to visualize how these transformations make the original bytes that we had\nbefore the encoding process. First, think back to the 6-bit transformation performed by the encoder exposed in @sec-encoder-logic.\nThe first byte in the output of the encoder is produced by moving the bits in the first byte of the input two positions to the right.\n\nIf for example the first byte in the input of the encoder was the sequence `ABCDEFGH`, then, the first byte in the output of the encoder would be\n`00ABCDEF` (this sequence would be the first byte in the input of the decoder). Now, if the second byte in the input of the encoder was the sequence\n`IJKLMNOP`, then, the second byte in the encoder output would be `00GHIJKL` (as we demonstrated in @fig-encoder-bitshift).\n\nHence, if the sequences `00ABCDEF` and `00GHIJKL` are the first and second bytes, respectively, in the input of the decoder, the\n@fig-decoder-bitshift demonstrates visually how these two bytes are transformed into the first byte of the output of the decoder.\nNotice that the output byte is the sequence `ABCDEFGH`, which is the original byte from the input of the encoder.\n\n![How the 1st byte in the decoder output is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input](../Figures/base64-decoder-bit-shift.png){#fig-decoder-bitshift}\n\nThe @tbl-6bit-decode presents how the three steps described earlier translate into Zig code:\n\n\n\n::: {#tbl-6bit-decode}\n\n| Byte index in the output | In code                       |\n|--------------------------|-------------------------------|\n| 0                        | (buf[0] << 2) + (buf[1] >> 4) |\n| 1                        | (buf[1] << 4) + (buf[2] >> 2) |\n| 2                        | (buf[2] << 6) + buf[3]        |\n\n: The necessary steps for the 6-transformation in the decode process.\n\n\n:::\n\n\n\n\n\n\n\n### Writing the `decode()` function\n\nThe `decode()` function below contains the entire decoding process.\nWe first calculate the size of the output, with\n`_calc_decode_length()`, then, we allocate enough memory for this output with\nthe allocator object.\n\nThree temporary variables are created: 1) `count`, to hold the window count\nin each iteration of the for loop; 2) `iout`, to hold the current index in the output;\n3) `buf`, which is the temporary buffer that holds the base64 indexes to be\nconverted through the 6-bit transformation.\n\nThen, in each iteration of the for loop we fill the temporary buffer with the current\nwindow of bytes. When `count` hits the number 4, then, we have a full window of\nindexes in `buf` to be converted, and then, we apply the 6-bit transformation\nover the temporary buffer.\n\nNotice that we check if the indexes 2 and 3 in the temporary buffer are the number 64, which, if you recall\nfrom @sec-map-base64-index, is when the `_calc_index()` function receives a `'='` character\nas input. So, if these indexes are equal to the number 64, the `decode()` function knows\nthat it can simply ignore these indexes. They are not converted because, as I described before,\nthe character `'='` has no meaning, despite being the end of meaningful characters in the sequence.\nSo we can safely ignore them when they appear in the sequence.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn decode(self: Base64,\n          allocator: std.mem.Allocator,\n          input: []const u8) ![]u8 {\n\n    if (input.len == 0) {\n        return \"\";\n    }\n    const n_output = try _calc_decode_length(input);\n    var output = try allocator.alloc(u8, n_output);\n    var count: u8 = 0;\n    var iout: u64 = 0;\n    var buf = [4]u8{ 0, 0, 0, 0 };\n\n    for (0..input.len) |i| {\n        buf[count] = self._char_index(input[i]);\n        count += 1;\n        if (count == 4) {\n            output[iout] = (buf[0] << 2) + (buf[1] >> 4);\n            if (buf[2] != 64) {\n                output[iout + 1] = (buf[1] << 4) + (buf[2] >> 2);\n            }\n            if (buf[3] != 64) {\n                output[iout + 2] = (buf[2] << 6) + buf[3];\n            }\n            iout += 3;\n            count = 0;\n        }\n    }\n\n    return output;\n}\n```\n:::\n\n\n\n\n\n## The end result\n\nNow that we have both `decode()` and `encode()` implemented. We have a fully functioning\nbase64 encoder/decoder implemented in Zig. Here is an usage example of our\n`Base64` struct with the `encode()` and `decode()` methods that we have implemented.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar memory_buffer: [1000]u8 = undefined;\nvar fba = std.heap.FixedBufferAllocator.init(\n    &memory_buffer\n);\nconst allocator = fba.allocator();\n\nconst text = \"Testing some more stuff\";\nconst etext = \"VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=\";\nconst base64 = Base64.init();\nconst encoded_text = try base64.encode(\n    allocator, text\n);\nconst decoded_text = try base64.decode(\n    allocator, etext\n);\ntry stdout.print(\n    \"Encoded text: {s}\\n\", .{encoded_text}\n);\ntry stdout.print(\n    \"Decoded text: {s}\\n\", .{decoded_text}\n);\n```\n:::\n\n\n\n\n```\nEncoded text: VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=\nDecoded text: Testing some more stuff\n```\n\nYou can also see the full source code at once, by visiting the official repository of this book[^repo].\nMore precisely inside the `ZigExamples` folder[^zig-base64-algo].\n\n[^repo]: \n",
    -    "supporting": [
    -      "01-base64_files"
    -    ],
    +    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n# Project 1 - Building a base64 encoder/decoder {#sec-base64}\n\nAs our first small project, I want to implement a base64 encoder/decoder with you.\nBase64 is an encoding system which translates binary data to text.\nA big chunk of the web uses base64 to deliver binary data to systems\nthat can only read text data.\n\nThe most common example of a modern use case for base64 is essentially any email system,\nlike GMail, Outlook, etc. Because email systems normally use\nthe Simple Mail Transfer Protocol (SMTP), which is a web protocol\nthat supports only text data. So, if you need, for any reason, to\nsend a binary file (like for example, a PDF, or an Excel file) as\nan attachment in your email, these binary files are normally\nconverted to base64, before they are included in the SMTP message.\nSo, the base64 encoding is largely used in these email systems to include\nbinary data into the SMTP message.\n\n\n\n\n\n\n## How the base64 algorithm work?\n\nBut how exactly does the algorithm behind the base64 encoding work? Let's discuss that. First, I will\nexplain the base64 scale, which is the 64-character scale that is the basis for\nthe base64 encoding system.\n\nAfter that, I explain the algorithm behind a base64 encoder, which is the part of the algorithm that is responsible for encoding messages\ninto the base64 encoding system. Then, after that, I explain the algorithm behind a base64 decoder, which is\nthe part of the algorithm that is responsible for translating base64 messages back into their original meaning.\n\nIf you are unsure about the differences between an \"encoder\" and a \"decoder\",\ntake a look at @sec-encode-vs-decode.\n\n\n### The base64 scale {#sec-base64-scale}\n\nThe base64 encoding system is based on a scale that goes from 0 to 63 (hence the name).\nEach index in this scale is represented by a character (it's a scale of 64 characters).\nSo, in order to convert some binary data, to the base64 encoding, we need to convert each binary number to the corresponding\ncharacter in this \"scale of 64 characters\".\n\nThe base64 scale starts with all ASCII uppercase letters (A to Z) which represents\nthe first 25 indexes in this scale (0 to 25). After that, we have all ASCII lowercase letters\n(a to z), which represents the range 26 to 51 in the scale. After that, we\nhave the one digit numbers (0 to 9), which represents the indexes from 52 to 61 in the scale.\nFinally, the last two indexes in the scale (62 and 63) are represented by the characters `+` and `/`,\nrespectively.\n\nThese are the 64 characters that compose the base64 scale. The equal sign character (`=`) is not part of the scale itself,\nbut it is a special character in the base64 encoding system. This character is used solely as a suffix, to mark the end of the character sequence,\nor, to mark the end of meaningful characters in the sequence.\n\nThe bullet points below summarises the base64 scale:\n\n- range 0 to 25 is represented by: ASCII uppercase letters `-> [A-Z]`;\n- range 26 to 51 is represented by: ASCII lowercase letters `-> [a-z]`;\n- range 52 to 61 is represented by: one digit numbers `-> [0-9]`;\n- index 62 and 63 are represented by the characters `+` and `/`, respectively;\n- the character `=` represents the end of meaningful characters in the sequence;\n\n\n\n\n### Creating the scale as a lookup table {#sec-base64-table}\n\nThe best way to represent this scale in code, is to represent it as a *lookup table*.\nLookup tables are a classic strategy in computer science to speed up calculations. The basic idea\nis to replace a runtime calculation (which can take a long time to be done) with a basic array indexing\noperation.\n\nInstead of calculating the results everytime you need them, you calculate all possible results at once, and then, you store them in an array\n(which behaves lake a \"table\"). Then, every time you need to use one of the characters in the base64 scale, instead of\nusing many resources to calculate the exact character to be used, you simply retrieve this character\nfrom the array where you stored all the possible characters in the base64 scale.\nWe retrieve the character that we need directly from memory.\n\nWe can start building a Zig struct to store our base64 decoder/encoder logic.\nWe start with the `Base64` struct below. For now, we only have one single data member in this\nstruct, i.e., the member `_table`, which represents our lookup table. We also have an `init()` method,\nto create a new instance of a `Base64` object, and, a `_char_at()` method, which is a\n\"get character at index $x$\" type of function.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Base64 = struct {\n    _table: *const [64]u8,\n\n    pub fn init() Base64 {\n        const upper = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n        const lower = \"abcdefghijklmnopqrstuvwxyz\";\n        const numbers_symb = \"0123456789+/\";\n        return Base64{\n            ._table = upper ++ lower ++ numbers_symb,\n        };\n    }\n\n    pub fn _char_at(self: Base64, index: usize) u8 {\n        return self._table[index];\n    }\n};\n```\n:::\n\n\n\nIn other words, the `_char_at()` method is responsible for getting the character in the lookup\ntable (i.e., the `_table` struct data member) that corresponds to a particular index in the\n\"base64 scale\". So, in the example below, we know that the character that corresponds to the\nindex 28 in the \"base64 scale\" is the character \"c\".\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst base64 = Base64.init();\ntry stdout.print(\n    \"Character at index 28: {c}\\n\",\n    .{base64._char_at(28)}\n);\n```\n:::\n\n\n```\nCharacter at index 28: c\n```\n\n\n\n### A base64 encoder {#sec-base64-encoder-algo}\n\nThe algorithm behind a base64 encoder usually works on a window of 3 bytes. Because each byte has\n8 bits, so, 3 bytes forms a set of $8 \\times 3 = 24$ bits. This is desirable for the base64 algorithm, because\n24 bits is divisible by 6, which forms $24 / 6 = 4$ groups of 6 bits each.\n\nTherefore, the base64 algorithm works by converting 3 bytes at a time\ninto 4 characters from the base64 scale. It keeps iterating through the input string,\n3 bytes at a time, and converting them into the base64 scale, producing 4 characters\nper iteration. It keeps iterating, and producing these \"new characters\"\nuntil it hits the end of the input string.\n\nNow you may think, what if you have a particular string that has a number of bytes\nthat is not divisible by 3 - what happens? For example, if you have a string\nthat contains only two characters/bytes, such as \"Hi\". How would the algorithm\nbehave in such situation? You find the answer in @fig-base64-algo1.\nYou can see in @fig-base64-algo1 that the string \"Hi\", when converted to base64,\nbecomes the string \"SGk=\":\n\n![The logic behind a base64 encoder](./../Figures/base64-encoder-flow.png){#fig-base64-algo1}\n\nTaking the string \"Hi\" as an example, we have 2 bytes, or, 16 bits in total. So, we lack a full byte (8 bits)\nto complete the window of 24 bits that the base64 algorithm likes to work on. The first thing that\nthe algorithm does, is to check how to divide the input bytes into groups of 6 bits.\n\nIf the algorithm notices that there is a group of 6 bits that it's not complete, meaning that, this group contains $nbits$, where $0 < nbits < 6$,\n\nthe algorithm simply adds extra zeros in this group to fill the space that it needs.\nThat is why in @fig-base64-algo1, in the third group after the 6-bit transformation,\n2 extra zeros were added to fill the gap.\n\nWhen we have a 6-bit group that is not completely full, like the third group, extra zeros\nare added to fill the gap. But what about when an entire 6-bit group is empty, or, it\nsimply doesn't exist? This is the case of the fourth 6-bit group exposed at\n@fig-base64-algo1.\n\nThis fourth group is necessary, because the algorithm works on 4 groups of 6 bits.\nBut the input string does not have enough bytes to create a fourth 6-bit group.\nEvery time this happens, where an entire group of 6 bits is empty,\nthis group becomes a \"padding group\". Every \"padding group\" is mapped to\nthe character `=` (equal sign), which represents \"null\", or, the end\nof meaningful characters in the sequence. Hence, everytime that the algorithm produces a\n\"padding group\", this group is automatically mapped to `=`.\n\nAs another example, if you give the string \"0\" as input to a base64 encoder, this string is\ntranslated into the base64 sequence \"MA==\".\nThe character \"0\" is, in binary, the sequence `00110000`[^zero-note]. So, with the 6-bit transformation\nexposed in @fig-base64-algo1, this single character would produce these two 6-bit groups: `001100`, `000000`.\nThe remaining two 6-bit groups become \"padding groups\". That is why the last\ntwo characters in the output sequence (MA==) are `==`.\n\n\n[^zero-note]: Notice that, the character \"0\" is different than the actual number 0, which is simply zero in binary.\n\n### A base64 decoder {#sec-base64-decoder-algo}\n\nThe algorithm behind a base64 decoder is essentially the inverse process of a base64 encoder.\nA base64 decoder needs to translate base64 messages back into their original meaning,\ni.e., into the original sequence of binary data.\n\nA base64 decoder usually works on a window of 4 bytes. Because it wants to convert these 4 bytes\nback into the original sequence of 3 bytes, that was converted into 4 groups of 6 bits by the\nbase64 encoder. Remember, in a base64 decoder we are essentially reverting the process made\nby the base64 encoder.\n\nEach byte in the input string (the base64 encoded string) normally contributes to re-create\ntwo different bytes in the output (the original binary data).\nIn other words, each byte that comes out of a base64 decoder is created by transforming merging two different\nbytes in the input together. You can visualize this relationship in @fig-base64-algo2:\n\n![The logic behind a base64 decoder](./../Figures/base64-decoder-flow.png){#fig-base64-algo2}\n\nThe exact transformations, or, the exact steps applied to each byte from the input to transform them\ninto the bytes of the output, are a bit tricky to visualize in a figure like this. Because of that, I have\nsummarized these transformations as \"Some bit shifting and additions ...\" in the figure. These transformations\nwill be described in depth later.\n\nBesides that, if you look again in @fig-base64-algo2, you will notice that the character `=` was completely\nignored by the algorithm. Remember, this is just a special character that marks the end of meaningful characters\nin the base64 sequence. So, every `=` character in a base64 encoded sequence should be ignored by a base64 decoder.\n\n\n## Difference between encode and decode {#sec-encode-vs-decode}\n\nIf you don't have any previous experience with base64, you might not understand the differences\nbetween \"encode\" and \"decode\". Essentially, the terms \"encode\" and \"decode\" here\nhave the exact same meaning as they have in the field of encryption (i.e., they mean the same thing as \"encode\" and \"decode\" in hashing\nalgorithms, like the MD5 algorithm).\n\nThus, \"encode\" means that we want to encode, or, in other words, we want to translate some message into\nthe base64 encoding system. We want to produce the sequence of base64 characters that represent this\noriginal message in the base64 encoding system.\n\nIn contrast, \"decode\" represents the inverse process.\nWe want to decode, or, in other words, translate a base64 message back to its original content.\nSo, in this process we get a sequence of base64 characters as input, and produce as output,\nthe binary data that is represented by this sequence of base64 characters.\n\nAny base64 library is normally composed of these two parts: 1) the encoder, which is a function that encodes\n(i.e., it converts) any sequence of binary data into a sequence of base64 characters; 2) the decoder, which is a function\nthat converts a sequence of base64 characters back into the original sequence of binary data.\n\n\n\n## Calculating the size of the output {#sec-base64-length-out}\n\nOne task that we need to do is to calculate how much space we need to reserve for the\noutput, both of the encoder and decoder. This is simple math, and can be done easily in Zig\nbecause every array has its length (its number of elements) easily accesible by consulting\nthe `.len` property of the array.\n\nFor the encoder, the logic is the following: for each 3 bytes that we find in the input,\n4 new bytes are created in the output. So, we take the number of bytes in the input, divide it\nby 3, use a ceiling function, then, we multiply the result by 4. That way, we get the total\nnumber of bytes that will be produced by the encoder in its output.\n\nThe `_calc_encode_length()` function below encapsulates this logic.\nInside this function, we take the length of the input array,\nwe divide it by 3, and apply a ceil operation over the result by using the\n`divCeil()` function from the Zig Standard Library. Lastly, we multiply\nthe end result by 4 to get the answer we need.\n\nAlso, you might have notice that, if the input length is less than 3 bytes, then, the output length of the encoder is\nalways 4 bytes. This is the case for every input with less than 3 bytes, because, as I described in @sec-base64-encoder-algo,\nthe algorithm always produces enough \"padding-groups\" in the end result, to complete the 4 bytes window.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_encode_length(input: []const u8) !usize {\n    if (input.len < 3) {\n        return 4;\n    }\n    const n_groups: usize = try std.math.divCeil(\n        usize, input.len, 3\n    );\n    return n_groups * 4;\n}\n```\n:::\n\n\n\nNow, the logic to calculate the length of the output from the decoder is a little bit more complicated. But, it is basically\njust the inverse logic that we've used for the encoder: for each 4 bytes in the input, 3 bytes\nwill be produced in the output of the decoder. However, this time we need to\ntake the `=` character into account, which is always ignored by the decoder, as we described in @sec-base64-decoder-algo, and,\nin @fig-base64-algo2.\n\nIn essence, we take the length of the input and divide it by 4, then we apply a floor function on the result, then\nwe multiply the result by 3, and then, we subtract from the result how much times the character `=` is found\nin the input.\n\nThe function `_calc_decode_length()` exposed below summarizes this logic that we described. It's similar\nto the function `_calc_encode_length()`. Notice that the division part is twisted. Also notice that this time, we apply\na floor operation over the output of the division, by using the `divFloor()`\nfunction (instead of a ceiling operation with `divCeil()`).\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn _calc_decode_length(input: []const u8) !usize {\n    if (input.len < 4) {\n        return 3;\n    }\n\n    const n_groups: usize = try std.math.divFloor(\n        usize, input.len, 4\n    );\n    var multiple_groups: usize = n_groups * 3;\n    var i: usize = input.len - 1;\n    while (i > 0) : (i -= 1) {\n        if (input[i] == '=') {\n            multiple_groups -= 1;\n        } else {\n            break;\n        }\n    }\n\n    return multiple_groups;\n}\n```\n:::\n\n\n\n## Building the encoder logic {#sec-encoder-logic}\n\nIn this section, we can start building the logic behind the `encode()` function, which\nwill be responsible for encoding messages into the base64 encoding system.\nIf you are an anxious person, and you want to see now the full source code of the implementation\nfor this base64 encoder/decoder, you can find it at the `ZigExamples` folder in the official repository of\nthis book[^zig-base64-algo].\n\n[^zig-base64-algo]: .\n\n\n\n### The 6-bit transformation {#sec-6bit-transf}\n\nThe 6-bit transformation presented in @fig-base64-algo1 is the core part of the base64 encoder algorithm.\nBy understanding how this transformation is made in code, the rest of the algorithm becomes much simpler\nto comprehend.\n\nIn essence, this 6-bit transformation is made with the help of bitwise operators.\nBitwise operators are essential to any type of low-level operation that is done at the bit-level. For the specific case of the base64 algorithm,\nthe operators *bif shift to the left* (`<<`), *bit shift to the right* (`>>`), and the *bitwise and* (`&`) are used. They\nare the core solution for the 6-bit transformation.\n\nThere are 3 different scenarios that we need to take into account in this transformation. First, is the perfect scenario,\nwhere we have the perfect window of 3 bytes to work on. Second, we have the scenario where we have a window of only\ntwo bytes to work with. And last, we have the scenario where we have a window of one single byte.\n\nIn each of these 3 scenarios, the 6-bit transformation works a bit differently. To make the explanation\neasier, I will use the variable `output` to refer to the bytes in the output of the base64 encoder,\nand the variable `input` to refer to the bytes in the input of the encoder.\n\n\nSo, if you have the perfect window of 3 bytes, these are steps for the 6-bit transformation:\n\n1. `output[0]` is produced by moving the bits from `input[0]` two positions to the right.\n1. `output[1]` is produced by summing two components. First, take the last two bits from `input[0]`, then, move them four positions to the left. Second, move the bits from `input[1]` four positions to the right. Sum these two components.\n1. `output[2]` is produced by summing two components. First, take the last four bits from `input[1]`, then, move them two positions to the left. Second, move the bits from `input[2]` six positions to the right. Sum these two components.\n1. `output[3]` is produced by taking the last six bits from `input[2]`.\n\n\nThis is the perfect scenario, where we have a full window of 3 bytes to work on.\nJust to make things as clear as possible, the @fig-encoder-bitshift demonstrates visually how\nthe step 2 mentioned above works. So the 2nd byte in the `output` of the encoder, is made by taking the 1st byte (dark purple)\nand the 2nd byte (orange) from the input. You can see that, at the end of the process, we get a new\nbyte that contains the last 2 bits from the 1st byte in the `input`, and the first 4 bits\nfrom the 2nd byte in the `input`.\n\n![How the 2nd byte in the output of the encoder is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input.](../Figures/base64-encoder-bit-shift.png){#fig-encoder-bitshift}\n\nOn the other hand, we must be prepared for the instances where we do not have the perfect window of 3 bytes.\nIf you have a window of 2 bytes, then, the steps 3 and 4, which produces the bytes `output[2]` and `output[3]`, change a little bit,\nand they become:\n\n- `output[2]` is produced by taking the last 4 bits from `input[1]`, then, move them two positions to the left.\n- `output[3]` is the character `'='`.\n\n\nFinally, if you have a window of a single byte, then, the steps 2 to 4, which produces the bytes `output[1]`, `output[2]` and `output[3]` change,\nbecoming:\n\n- `output[1]` is produced by taking the last two bits from `input[0]`, then, move them four positions to the left.\n- `output[2]` and `output[3]` are the character `=`.\n\n\nIf these bullet points were a bit confusing for you, you may find the @tbl-transf-6bit more intuitive.\nThis table unifies all this logic into a simple table. Notice that\nthis table also provides the exact expression in Zig that creates the corresponding\nbyte in the output.\n\n\n::: {#tbl-transf-6bit}\n\n| Number of bytes in the window | Byte index in the output | In code                                    |\n|-------------------------------|--------------------------|--------------------------------------------|\n| 3                             | 0                        | input[0] >> 2                              |\n| 3                             | 1                        | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 3                             | 2                        | ((input[1] & 0x0f) << 2) + (input[2] >> 6) |\n| 3                             | 3                        | input[2] & 0x3f                            |\n| 2                             | 0                        | input[0] >> 2                              |\n| 2                             | 1                        | ((input[0] & 0x03) << 4) + (input[1] >> 4) |\n| 2                             | 2                        | ((input[1] & 0x0f) << 2)                   |\n| 2                             | 3                        | '='                                        |\n| 1                             | 0                        | input[0] >> 2                              |\n| 1                             | 1                        | ((input[0] & 0x03) << 4)                   |\n| 1                             | 2                        | '='                                        |\n| 1                             | 3                        | '='                                        |\n\n: How the 6-bit transformation translates into code in different window settings.\n\n:::\n\n\n\n\n\n\n### Bit-shifting in Zig\n\nBit-shifting in Zig works similarly to bit-shifting in C.\nAll bitwise operators that exist in C are available in Zig.\nHere, in the base64 encoder algorithm, they are essential\nto produce the result we want.\n\nFor those who are not familiar with these operators, they are\noperators that operates at the bit-level of your values.\nThis means that these operators takes the bits that form the value\nyou have, and change them in some way. This ultimately also changes\nthe value itself, because the binary representation of this value\nchanges.\n\nWe have already seen in @fig-encoder-bitshift the effect produced by a bit-shift.\nBut let's use the first byte in the output of the base64 encoder as another example of what\nbit-shifting means. This is the easiest byte of the 4 bytes in the output\nto build. Because we only need to move the bits from the first byte in the input two positions to the right,\nwith the *bit shift to the right* (`>>`) operator.\n\nIf we take the string \"Hi\" that we used in @fig-base64-algo1 as an example, the first byte in\nthis string is \"H\", which is the sequence `01001000` in binary.\nIf we move the bits of this byte, two places to the right, we get the sequence `00010010` as result.\nThis binary sequence is the value `18` in decimal, and also, the value `0x12` in hexadecimal.\nNotice that the first 6 bits of \"H\" were moved to the end of the byte.\nWith this operation, we get the first byte of the output.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const input = \"Hi\";\n    try stdout.print(\"{d}\\n\", .{input[0] >> 2});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n18\n```\n\n\n:::\n:::\n\n\nIf you recall @fig-base64-algo1, the first byte present in the output should\nbe equivalent to the 6-bit group `010010`. Although being visually different, the\nsequences `010010` and `00010010` are semantically equal. They mean the same thing.\nThey both represent the number 18 in decimal, and the value `0x12` in hexadecimal.\n\nSo, don't take the \"6-bit group\" factor so seriously. We do not need necessarily to\nget a 6-bit sequence as result. As long as the meaning of the 8-bit sequence we get is the same\nof the 6-bit sequence, we are in the clear.\n\n\n\n### Selecting specific bits with the `&` operator\n\nIf you comeback to @sec-6bit-transf, you will see that, in order to produce\nthe second and third bytes in the output, we need to select specific\nbits from the first and second bytes in the input string. But how\ncan we do that? The answer relies on the *bitwise and* (`&`) operator.\n\nThe @fig-encoder-bitshift already showed you what effect this `&` operator\nproduces in the bits of its operands. But let's make a clear description of it.\n\nIn summary, the `&` operator performs a logical conjunction operation\nbetween the bits of its operands. In more details, the operator `&`\ncompares each bit of the first operand to the corresponding bit of the second operand.\nIf both bits are 1, the corresponding result bit is set to 1.\nOtherwise, the corresponding result bit is set to 0 [@microsoftbitwiseand].\n\nSo, if we apply this operator to the binary sequences `1000100` and `00001101`\nthe result of this operation is the binary sequence `00000100`. Because only\nat the sixth position in both binary sequences we had a 1 value. So any\nposition where we do not have both binary sequences setted to 1, we get\na 0 bit in the resulting binary sequence.\n\nWe lose information about the original bit values\nfrom both sequences in this case. Because we no longer know\nif this 0 bit in the resulting binary sequence was produced by\ncombining 0 with 0, or 1 with 0, or 0 with 1.\n\nAs an example, suppose you have the binary sequence `10010111`, which is the number 151 in decimal. How\ncan we get a new binary sequence which contains only the third and\nfourth bits of this sequence?\n\nWe just need to combine this sequence with `00110000` (is `0x30` in hexadecimal) using the `&` operator.\nNotice that only the third and fourth positions in this binary sequence is setted to 1. As a consequence, only the\nthird and fourth values of both binary sequences are potentially preserved in the output. All the remaining positions\nare setted to zero in the output sequence, which is `00010000` (is the number 16 in decimal).\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const bits = 0b10010111;\n    try stdout.print(\"{d}\\n\", .{bits & 0b00110000});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n16\n```\n\n\n:::\n:::\n\n\n\n\n### Allocating space for the output\n\nAs I described in @sec-stack, to store an object in the stack,\nthis object needs to have a known and fixed length at compile-time. This is an important\nlimitation for our base64 encoder/decoder case. Because the size of\nthe output (from both the encoder and decoder) depends\ndirectly on the size of the input.\n\nHaving this in mind, we cannot know at compile time which is\nthe size of the output for both the encoder and decoder.\nSo, if we can't know the size of the output at compile time,\nthis means that we cannot store the output for both the encoder\nand decoder in the stack.\n\nConsequently, we need to store this output on the heap,\nand, as I commented in @sec-heap, we can only\nstore objects in the heap by using allocator objects.\nSo, one the arguments to both the `encode()` and `decode()`\nfunctions, needs to be an allocator object, because\nwe know for sure that, at some point inside the body of these\nfunctions, we need to allocate space on the heap to\nstore the output of these functions.\n\nThat is why, both the `encode()` and `decode()` functions that I\npresent in this book, have an argument called `allocator`,\nwhich receives a allocator object as input, identified by\nthe type `std.mem.Allocator` from the Zig Standard Library.\n\n\n\n### Writing the `encode()` function\n\nNow that we have a basic understanding on how the bitwise operators work, and how\nexactly they help us to achieve the result we want to achieve. We can now encapsulate\nall the logic that we have described in @fig-base64-algo1 and @tbl-transf-6bit into a nice\nfunction that we can add to our `Base64` struct definition, that we started in @sec-base64-table.\n\nYou can find the `encode()` function below. Notice that the first argument of this function,\nis the `Base64` struct itself. Therefore, this argument clearly signals\nthat this function is a method from the `Base64` struct.\n\nBecause the `encode()` function itself is fairly long,\nI intentionally omitted the `Base64` struct definition in this source code,\njust for brevity reasons. So, just remember that this function is a public function (or a public method) from the\n`Base64` struct.\n\nFurthermore, this `encode()` function has two other arguments:\n\n1. `input` is the input sequence of characters that you want to encode in base64;\n1. `allocator` is an allocator object to use in the necessary memory allocations.\n\nI described everything you need to know about allocator objects in @sec-allocators.\nSo, if you are not familiar with them, I highly recommend you to comeback to\nthat section, and read it.\nBy looking at the `encode()` function, you will see that we use this\nallocator object to allocate enough memory to store the output of\nthe encoding process.\n\nThe main for loop in the function is responsible for iterating through the entire input string.\nIn every iteration, we use a `count` variable to count how many iterations we had at the\nmoment. When `count` reaches 3, then, we try to encode the 3 characters (or bytes) that we have accumulated\nin the temporary buffer object (`buf`).\n\nAfter encoding these 3 characters and storing the result in the `output` variable, we reset\nthe `count` variable to zero, and start to count again on the next iteration of the loop.\nIf the loop hits the end of the string, and, the `count` variable is less than 3, then, it means that\nthe temporary buffer contains the last 1 or 2 bytes from the input.\nThat is why we have two `if` statements after the for loop. To deal which each possible case.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn encode(self: Base64,\n              allocator: std.mem.Allocator,\n              input: []const u8) ![]u8 {\n\n    if (input.len == 0) {\n        return \"\";\n    }\n\n    const n_out = try _calc_encode_length(input);\n    var out = try allocator.alloc(u8, n_out);\n    var buf = [3]u8{ 0, 0, 0 };\n    var count: u8 = 0;\n    var iout: u64 = 0;\n\n    for (input, 0..) |_, i| {\n        buf[count] = input[i];\n        count += 1;\n        if (count == 3) {\n            out[iout] = self._char_at(buf[0] >> 2);\n            out[iout + 1] = self._char_at(\n                ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n            );\n            out[iout + 2] = self._char_at(\n                ((buf[1] & 0x0f) << 2) + (buf[2] >> 6)\n            );\n            out[iout + 3] = self._char_at(buf[2] & 0x3f);\n            iout += 4;\n            count = 0;\n        }\n    }\n\n    if (count == 1) {\n        out[iout] = self._char_at(buf[0] >> 2);\n        out[iout + 1] = self._char_at(\n            (buf[0] & 0x03) << 4\n        );\n        out[iout + 2] = '=';\n        out[iout + 3] = '=';\n    }\n\n    if (count == 2) {\n        out[iout] = self._char_at(buf[0] >> 2);\n        out[iout + 1] = self._char_at(\n            ((buf[0] & 0x03) << 4) + (buf[1] >> 4)\n        );\n        out[iout + 2] = self._char_at(\n            (buf[1] & 0x0f) << 2\n        );\n        out[iout + 3] = '=';\n        iout += 4;\n    }\n\n    return out;\n}\n```\n:::\n\n\n\n\n## Building the decoder logic {#sec-decoder-logic}\n\nNow, we can focus on writing the base64 decoder logic. Remember from @fig-base64-algo2 that,\na base64 decoder does the inverse process of an encoder. So, all we need to do, is to\nwrite a `decode()` function that performs the inverse process that I exposed in @sec-encoder-logic.\n\n\n### Mapping base64 characters to their indexes {#sec-map-base64-index}\n\nOne thing that we need to do, in order to decode a base64-encoded message, is to calculate\nthe index in the base64 scale of every base64 character that we encounter in the decoder input.\n\nIn other words, the decoder receives as input, a sequence of base64 characters. We need\nto translate this sequence of characters into a sequence of indexes. These indexes\nare the index of each character in the base64 scale. This way, we get the value/byte\nthat was calculated in the 6-bit transformation step of the encoder process.\n\nThere are probably better/faster ways to calculate this, especially using a \"divide and conquer\"\ntype of strategy. But for now, I am satisfied with a simple and \"brute force\" type of strategy.\nThe `_char_index()` function below contains this strategy.\n\nWe are essentially looping through the *lookup table* with the base64 scale,\nand comparing the character we got with each character in the base64 scale.\nIf these characters match, then, we return the index of this character in the\nbase64 scale as the result.\n\nNotice that, if the input character is `'='`, the function returns the index 64, which is\n\"out of range\" in the scale. But, as I described in @sec-base64-scale,\nthe character `'='` does not belong to the base64 scale itself.\nIt's a special and meaningless character in base64.\n\nAlso notice that this `_char_index()` function is a method from our `Base64` struct,\nbecause of the `self` argument. Again, I have omitted the `Base64` struct definition in this example\nfor brevity reasons.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn _char_index(self: Base64, char: u8) u8 {\n    if (char == '=')\n        return 64;\n    var index: u8 = 0;\n    for (0..63) |i| {\n        if (self._char_at(i) == char)\n            break;\n        index += 1;\n    }\n\n    return index;\n}\n```\n:::\n\n\n\n\n### The 6-bit transformation\n\nOnce again, the core part of the algorithm is the 6-bit transformation.\nIf we understand the necessary steps to perform this transformation, the rest\nof the algorithm becomes much easier.\n\nFirst of all, before we actually go to the 6-bit transformation,\nwe need to make sure that we use `_char_index()` to convert the sequence of base64 characters\ninto a sequence of indexes. So the snippet below is important for the job that will be done.\nThe result of `_char_index()` is stored in a temporary buffer, and this temporary buffer\nis what we are going to use in the 6-bit transformation, instead of the actual `input` object.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (0..input.len) |i| {\n    buf[i] = self._char_index(input[i]);\n}\n```\n:::\n\n\nNow, instead of producing 4 bytes (or 4 characters) as output per each window of 3 characters in the input,\na base64 decoder produces 3 bytes (or 3 characters) as output per each window of 4 characters in the input.\nOnce again, is the inverse process.\n\nSo, the steps to produce the 3 bytes in the output are:\n\n1. `output[0]` is produced by summing two components. First, move the bits from `buf[0]` two positions to the left. Second, move the bits from `buf[1]` 4 positions to the right. Then, sum these two components.\n1. `output[1]` is produced by summing two components. First, move the bits from `buf[1]` four positions to the left. Second, move the bits from `buf[2]` 2 positions to the right. Then, sum these two components.\n1. `output[2]` is produced by summing two components. First, move the bits from `buf[2]` six positions to the left. Then, you sum the result with `buf[3]`.\n\n\nBefore we continue, let's try to visualize how these transformations make the original bytes that we had\nbefore the encoding process. First, think back to the 6-bit transformation performed by the encoder exposed in @sec-encoder-logic.\nThe first byte in the output of the encoder is produced by moving the bits in the first byte of the input two positions to the right.\n\nIf for example the first byte in the input of the encoder was the sequence `ABCDEFGH`, then, the first byte in the output of the encoder would be\n`00ABCDEF` (this sequence would be the first byte in the input of the decoder). Now, if the second byte in the input of the encoder was the sequence\n`IJKLMNOP`, then, the second byte in the encoder output would be `00GHIJKL` (as we demonstrated in @fig-encoder-bitshift).\n\nHence, if the sequences `00ABCDEF` and `00GHIJKL` are the first and second bytes, respectively, in the input of the decoder, the\n@fig-decoder-bitshift demonstrates visually how these two bytes are transformed into the first byte of the output of the decoder.\nNotice that the output byte is the sequence `ABCDEFGH`, which is the original byte from the input of the encoder.\n\n![How the 1st byte in the decoder output is produced from the 1st byte (dark purple) and the 2nd byte (orange) of the input](../Figures/base64-decoder-bit-shift.png){#fig-decoder-bitshift}\n\nThe @tbl-6bit-decode presents how the three steps described earlier translate into Zig code:\n\n\n\n::: {#tbl-6bit-decode}\n\n| Byte index in the output | In code                       |\n|--------------------------|-------------------------------|\n| 0                        | (buf[0] << 2) + (buf[1] >> 4) |\n| 1                        | (buf[1] << 4) + (buf[2] >> 2) |\n| 2                        | (buf[2] << 6) + buf[3]        |\n\n: The necessary steps for the 6-transformation in the decode process.\n\n\n:::\n\n\n\n\n\n\n\n### Writing the `decode()` function\n\nThe `decode()` function below contains the entire decoding process.\nWe first calculate the size of the output, with\n`_calc_decode_length()`, then, we allocate enough memory for this output with\nthe allocator object.\n\nThree temporary variables are created: 1) `count`, to hold the window count\nin each iteration of the for loop; 2) `iout`, to hold the current index in the output;\n3) `buf`, which is the temporary buffer that holds the base64 indexes to be\nconverted through the 6-bit transformation.\n\nThen, in each iteration of the for loop we fill the temporary buffer with the current\nwindow of bytes. When `count` hits the number 4, then, we have a full window of\nindexes in `buf` to be converted, and then, we apply the 6-bit transformation\nover the temporary buffer.\n\nNotice that we check if the indexes 2 and 3 in the temporary buffer are the number 64, which, if you recall\nfrom @sec-map-base64-index, is when the `_calc_index()` function receives a `'='` character\nas input. So, if these indexes are equal to the number 64, the `decode()` function knows\nthat it can simply ignore these indexes. They are not converted because, as I described before,\nthe character `'='` has no meaning, despite being the end of meaningful characters in the sequence.\nSo we can safely ignore them when they appear in the sequence.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn decode(self: Base64,\n          allocator: std.mem.Allocator,\n          input: []const u8) ![]u8 {\n\n    if (input.len == 0) {\n        return \"\";\n    }\n    const n_output = try _calc_decode_length(input);\n    var output = try allocator.alloc(u8, n_output);\n    var count: u8 = 0;\n    var iout: u64 = 0;\n    var buf = [4]u8{ 0, 0, 0, 0 };\n\n    for (0..input.len) |i| {\n        buf[count] = self._char_index(input[i]);\n        count += 1;\n        if (count == 4) {\n            output[iout] = (buf[0] << 2) + (buf[1] >> 4);\n            if (buf[2] != 64) {\n                output[iout + 1] = (buf[1] << 4) + (buf[2] >> 2);\n            }\n            if (buf[3] != 64) {\n                output[iout + 2] = (buf[2] << 6) + buf[3];\n            }\n            iout += 3;\n            count = 0;\n        }\n    }\n\n    return output;\n}\n```\n:::\n\n\n\n## The end result\n\nNow that we have both `decode()` and `encode()` implemented. We have a fully functioning\nbase64 encoder/decoder implemented in Zig. Here is an usage example of our\n`Base64` struct with the `encode()` and `decode()` methods that we have implemented.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar memory_buffer: [1000]u8 = undefined;\nvar fba = std.heap.FixedBufferAllocator.init(\n    &memory_buffer\n);\nconst allocator = fba.allocator();\n\nconst text = \"Testing some more stuff\";\nconst etext = \"VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=\";\nconst base64 = Base64.init();\nconst encoded_text = try base64.encode(\n    allocator, text\n);\nconst decoded_text = try base64.decode(\n    allocator, etext\n);\ntry stdout.print(\n    \"Encoded text: {s}\\n\", .{encoded_text}\n);\ntry stdout.print(\n    \"Decoded text: {s}\\n\", .{decoded_text}\n);\n```\n:::\n\n\n```\nEncoded text: VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=\nDecoded text: Testing some more stuff\n```\n\nYou can also see the full source code at once, by visiting the official repository of this book[^repo].\nMore precisely inside the `ZigExamples` folder[^zig-base64-algo].\n\n[^repo]: \n",
    +    "supporting": [],
         "filters": [
           "rmarkdown/pagebreak.lua"
         ],
    diff --git a/_freeze/Chapters/01-memory/execute-results/epub.json b/_freeze/Chapters/01-memory/execute-results/epub.json
    deleted file mode 100644
    index eda130d2..00000000
    --- a/_freeze/Chapters/01-memory/execute-results/epub.json
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -{
    -  "hash": "55899a376e1db53689b78790e55a518d",
    -  "result": {
    -    "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n# Memory and Allocators\n\n\nIn this chapter, we will talk about memory. How does Zig control memory? What\ncommon tools are used? Are there any important aspects that make memory\ndifferent/special in Zig? You will find the answers here.\n\nComputers fundamentally rely on memory to function. This memory acts as a temporary storage\nspace for the data and values generated during computations. Without memory, the core\nconcepts of \"variables\" and \"objects\" in programming languages would be impossible.\n\n\n\n\n## Memory spaces\n\nEvery object that you create in your Zig source code needs to be stored somewhere,\nin your computer's memory. Depending on where and how you define your object, Zig\nwill use a different \"memory space\", or a different\ntype of memory to store this object.\n\nEach type of memory normally serves for different purposes.\nIn Zig, there are 3 types of memory (or 3 different memory spaces) that we care about. They are:\n\n- Global data register (or the \"global data section\");\n- Stack;\n- Heap;\n\n\n### Compile-time known versus runtime known {#sec-compile-time}\n\nOne strategy that Zig uses to decide where it will store each object that you declare, is by looking\nat the value of this particular object. More specifically, by investigating if this value is\nknown at \"compile-time\" or at \"runtime\".\n\nWhen you write a program in Zig, the values of some of the objects that you write in your program are *known\nat compile time*. Meaning that, when you compile your Zig source code, during the compilation process,\nthe `zig` compiler can figure out the exact value of a particular object\nthat exists in your source code.\nKnowing the length (or the size) of each object is also important. So the length (or the size) of each object that you write in your program is,\nin some cases, *known at compile time*.\n\nThe `zig` compiler cares more about knowing the length (or the size) of a particular object\n, than to know its actual value. But, if the `zig` compiler knows the value of the object, then, it\nautomatically knows the size of this object. Because it can simply calculate the\nsize of the object by looking at the size of the value.\n\nTherefore, the priority for the `zig` compiler is to discover the size of each object in your source code.\nIf the value of the object in question is known at compile-time, then, the `zig` compiler\nautomatically knows the size/length of this object. But if the value of this object is not\nknown at compile-time, then, the size of this object is only known at compile-time if,\nand only if, the type of this object has a known fixed size.\n\nIn order for a type to have a known fixed size, this type must have data members whose size is fixed.\nIf this type includes, for example, a variable sized array in it, then, this type does not have a known\nfixed size. Because this array can have any size at runtime\n(i.e., it can be an array of 2 elements, or 50 elements, or 1 thousand elements, etc.).\n\nFor example, a string object, which internally is an array of constant u8 values (`[]const u8`)\nhas a variable size. It can be a string object with 100 or 500 characters in it. If we do not\nknow at compile-time, which exact string will be stored inside this string object, then, we cannot calculate\nthe size of this string object at compile-time. So, any type, or any struct declaration that you make, that\nincludes a string data member that does not have an explicit fixed size, makes this type, or this\nnew struct that you are declaring, a type that does not have a known fixed size at compile-time.\n\nIn contrast, if the type of this struct that you are declaring, includes a data member that is an array,\nbut this array has a known fixed size, like `[60]u8` (which declares an array of 60 `u8` values), then,\nthis type, or, this struct that you are declaring, becomes a type with a known fixed size at compile-time.\nAnd because of that, in this case, the `zig` compiler does not need to know at compile-time the exact value of\nany object of this type. Since the compiler can find the necessary size to store this object by\nlooking at the size of its type.\n\n\nLet's look at an example. In the source code below, we have two constant objects (`name` and `array`) declared.\nBecause the values of these particular objects are written down, in the source code itself (`\"Pedro\"`\nand the number sequence from 1 to 4), the `zig` compiler can easily discover the values of these constant\nobjects (`name` and `array`) during the compilation process.\nThis is what \"known at compile time\" means. It refers to any object that you have in your Zig source code\nwhose value can be identified at compile time.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn input_length(input: []const u8) usize {\n    const n = input.len;\n    return n;\n}\n\npub fn main() !void {\n    const name = \"Pedro\";\n    const array = [_]u8{1, 2, 3, 4};\n    _ = name; _ = array;\n}\n```\n:::\n\n\n\nThe other side of the spectrum are objects whose values are not known at compile time.\nFunction arguments are a classic example of this. Because the value of each function\nargument depends on the value that you assign to this particular argument,\nwhen you call the function.\n\nFor example, the function `input_length()` contains an argument named `input`, which is an array of constant `u8` integers (`[]const u8`).\nIt's impossible to know the value of this particular argument at compile time. And it also is impossible to know the size/length\nof this particular argument. Because it's an array that does not have a fixed size specified explicitly in the argument type annotation.\n\nSo, we know that this `input` argument will be an array of `u8` integers. But we do not know at compile-time, its value, and neither its size.\nThis information is known only at runtime, which is the period of time when you program is executed.\nAs a consequence, the value of the expression `input.len` is also known only at runtime.\nThis is an intrinsic characteristic of any function. Just remember that the value of function arguments is usually not \"compile-time known\".\n\nHowever, as I mentioned earlier, what really matters to the compiler is to know the size of the object\nat compile-time, and not necessarily its value. So, although we don't know the value of the object `n`, which is the result of the expression\n`input.len`, at compile-time, we do know its size. Because the expression `input.len` always returns a value of type `usize`,\nand the type `usize` has a known fixed size.\n\n\n\n### Global data register\n\nThe global data register is a specific section of the executable of your Zig program, that is responsible\nfor storing any value that is known at compile time.\n\nEvery constant object whose value is known at compile time that you declare in your source code,\nis stored in the global data register. Also, every literal value that you write in your source code,\nsuch as the string `\"this is a string\"`, or the integer `10`, or a boolean value such as `true`,\nis also stored in the global data register.\n\nHonestly, you don't need to care much about this memory space. Because you can't control it,\nyou can't deliberately access it or use it for your own purposes.\nAlso, this memory space does not affect the logic of your program.\nIt simply exists in your program.\n\n\n### Stack vs Heap\n\nIf you are familiar with systems programming, or just low-level programming in general, you\nprobably have heard of the \"duel\" between Stack vs Heap. These are two different types of memory,\nor different memory spaces, which are both available in Zig.\n\nThese two types of memory don't actually duel with\neach other. This is a common mistake that beginners have, when seeing \"x vs y\" styles of\ntabloid headlines. These two types of memory are actually complementary to each other.\nSo, in almost every Zig program that you ever write, you will likely use a combination of both.\nI will describe each memory space in detail over the next sections. But for now, I just want to\nstablish the main difference between these two types of memory.\n\nIn essence, the stack memory is normally used to store values whose length is fixed and known\nat compile time. In contrast, the heap memory is a *dynamic* type of memory space, meaning that, it's\nused to store values whose length might grow during the execution (runtime) of your program [@jenny2022].\n\nLengths that grow during runtime are intrinsically associated with \"runtime known\" type of values.\nIn other words, if you have an object whose length might grow during runtime, then, the length\nof this object becomes not known at compile time. If the length is not known at compile-time,\nthe value of this object also becomes not known at compile-time.\nThese types of objects should be stored in the heap memory space, which is\na dynamic memory space, which can grow or shrink to fit the size of your objects.\n\n\n\n### Stack {#sec-stack}\n\nThe stack is a type of memory that uses the power of the *stack data structure*, hence the name.\nA \"stack\" is a type of *data structure* that uses a \"last in, first out\" (LIFO) mechanism to store the values\nyou give it to. I imagine you are familiar with this data structure.\nBut, if you are not, the [Wikipedia page](https://en.wikipedia.org/wiki/Stack_(abstract_data_type))[^wiki-stack]\n, or, the [Geeks For Geeks page](https://www.geeksforgeeks.org/stack-data-structure/)[^geek-stack] are both\nexcellent and easy resources to fully understand how this data structure works.\n\n[^wiki-stack]: \n[^geek-stack]: \n\nSo, the stack memory space is a type of memory that stores values using a stack data structure.\nIt adds and removes values from the memory by following a \"last in, first out\" (LIFO) principle.\n\nEvery time you make a function call in Zig, an amount of space in the stack is\nreserved for this particular function call [@jenny2022; @zigdocs].\nThe value of each function argument given to the function in this function call is stored in this\nstack space. Also, every local object that you declare inside the function scope is\nusually stored in this same stack space.\n\n\nLooking at the example below, the object `result` is a local object declared inside the scope of the `add()`\nfunction. Because of that, this object is stored inside the stack space reserved for the `add()` function.\nThe `r` object (which is declared outside of the `add()` function scope) is also stored in the stack.\nBut since it's declared in the \"outer\" scope, this object is stored in the\nstack space that belongs to this outer scope.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn add(x: u8, y: u8) u8 {\n    const result = x + y;\n    return result;\n}\n\npub fn main() !void {\n    const r = add(5, 27);\n    _ = r;\n}\n```\n:::\n\n\n\n\nSo, any object that you declare inside the scope of a function is always stored inside\nthe space that was reserved for that particular function in the stack memory. This\nalso counts for any object declared inside the scope of your `main()` function for example.\nAs you would expect, in this case, they\nare stored inside the stack space reserved for the `main()` function.\n\nOne very important detail about the stack memory is that **it frees itself automatically**.\nThis is very important, remember that. When objects are stored in the stack memory,\nyou don't have the work (or the responsibility) of freeing/destroying these objects.\nBecause they will be automatically destroyed once the stack space is freed at the end of the function scope.\n\nSo, once the function call returns (or ends, if you prefer to call it this way)\nthe space that was reserved in the stack is destroyed, and all of the objects that were in that space goes away with it.\nThis mechanism exists because this space, and the objects within it, are not necessary anymore,\nsince the function \"finished its business\".\nUsing the `add()` function that we exposed above as an example, it means that the object `result` is automatically\ndestroyed once the function returns.\n\n::: {.callout-important}\nLocal objects that are stored in the stack space of a function are automatically\nfreed/destroyed at the end of the function scope.\n:::\n\n\nThis same logic applies to any other special structure in Zig that has its own scope by surrounding\nit with curly braces (`{}`).\nFor loops, while loops, if else statements, etc. For example, if you declare any local\nobject in the scope of a for loop, this local object is accessible only within the scope\nof this particular for loop. Because once the scope of this for loop ends, the space in the stack\nreserved for this for loop is freed.\nThe example below demonstrates this idea.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This does not compile successfully!\nconst a = [_]u8{0, 1, 2, 3, 4};\nfor (0..a.len) |i| {\n    const index = i;\n    _ = index;\n}\n// Trying to use an object that was\n// declared in the for loop scope,\n// and that does not exist anymore.\nstd.debug.print(\"{d}\\n\", .{index});\n```\n:::\n\n\n\n\n\nOne important consequence of this mechanism is that, once the function returns, you can no longer access any memory\naddress that was inside the space in the stack reserved for this particular function. Because this space was\ndestroyed. This means that, if this local object is stored in the stack,\nyou cannot make a function that **returns a pointer to this object**.\n\nThink about that for a second. If all local objects in the stack are destroyed at the end of the function scope, why\nwould you even consider returning a pointer to one of these objects? This pointer is at best,\ninvalid, or, more likely, \"undefined\".\n\nIn conclusion, it's totally fine to write a function that returns the local object\nitself as result, because then, you return the value of that object as the result.\nBut, if this local object is stored in the stack, you should never write a function\nthat returns a pointer to this local object. Because the memory address pointed by the pointer\nno longer exists.\n\n\nSo, using again the `add()` function as an example, if you rewrite this function so that it\nreturns a pointer to the local object `result`, the `zig` compiler will actually compile\nyour program, with no warnings or errors. At first glance, it looks like this is good code\nthat works as expected. But this is a lie!\n\nIf you try to take a look at the value inside of the `r` object,\nor, if you try to use this `r` object in another expression\nor function call, then, you would have undefined behaviour, and major\nbugs in your program [@zigdocs, see \"Lifetime and Ownership\"[^life] and \"Undefined Behaviour\"[^undef] sections].\n\n[^life]: \n[^undef]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn add(x: u8, y: u8) *const u8 {\n    const result = x + y;\n    return &result;\n}\n\npub fn main() !void {\n    // This code compiles successfully. But it has\n    // undefined behaviour. Never do this!!!\n    // The `r` object is undefined!\n    const r = add(5, 27); _ = r;\n}\n```\n:::\n\n\n\nThis \"invalid pointer to stack variable\" problem is well known across many programming language communities.\nIf you try to do the same thing, for example, in a C or C++ program (i.e., returning an address to\na local object stored in the stack), you would also get undefined behaviour\nin the program.\n\n::: {.callout-important}\nIf a local object in your function is stored in the stack, you should never\nreturn a pointer to this local object from the function. Because\nthis pointer will always become undefined after the function returns, since the stack space of the function\nis destroyed at the end of its scope.\n:::\n\nBut what if you really need to use this local object in some way after your function returns?\nHow can you do this? The answer is: \"in the same way you would do if this were a C or C++ program. By returning\nan address to an object stored in the heap\". The heap memory has a much more flexible lifecycle,\nand allows you to get a valid pointer to a local object of a function that already returned\nfrom its scope.\n\n\n### Heap {#sec-heap}\n\nOne important limitation of the stack, is that, only objects whose length/size is known at compile-time can be\nstored in it. In contrast, the heap is a much more dynamic\n(and flexible) type of memory. It's the perfect type of memory to use\nfor objects whose size/length might grow during the execution of your program.\n\nVirtually any application that behaves as a server is a classic use case of the heap.\nA HTTP server, a SSH server, a DNS server, a LSP server, ... any type of server.\nIn summary, a server is a type of application that runs for long periods of time,\nand that serves (or \"deals with\") any incoming request that reaches this particular server.\n\nThe heap is a good choice for this type of system, mainly because the server does not know upfront\nhow many requests it will receive from users, while it is active. It could be a single request,\n5 thousand requests, or even zero requests.\nThe server needs to have the ability to allocate and manage its memory according to how many requests it receives.\n\nAnother key difference between the stack and the heap, is that the heap is a type\nof memory that you, the programmer, have complete control over. This makes the heap a\nmore flexible type of memory, but it also makes it harder to work with. Because you,\nthe programmer, is responsible for managing everything related to it. Including where the memory is allocated,\nhow much memory is allocated, and where this memory is freed.\n\n> Unlike stack memory, heap memory is allocated explicitly by programmers and it won’t be deallocated until it is explicitly freed [@jenny2022].\n\nTo store an object in the heap, you, the programmer, needs to explicitly tells Zig to do so,\nby using an allocator to allocate some space in the heap. In @sec-allocators, I will present how you can use allocators to allocate memory\nin Zig.\n\n::: {.callout-important}\nEvery memory you allocate in the heap needs to be explicitly freed by you, the programmer.\n:::\n\nThe majority of allocators in Zig do allocate memory on the heap. But some exceptions to this rule are\n`ArenaAllocator()` and `FixedBufferAllocator()`. The `ArenaAllocator()` is a special\ntype of allocator that works in conjunction with a second type of allocator.\nOn the other side, the `FixedBufferAllocator()` is an allocator that works based on\nbuffer objects created on the stack. This means that the `FixedBufferAllocator()` makes\nallocations only on the stack.\n\n\n\n\n### Summary\n\nAfter discussing all of these boring details, we can quickly recap what we learned.\nIn summary, the Zig compiler will use the following rules to decide where each\nobject you declare is stored:\n\n1. every literal value (such as `\"this is string\"`, `10`, or `true`) is stored in the global data section.\n1. every constant object (`const`) whose value **is known at compile-time** is also stored in the global data section.\n1. every object (constant or not) whose length/size **is known at compile time** is stored in the stack space for the current scope.\n1. if an object is created with the method `alloc()` or `create()` of an allocator object, this object is stored in the memory space used by this particular allocator object. Most of allocators available in Zig use the heap memory, so, this object is likely stored in the heap (`FixedBufferAllocator()` is an exception to that).\n1. the heap can only be accessed through allocators. If your object was not created through the `alloc()` or `create()` methods of an allocator object, then, it is most certainly not an object stored in the heap.\n\n\n## Stack overflows {#sec-stack-overflow}\n\nAllocating memory on the stack is generally faster than allocating it on the heap.\nBut this better performance comes with many restrictions. We have already discussed\nmany of these restrictions of the stack in @sec-stack. But there is one more important\nlimitation that I want to talk about, which is the size of the stack itself.\n\nThe stack is limited in size. This size varies from computer to computer, and it depends on\na lot of things (the computer architecture, the operating system, etc.). Nevertheless, this size is usually\nnot that big. This is why we normally use the stack to store only temporary and small objects in memory.\n\nIn essence, if you try to make an allocation on the stack, that is so big that exceeds the stack size limit,\na *stack overflow* happens, and your program just crashes as a result of that. In other words, a stack overflow happens when\nyou attempt to use more space than is available on the stack.\n\nThis type of problem is very similar to a *buffer overflow*, i.e., you are trying to use more space\nthan is available in the \"buffer object\". However, a stack overflow always causes your program to crash,\nwhile a buffer overflow does not always cause your program to crash (although it often does).\n\nYou can see an example of a stack overflow in the example below. We are trying to allocate a very big array of `u64` values\non the stack. You can see below that this program does not run successfully, because it crashed\nwith a \"segmentation fault\" error message.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar very_big_alloc: [1000 * 1000 * 24]u64 = undefined;\n@memset(very_big_alloc[0..], 0);\n```\n:::\n\n\n\n```\nSegmentation fault (core dumped)\n```\n\nThis segmentation fault error is a result of the stack overflow that was caused by the big\nmemory allocation made on the stack, to store the `very_big_alloc` object.\nThis is why very big objects are usually stored on the heap, instead of the stack.\n\n\n\n## Allocators {#sec-allocators}\n\nOne key aspect about Zig, is that there are \"no hidden-memory allocations\" in Zig.\nWhat that really means, is that \"no allocations happen behind your back in the standard library\" [@zigguide].\n\nThis is a known problem, especially in C++. Because in C++, there are some operators that do allocate\nmemory behind the scene, and there is no way for you to know that, until you actually read the\nsource code of these operators, and find the memory allocation calls.\nMany programmers find this behaviour annoying and hard to keep track of.\n\nBut, in Zig, if a function, an operator, or anything from the standard library\nneeds to allocate some memory during its execution, then, this function/operator needs to receive (as input) an allocator\nprovided by the user, to actually be able to allocate the memory it needs.\n\nThis creates a clear distinction between functions that \"do not\" from those that \"actually do\"\nallocate memory. Just look at the arguments of this function.\nIf a function, or operator, has an allocator object as one of its inputs/arguments, then, you know for\nsure that this function/operator will allocate some memory during its execution.\n\nAn example is the `allocPrint()` function from the Zig Standard Library. With this function, you can\nwrite a new string using format specifiers. So, this function is, for example, very similar to the function `sprintf()` in C.\nIn order to write such a new string, the `allocPrint()` function needs to allocate some memory to store the\noutput string.\n\nThat is why, the first argument of this function is an allocator object that you, the user/programmer, gives\nas input to the function. In the example below, I am using the `GeneralPurposeAllocator()` as my allocator\nobject. But I could easily use any other type of allocator object from the Zig Standard Library.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nconst name = \"Pedro\";\nconst output = try std.fmt.allocPrint(\n    allocator,\n    \"Hello {s}!!!\",\n    .{name}\n);\ntry stdout.print(\"{s}\\n\", .{output});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello Pedro!!!\n```\n\n\n:::\n:::\n\n\n\n\nYou get a lot of control over where and how much memory this function can allocate.\nBecause it is you, the user/programmer, that provides the allocator for the function to use.\nThis makes \"total control\" over memory management easier to achieve in Zig.\n\n### What are allocators?\n\nAllocators in Zig are objects that you can use to allocate memory for your program.\nThey are similar to the memory allocating functions in C, like `malloc()` and `calloc()`.\nSo, if you need to use more memory than you initially have, during the execution of your program, you can simply ask\nfor more memory by using an allocator object.\n\nZig offers different types of allocators, and they are usually available through the `std.heap` module of\nthe standard library. Thus, just import the Zig Standard Library into your Zig module (with `@import(\"std\")`), and you can start\nusing these allocators in your code.\n\nFurthermore, every allocator object is built on top of the `Allocator` interface in Zig.\nThis means that, every allocator object you find in Zig must have the methods `alloc()`,\n`create()`, `free()` and `destroy()`. So, you can change the type of allocator you are using,\nbut you don't need to change the function calls to the methods that do the memory allocation\n(and the free memory operations) for your program.\n\n### Why you need an allocator?\n\nAs we described in @sec-stack, everytime you make a function call in Zig,\na space in the stack is reserved for this function call. But the stack\nhas a key limitation which is: every object stored in the stack has a\nknown fixed length.\n\nBut in reality, there are two very common instances where this \"fixed length limitation\" of the stack is a deal braker:\n\n1. the objects that you create inside your function might grow in size during the execution of the function.\n1. sometimes, it's impossible to know upfront how many inputs you will receive, or how big this input will be.\n\nAlso, there is another instance where you might want to use an allocator, which is when you want to write a function that returns a pointer\nto a local object. As I described in @sec-stack, you cannot do that if this local object is stored in the\nstack. However, if this object is stored in the heap, then, you can return a pointer to this object at the\nend of the function. Because you (the programmer) control the lifetime of any heap memory that you allocate. You decide\nwhen this memory gets destroyed/freed.\n\nThese are common situations for which the stack is not good.\nThat is why you need a different memory management strategy to\nstore these objects inside your function. You need to use\na memory type that can grow together with your objects, or that you\ncan control the lifetime of this memory.\nThe heap fits this description.\n\nAllocating memory on the heap is commonly known as dynamic memory management. As the objects you create grow in size\nduring the execution of your program, you grow the amount of memory\nyou have by allocating more memory in the heap to store these objects.\nAnd you do that in Zig, by using an allocator object.\n\n\n### The different types of allocators\n\n\nAt the moment of the writing of this book, in Zig, we have 6 different\nallocators available in the standard library:\n\n- `GeneralPurposeAllocator()`.\n- `page_allocator()`.\n- `FixedBufferAllocator()` and `ThreadSafeFixedBufferAllocator()`.\n- `ArenaAllocator()`.\n- `c_allocator()` (requires you to link to libc).\n\n\nEach allocator has its own perks and limitations. All allocators, except `FixedBufferAllocator()` and `ArenaAllocator()`,\nare allocators that use the heap memory. So any memory that you allocate with\nthese allocators, will be placed in the heap.\n\n### General-purpose allocators\n\nThe `GeneralPurposeAllocator()`, as the name suggests, is a \"general purpose\" allocator. You can use it for every type\nof task. In the example below, I'm allocating enough space to store a single integer in the object `some_number`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    const some_number = try allocator.create(u32);\n    defer allocator.destroy(some_number);\n\n    some_number.* = @as(u32, 45);\n}\n```\n:::\n\n\n\n\nWhile useful, you might want to use the `c_allocator()`, which is a alias to the C standard allocator `malloc()`. So, yes, you can use\n`malloc()` in Zig if you want to. Just use the `c_allocator()` from the Zig standard library. However,\nif you do use `c_allocator()`, you must link to Libc when compiling your source code with the\n`zig` compiler, by including the flag `-lc` in your compilation process.\nIf you do not link your source code to Libc, Zig will not be able to find the\n`malloc()` implementation in your system.\n\n### Page allocator\n\nThe `page_allocator()` is an allocator that allocates full pages of memory in the heap. In other words,\nevery time you allocate memory with `page_allocator()`, a full page of memory in the heap is allocated,\ninstead of just a small piece of it.\n\nThe size of this page depends on the system you are using.\nMost systems use a page size of 4KB in the heap, so, that is the amount of memory that is normally\nallocated in each call by `page_allocator()`. That is why, `page_allocator()` is considered a\nfast, but also \"wasteful\" allocator in Zig. Because it allocates a big amount of memory\nin each call, and you most likely will not need that much memory in your program.\n\n### Buffer allocators\n\nThe `FixedBufferAllocator()` and `ThreadSafeFixedBufferAllocator()` are allocator objects that\nwork with a fixed sized buffer object at the back. In other words, they use a fixed sized buffer\nobject as the basis for the memory. When you ask these allocator objects to allocate some memory for you,\nthey are essentially reserving some amount of space inside this fixed sized buffer object for you to use.\n\nThis means that, in order to use these allocators, you must first create a buffer object in your code,\nand then, give this buffer object as an input to these allocators.\n\nThis also means that, these allocator objects can allocate memory both in the stack or in the heap.\nEverything depends on where the buffer object that you provide lives. If this buffer object lives\nin the stack, then, the memory allocated is \"stack-based\". But if it lives on the heap, then,\nthe memory allocated is \"heap-based\".\n\n\nIn the example below, I'm creating a `buffer` object on the stack that is 10 elements long.\nNotice that I give this `buffer` object to the `FixedBufferAllocator()` constructor.\nNow, because this `buffer` object is 10 elements long, this means that I am limited to this space.\nI cannot allocate more than 10 elements with this allocator object. If I try to\nallocate more than that, the `alloc()` method will return an `OutOfMemory` error value.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar buffer: [10]u8 = undefined;\nfor (0..buffer.len) |i| {\n    buffer[i] = 0; // Initialize to zero\n}\n\nvar fba = std.heap.FixedBufferAllocator.init(&buffer);\nconst allocator = fba.allocator();\nconst input = try allocator.alloc(u8, 5);\ndefer allocator.free(input);\n```\n:::\n\n\n\nRemember, the memory allocated by these allocator objects can be either from\nthe stack, or, from the heap. It all depends on where the buffer object that you provide lives.\nIn the above example, the `buffer` object lives in the stack, and, therefore, the memory allocated\nis based in the stack. But what if it was based on the heap?\n\nAs we described in @sec-stack-overflow, one of the main reasons why you would use the heap,\ninstead of the stack, is to allocate huge amounts of space to store very big objects.\nThus, let's suppose you wanted to use a very big buffer object as the basis for your\nallocator objects. You would have to allocate this very big buffer object on the heap.\nThe example below demonstrates this case.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst heap = std.heap.page_allocator;\nconst memory_buffer = try heap.alloc(\n    u8, 100 * 1024 * 1024 // 100 MB memory\n);\ndefer heap.free(memory_buffer);\nvar fba = std.heap.FixedBufferAllocator.init(\n    memory_buffer\n);\nconst allocator = fba.allocator();\n\nconst input = try allocator.alloc(u8, 1000);\ndefer allocator.free(input);\n```\n:::\n\n\n\n\n\n### Arena allocator {#sec-arena-allocator}\n\nThe `ArenaAllocator()` is an allocator object that takes a child allocator as input. The idea behind the `ArenaAllocator()` in Zig\nis similar to the concept of \"arenas\" in the programming language Go[^go-arena]. It's an allocator object that allows you\nto allocate memory as many times you want, but free all memory only once.\nIn other words, if you have, for example, called 5 times the method `alloc()` of an `ArenaAllocator()` object, you can\nfree all the memory you allocated over these 5 calls at once, by simply calling the `deinit()` method of the same `ArenaAllocator()` object.\n\n[^go-arena]: \n\nIf you give, for example, a `GeneralPurposeAllocator()` object as input to the `ArenaAllocator()` constructor, like in the example below, then, the allocations\nyou perform with `alloc()` will actually be made with the underlying object `GeneralPurposeAllocator()` that was passed.\nSo, with an arena allocator, any new memory you ask for is allocated by the child allocator. The only thing that an arena allocator\nreally does is help you to free all the memory you allocated multiple times with just a single command. In the example\nbelow, I called `alloc()` 3 times. So, if I did not use an arena allocator, then, I would need to call\n`free()` 3 times to free all the allocated memory.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nvar aa = std.heap.ArenaAllocator.init(gpa.allocator());\ndefer aa.deinit();\nconst allocator = aa.allocator();\n\nconst in1 = try allocator.alloc(u8, 5);\nconst in2 = try allocator.alloc(u8, 10);\nconst in3 = try allocator.alloc(u8, 15);\n_ = in1; _ = in2; _ = in3;\n```\n:::\n\n\n\n\n\n### The `alloc()` and `free()` methods\n\nIn the code example below, we are accessing the `stdin`, which is\nthe standard input channel, to receive an input from the\nuser. We read the input given by the user with the `readUntilDelimiterOrEof()`\nmethod.\n\nNow, after reading the input of the user, we need to store this input somewhere in\nour program. That is why I use an allocator in this example. I use it to allocate some\namount of memory to store this input given by the user. More specifically, the method `alloc()`\nof the allocator object is used to allocate an array capable of storing 50 `u8` values.\n\nNotice that this `alloc()` method receives two inputs. The first one, is a type.\nThis defines what type of values the allocated array will store. In the example\nbelow, we are allocating an array of unsigned 8-bit integers (`u8`). But\nyou can create an array to store any type of value you want. Next, in the second argument, we\ndefine the size of the allocated array, by specifying how many elements\nthis array will contain. In the case below, we are allocating an array of 50 elements.\n\nIn @sec-zig-strings we described that strings in Zig are simply arrays of characters.\nEach character is represented by a `u8` value. So, this means that the array that\nwas allocated in the object `input` is capable of storing a string that is\n50-characters long.\n\nSo, in essence, the expression `var input: [50]u8 = undefined` would create\nan array for 50 `u8` values in the stack of the current scope. But, you\ncan allocate the same array in the heap by using the expression `var input = try allocator.alloc(u8, 50)`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdin = std.io.getStdIn();\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    var input = try allocator.alloc(u8, 50);\n    defer allocator.free(input);\n    for (0..input.len) |i| {\n        input[i] = 0; // initialize all fields to zero.\n    }\n    // read user input\n    const input_reader = stdin.reader();\n    _ = try input_reader.readUntilDelimiterOrEof(\n        input,\n        '\\n'\n    );\n    std.debug.print(\"{s}\\n\", .{input});\n}\n```\n:::\n\n\n\nAlso, notice that in this example, we use the `defer` keyword (which I described in @sec-defer) to run a small\npiece of code at the end of the current scope, which is the expression `allocator.free(input)`.\nWhen you execute this expression, the allocator will free the memory that it allocated\nfor the `input` object.\n\nWe have talked about this in @sec-heap. You **should always** explicitly free any memory that you allocate\nusing an allocator! You do that by using the `free()` method of the same allocator object you\nused to allocate this memory. The `defer` keyword is used in this example only to help us execute\nthis free operation at the end of the current scope.\n\n\n### The `create()` and `destroy()` methods\n\nWith the `alloc()` and `free()` methods, you can allocate memory to store multiple elements\nat once. In other words, with these methods, we always allocate an array to store multiple elements at once.\nBut what if you need enough space to store just a single item? Should you\nallocate an array of a single element through `alloc()`?\n\nThe answer is no! In this case,\nyou should use the `create()` method of the allocator object.\nEvery allocator object offers the `create()` and `destroy()` methods,\nwhich are used to allocate and free memory for a single item, respectively.\n\nSo, in essence, if you want to allocate memory to store an array of elements, you\nshould use `alloc()` and `free()`. But if you need to store just a single item,\nthen, the `create()` and `destroy()` methods are ideal for you.\n\nIn the example below, I'm defining a struct to represent an user of some sort.\nIt could be a user for a game, or software to manage resources, it doesn't mater.\nNotice that I use the `create()` method this time, to store a single `User` object\nin the program. Also notice that I use the `destroy()` method to free the memory\nused by this object at the end of the scope.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst User = struct {\n    id: usize,\n    name: []const u8,\n\n    pub fn init(id: usize, name: []const u8) User {\n        return .{ .id = id, .name = name };\n    }\n};\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    const user = try allocator.create(User);\n    defer allocator.destroy(user);\n\n    user.* = User.init(0, \"Pedro\");\n}\n```\n:::\n",
    -    "supporting": [
    -      "01-memory_files"
    -    ],
    -    "filters": [
    -      "rmarkdown/pagebreak.lua"
    -    ],
    -    "includes": {},
    -    "engineDependencies": {
    -      "knitr": [
    -        "{\"type\":\"list\",\"attributes\":{},\"value\":[]}"
    -      ]
    -    },
    -    "preserve": null,
    -    "postProcess": false
    -  }
    -}
    \ No newline at end of file
    diff --git a/_freeze/Chapters/01-memory/execute-results/html.json b/_freeze/Chapters/01-memory/execute-results/html.json
    index 269c7d87..9f9e16f9 100644
    --- a/_freeze/Chapters/01-memory/execute-results/html.json
    +++ b/_freeze/Chapters/01-memory/execute-results/html.json
    @@ -2,10 +2,8 @@
       "hash": "55899a376e1db53689b78790e55a518d",
       "result": {
         "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Memory and Allocators\n\n\nIn this chapter, we will talk about memory. How does Zig control memory? What\ncommon tools are used? Are there any important aspects that make memory\ndifferent/special in Zig? You will find the answers here.\n\nComputers fundamentally rely on memory to function. This memory acts as a temporary storage\nspace for the data and values generated during computations. Without memory, the core\nconcepts of \"variables\" and \"objects\" in programming languages would be impossible.\n\n\n\n\n## Memory spaces\n\nEvery object that you create in your Zig source code needs to be stored somewhere,\nin your computer's memory. Depending on where and how you define your object, Zig\nwill use a different \"memory space\", or a different\ntype of memory to store this object.\n\nEach type of memory normally serves for different purposes.\nIn Zig, there are 3 types of memory (or 3 different memory spaces) that we care about. They are:\n\n- Global data register (or the \"global data section\");\n- Stack;\n- Heap;\n\n\n### Compile-time known versus runtime known {#sec-compile-time}\n\nOne strategy that Zig uses to decide where it will store each object that you declare, is by looking\nat the value of this particular object. More specifically, by investigating if this value is\nknown at \"compile-time\" or at \"runtime\".\n\nWhen you write a program in Zig, the values of some of the objects that you write in your program are *known\nat compile time*. Meaning that, when you compile your Zig source code, during the compilation process,\nthe `zig` compiler can figure out the exact value of a particular object\nthat exists in your source code.\nKnowing the length (or the size) of each object is also important. So the length (or the size) of each object that you write in your program is,\nin some cases, *known at compile time*.\n\nThe `zig` compiler cares more about knowing the length (or the size) of a particular object\n, than to know its actual value. But, if the `zig` compiler knows the value of the object, then, it\nautomatically knows the size of this object. Because it can simply calculate the\nsize of the object by looking at the size of the value.\n\nTherefore, the priority for the `zig` compiler is to discover the size of each object in your source code.\nIf the value of the object in question is known at compile-time, then, the `zig` compiler\nautomatically knows the size/length of this object. But if the value of this object is not\nknown at compile-time, then, the size of this object is only known at compile-time if,\nand only if, the type of this object has a known fixed size.\n\nIn order for a type to have a known fixed size, this type must have data members whose size is fixed.\nIf this type includes, for example, a variable sized array in it, then, this type does not have a known\nfixed size. Because this array can have any size at runtime\n(i.e., it can be an array of 2 elements, or 50 elements, or 1 thousand elements, etc.).\n\nFor example, a string object, which internally is an array of constant u8 values (`[]const u8`)\nhas a variable size. It can be a string object with 100 or 500 characters in it. If we do not\nknow at compile-time, which exact string will be stored inside this string object, then, we cannot calculate\nthe size of this string object at compile-time. So, any type, or any struct declaration that you make, that\nincludes a string data member that does not have an explicit fixed size, makes this type, or this\nnew struct that you are declaring, a type that does not have a known fixed size at compile-time.\n\nIn contrast, if the type of this struct that you are declaring, includes a data member that is an array,\nbut this array has a known fixed size, like `[60]u8` (which declares an array of 60 `u8` values), then,\nthis type, or, this struct that you are declaring, becomes a type with a known fixed size at compile-time.\nAnd because of that, in this case, the `zig` compiler does not need to know at compile-time the exact value of\nany object of this type. Since the compiler can find the necessary size to store this object by\nlooking at the size of its type.\n\n\nLet's look at an example. In the source code below, we have two constant objects (`name` and `array`) declared.\nBecause the values of these particular objects are written down, in the source code itself (`\"Pedro\"`\nand the number sequence from 1 to 4), the `zig` compiler can easily discover the values of these constant\nobjects (`name` and `array`) during the compilation process.\nThis is what \"known at compile time\" means. It refers to any object that you have in your Zig source code\nwhose value can be identified at compile time.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn input_length(input: []const u8) usize {\n    const n = input.len;\n    return n;\n}\n\npub fn main() !void {\n    const name = \"Pedro\";\n    const array = [_]u8{1, 2, 3, 4};\n    _ = name; _ = array;\n}\n```\n:::\n\n\n\n\nThe other side of the spectrum are objects whose values are not known at compile time.\nFunction arguments are a classic example of this. Because the value of each function\nargument depends on the value that you assign to this particular argument,\nwhen you call the function.\n\nFor example, the function `input_length()` contains an argument named `input`, which is an array of constant `u8` integers (`[]const u8`).\nIt's impossible to know the value of this particular argument at compile time. And it also is impossible to know the size/length\nof this particular argument. Because it's an array that does not have a fixed size specified explicitly in the argument type annotation.\n\nSo, we know that this `input` argument will be an array of `u8` integers. But we do not know at compile-time, its value, and neither its size.\nThis information is known only at runtime, which is the period of time when you program is executed.\nAs a consequence, the value of the expression `input.len` is also known only at runtime.\nThis is an intrinsic characteristic of any function. Just remember that the value of function arguments is usually not \"compile-time known\".\n\nHowever, as I mentioned earlier, what really matters to the compiler is to know the size of the object\nat compile-time, and not necessarily its value. So, although we don't know the value of the object `n`, which is the result of the expression\n`input.len`, at compile-time, we do know its size. Because the expression `input.len` always returns a value of type `usize`,\nand the type `usize` has a known fixed size.\n\n\n\n### Global data register\n\nThe global data register is a specific section of the executable of your Zig program, that is responsible\nfor storing any value that is known at compile time.\n\nEvery constant object whose value is known at compile time that you declare in your source code,\nis stored in the global data register. Also, every literal value that you write in your source code,\nsuch as the string `\"this is a string\"`, or the integer `10`, or a boolean value such as `true`,\nis also stored in the global data register.\n\nHonestly, you don't need to care much about this memory space. Because you can't control it,\nyou can't deliberately access it or use it for your own purposes.\nAlso, this memory space does not affect the logic of your program.\nIt simply exists in your program.\n\n\n### Stack vs Heap\n\nIf you are familiar with systems programming, or just low-level programming in general, you\nprobably have heard of the \"duel\" between Stack vs Heap. These are two different types of memory,\nor different memory spaces, which are both available in Zig.\n\nThese two types of memory don't actually duel with\neach other. This is a common mistake that beginners have, when seeing \"x vs y\" styles of\ntabloid headlines. These two types of memory are actually complementary to each other.\nSo, in almost every Zig program that you ever write, you will likely use a combination of both.\nI will describe each memory space in detail over the next sections. But for now, I just want to\nstablish the main difference between these two types of memory.\n\nIn essence, the stack memory is normally used to store values whose length is fixed and known\nat compile time. In contrast, the heap memory is a *dynamic* type of memory space, meaning that, it's\nused to store values whose length might grow during the execution (runtime) of your program [@jenny2022].\n\nLengths that grow during runtime are intrinsically associated with \"runtime known\" type of values.\nIn other words, if you have an object whose length might grow during runtime, then, the length\nof this object becomes not known at compile time. If the length is not known at compile-time,\nthe value of this object also becomes not known at compile-time.\nThese types of objects should be stored in the heap memory space, which is\na dynamic memory space, which can grow or shrink to fit the size of your objects.\n\n\n\n### Stack {#sec-stack}\n\nThe stack is a type of memory that uses the power of the *stack data structure*, hence the name.\nA \"stack\" is a type of *data structure* that uses a \"last in, first out\" (LIFO) mechanism to store the values\nyou give it to. I imagine you are familiar with this data structure.\nBut, if you are not, the [Wikipedia page](https://en.wikipedia.org/wiki/Stack_(abstract_data_type))[^wiki-stack]\n, or, the [Geeks For Geeks page](https://www.geeksforgeeks.org/stack-data-structure/)[^geek-stack] are both\nexcellent and easy resources to fully understand how this data structure works.\n\n[^wiki-stack]: \n[^geek-stack]: \n\nSo, the stack memory space is a type of memory that stores values using a stack data structure.\nIt adds and removes values from the memory by following a \"last in, first out\" (LIFO) principle.\n\nEvery time you make a function call in Zig, an amount of space in the stack is\nreserved for this particular function call [@jenny2022; @zigdocs].\nThe value of each function argument given to the function in this function call is stored in this\nstack space. Also, every local object that you declare inside the function scope is\nusually stored in this same stack space.\n\n\nLooking at the example below, the object `result` is a local object declared inside the scope of the `add()`\nfunction. Because of that, this object is stored inside the stack space reserved for the `add()` function.\nThe `r` object (which is declared outside of the `add()` function scope) is also stored in the stack.\nBut since it's declared in the \"outer\" scope, this object is stored in the\nstack space that belongs to this outer scope.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn add(x: u8, y: u8) u8 {\n    const result = x + y;\n    return result;\n}\n\npub fn main() !void {\n    const r = add(5, 27);\n    _ = r;\n}\n```\n:::\n\n\n\n\n\nSo, any object that you declare inside the scope of a function is always stored inside\nthe space that was reserved for that particular function in the stack memory. This\nalso counts for any object declared inside the scope of your `main()` function for example.\nAs you would expect, in this case, they\nare stored inside the stack space reserved for the `main()` function.\n\nOne very important detail about the stack memory is that **it frees itself automatically**.\nThis is very important, remember that. When objects are stored in the stack memory,\nyou don't have the work (or the responsibility) of freeing/destroying these objects.\nBecause they will be automatically destroyed once the stack space is freed at the end of the function scope.\n\nSo, once the function call returns (or ends, if you prefer to call it this way)\nthe space that was reserved in the stack is destroyed, and all of the objects that were in that space goes away with it.\nThis mechanism exists because this space, and the objects within it, are not necessary anymore,\nsince the function \"finished its business\".\nUsing the `add()` function that we exposed above as an example, it means that the object `result` is automatically\ndestroyed once the function returns.\n\n::: {.callout-important}\nLocal objects that are stored in the stack space of a function are automatically\nfreed/destroyed at the end of the function scope.\n:::\n\n\nThis same logic applies to any other special structure in Zig that has its own scope by surrounding\nit with curly braces (`{}`).\nFor loops, while loops, if else statements, etc. For example, if you declare any local\nobject in the scope of a for loop, this local object is accessible only within the scope\nof this particular for loop. Because once the scope of this for loop ends, the space in the stack\nreserved for this for loop is freed.\nThe example below demonstrates this idea.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This does not compile successfully!\nconst a = [_]u8{0, 1, 2, 3, 4};\nfor (0..a.len) |i| {\n    const index = i;\n    _ = index;\n}\n// Trying to use an object that was\n// declared in the for loop scope,\n// and that does not exist anymore.\nstd.debug.print(\"{d}\\n\", .{index});\n```\n:::\n\n\n\n\n\n\nOne important consequence of this mechanism is that, once the function returns, you can no longer access any memory\naddress that was inside the space in the stack reserved for this particular function. Because this space was\ndestroyed. This means that, if this local object is stored in the stack,\nyou cannot make a function that **returns a pointer to this object**.\n\nThink about that for a second. If all local objects in the stack are destroyed at the end of the function scope, why\nwould you even consider returning a pointer to one of these objects? This pointer is at best,\ninvalid, or, more likely, \"undefined\".\n\nIn conclusion, it's totally fine to write a function that returns the local object\nitself as result, because then, you return the value of that object as the result.\nBut, if this local object is stored in the stack, you should never write a function\nthat returns a pointer to this local object. Because the memory address pointed by the pointer\nno longer exists.\n\n\nSo, using again the `add()` function as an example, if you rewrite this function so that it\nreturns a pointer to the local object `result`, the `zig` compiler will actually compile\nyour program, with no warnings or errors. At first glance, it looks like this is good code\nthat works as expected. But this is a lie!\n\nIf you try to take a look at the value inside of the `r` object,\nor, if you try to use this `r` object in another expression\nor function call, then, you would have undefined behaviour, and major\nbugs in your program [@zigdocs, see \"Lifetime and Ownership\"[^life] and \"Undefined Behaviour\"[^undef] sections].\n\n[^life]: \n[^undef]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn add(x: u8, y: u8) *const u8 {\n    const result = x + y;\n    return &result;\n}\n\npub fn main() !void {\n    // This code compiles successfully. But it has\n    // undefined behaviour. Never do this!!!\n    // The `r` object is undefined!\n    const r = add(5, 27); _ = r;\n}\n```\n:::\n\n\n\n\nThis \"invalid pointer to stack variable\" problem is well known across many programming language communities.\nIf you try to do the same thing, for example, in a C or C++ program (i.e., returning an address to\na local object stored in the stack), you would also get undefined behaviour\nin the program.\n\n::: {.callout-important}\nIf a local object in your function is stored in the stack, you should never\nreturn a pointer to this local object from the function. Because\nthis pointer will always become undefined after the function returns, since the stack space of the function\nis destroyed at the end of its scope.\n:::\n\nBut what if you really need to use this local object in some way after your function returns?\nHow can you do this? The answer is: \"in the same way you would do if this were a C or C++ program. By returning\nan address to an object stored in the heap\". The heap memory has a much more flexible lifecycle,\nand allows you to get a valid pointer to a local object of a function that already returned\nfrom its scope.\n\n\n### Heap {#sec-heap}\n\nOne important limitation of the stack, is that, only objects whose length/size is known at compile-time can be\nstored in it. In contrast, the heap is a much more dynamic\n(and flexible) type of memory. It's the perfect type of memory to use\nfor objects whose size/length might grow during the execution of your program.\n\nVirtually any application that behaves as a server is a classic use case of the heap.\nA HTTP server, a SSH server, a DNS server, a LSP server, ... any type of server.\nIn summary, a server is a type of application that runs for long periods of time,\nand that serves (or \"deals with\") any incoming request that reaches this particular server.\n\nThe heap is a good choice for this type of system, mainly because the server does not know upfront\nhow many requests it will receive from users, while it is active. It could be a single request,\n5 thousand requests, or even zero requests.\nThe server needs to have the ability to allocate and manage its memory according to how many requests it receives.\n\nAnother key difference between the stack and the heap, is that the heap is a type\nof memory that you, the programmer, have complete control over. This makes the heap a\nmore flexible type of memory, but it also makes it harder to work with. Because you,\nthe programmer, is responsible for managing everything related to it. Including where the memory is allocated,\nhow much memory is allocated, and where this memory is freed.\n\n> Unlike stack memory, heap memory is allocated explicitly by programmers and it won’t be deallocated until it is explicitly freed [@jenny2022].\n\nTo store an object in the heap, you, the programmer, needs to explicitly tells Zig to do so,\nby using an allocator to allocate some space in the heap. In @sec-allocators, I will present how you can use allocators to allocate memory\nin Zig.\n\n::: {.callout-important}\nEvery memory you allocate in the heap needs to be explicitly freed by you, the programmer.\n:::\n\nThe majority of allocators in Zig do allocate memory on the heap. But some exceptions to this rule are\n`ArenaAllocator()` and `FixedBufferAllocator()`. The `ArenaAllocator()` is a special\ntype of allocator that works in conjunction with a second type of allocator.\nOn the other side, the `FixedBufferAllocator()` is an allocator that works based on\nbuffer objects created on the stack. This means that the `FixedBufferAllocator()` makes\nallocations only on the stack.\n\n\n\n\n### Summary\n\nAfter discussing all of these boring details, we can quickly recap what we learned.\nIn summary, the Zig compiler will use the following rules to decide where each\nobject you declare is stored:\n\n1. every literal value (such as `\"this is string\"`, `10`, or `true`) is stored in the global data section.\n1. every constant object (`const`) whose value **is known at compile-time** is also stored in the global data section.\n1. every object (constant or not) whose length/size **is known at compile time** is stored in the stack space for the current scope.\n1. if an object is created with the method `alloc()` or `create()` of an allocator object, this object is stored in the memory space used by this particular allocator object. Most of allocators available in Zig use the heap memory, so, this object is likely stored in the heap (`FixedBufferAllocator()` is an exception to that).\n1. the heap can only be accessed through allocators. If your object was not created through the `alloc()` or `create()` methods of an allocator object, then, it is most certainly not an object stored in the heap.\n\n\n## Stack overflows {#sec-stack-overflow}\n\nAllocating memory on the stack is generally faster than allocating it on the heap.\nBut this better performance comes with many restrictions. We have already discussed\nmany of these restrictions of the stack in @sec-stack. But there is one more important\nlimitation that I want to talk about, which is the size of the stack itself.\n\nThe stack is limited in size. This size varies from computer to computer, and it depends on\na lot of things (the computer architecture, the operating system, etc.). Nevertheless, this size is usually\nnot that big. This is why we normally use the stack to store only temporary and small objects in memory.\n\nIn essence, if you try to make an allocation on the stack, that is so big that exceeds the stack size limit,\na *stack overflow* happens, and your program just crashes as a result of that. In other words, a stack overflow happens when\nyou attempt to use more space than is available on the stack.\n\nThis type of problem is very similar to a *buffer overflow*, i.e., you are trying to use more space\nthan is available in the \"buffer object\". However, a stack overflow always causes your program to crash,\nwhile a buffer overflow does not always cause your program to crash (although it often does).\n\nYou can see an example of a stack overflow in the example below. We are trying to allocate a very big array of `u64` values\non the stack. You can see below that this program does not run successfully, because it crashed\nwith a \"segmentation fault\" error message.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar very_big_alloc: [1000 * 1000 * 24]u64 = undefined;\n@memset(very_big_alloc[0..], 0);\n```\n:::\n\n\n\n\n```\nSegmentation fault (core dumped)\n```\n\nThis segmentation fault error is a result of the stack overflow that was caused by the big\nmemory allocation made on the stack, to store the `very_big_alloc` object.\nThis is why very big objects are usually stored on the heap, instead of the stack.\n\n\n\n## Allocators {#sec-allocators}\n\nOne key aspect about Zig, is that there are \"no hidden-memory allocations\" in Zig.\nWhat that really means, is that \"no allocations happen behind your back in the standard library\" [@zigguide].\n\nThis is a known problem, especially in C++. Because in C++, there are some operators that do allocate\nmemory behind the scene, and there is no way for you to know that, until you actually read the\nsource code of these operators, and find the memory allocation calls.\nMany programmers find this behaviour annoying and hard to keep track of.\n\nBut, in Zig, if a function, an operator, or anything from the standard library\nneeds to allocate some memory during its execution, then, this function/operator needs to receive (as input) an allocator\nprovided by the user, to actually be able to allocate the memory it needs.\n\nThis creates a clear distinction between functions that \"do not\" from those that \"actually do\"\nallocate memory. Just look at the arguments of this function.\nIf a function, or operator, has an allocator object as one of its inputs/arguments, then, you know for\nsure that this function/operator will allocate some memory during its execution.\n\nAn example is the `allocPrint()` function from the Zig Standard Library. With this function, you can\nwrite a new string using format specifiers. So, this function is, for example, very similar to the function `sprintf()` in C.\nIn order to write such a new string, the `allocPrint()` function needs to allocate some memory to store the\noutput string.\n\nThat is why, the first argument of this function is an allocator object that you, the user/programmer, gives\nas input to the function. In the example below, I am using the `GeneralPurposeAllocator()` as my allocator\nobject. But I could easily use any other type of allocator object from the Zig Standard Library.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nconst name = \"Pedro\";\nconst output = try std.fmt.allocPrint(\n    allocator,\n    \"Hello {s}!!!\",\n    .{name}\n);\ntry stdout.print(\"{s}\\n\", .{output});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello Pedro!!!\n```\n\n\n:::\n:::\n\n\n\n\n\nYou get a lot of control over where and how much memory this function can allocate.\nBecause it is you, the user/programmer, that provides the allocator for the function to use.\nThis makes \"total control\" over memory management easier to achieve in Zig.\n\n### What are allocators?\n\nAllocators in Zig are objects that you can use to allocate memory for your program.\nThey are similar to the memory allocating functions in C, like `malloc()` and `calloc()`.\nSo, if you need to use more memory than you initially have, during the execution of your program, you can simply ask\nfor more memory by using an allocator object.\n\nZig offers different types of allocators, and they are usually available through the `std.heap` module of\nthe standard library. Thus, just import the Zig Standard Library into your Zig module (with `@import(\"std\")`), and you can start\nusing these allocators in your code.\n\nFurthermore, every allocator object is built on top of the `Allocator` interface in Zig.\nThis means that, every allocator object you find in Zig must have the methods `alloc()`,\n`create()`, `free()` and `destroy()`. So, you can change the type of allocator you are using,\nbut you don't need to change the function calls to the methods that do the memory allocation\n(and the free memory operations) for your program.\n\n### Why you need an allocator?\n\nAs we described in @sec-stack, everytime you make a function call in Zig,\na space in the stack is reserved for this function call. But the stack\nhas a key limitation which is: every object stored in the stack has a\nknown fixed length.\n\nBut in reality, there are two very common instances where this \"fixed length limitation\" of the stack is a deal braker:\n\n1. the objects that you create inside your function might grow in size during the execution of the function.\n1. sometimes, it's impossible to know upfront how many inputs you will receive, or how big this input will be.\n\nAlso, there is another instance where you might want to use an allocator, which is when you want to write a function that returns a pointer\nto a local object. As I described in @sec-stack, you cannot do that if this local object is stored in the\nstack. However, if this object is stored in the heap, then, you can return a pointer to this object at the\nend of the function. Because you (the programmer) control the lifetime of any heap memory that you allocate. You decide\nwhen this memory gets destroyed/freed.\n\nThese are common situations for which the stack is not good.\nThat is why you need a different memory management strategy to\nstore these objects inside your function. You need to use\na memory type that can grow together with your objects, or that you\ncan control the lifetime of this memory.\nThe heap fits this description.\n\nAllocating memory on the heap is commonly known as dynamic memory management. As the objects you create grow in size\nduring the execution of your program, you grow the amount of memory\nyou have by allocating more memory in the heap to store these objects.\nAnd you do that in Zig, by using an allocator object.\n\n\n### The different types of allocators\n\n\nAt the moment of the writing of this book, in Zig, we have 6 different\nallocators available in the standard library:\n\n- `GeneralPurposeAllocator()`.\n- `page_allocator()`.\n- `FixedBufferAllocator()` and `ThreadSafeFixedBufferAllocator()`.\n- `ArenaAllocator()`.\n- `c_allocator()` (requires you to link to libc).\n\n\nEach allocator has its own perks and limitations. All allocators, except `FixedBufferAllocator()` and `ArenaAllocator()`,\nare allocators that use the heap memory. So any memory that you allocate with\nthese allocators, will be placed in the heap.\n\n### General-purpose allocators\n\nThe `GeneralPurposeAllocator()`, as the name suggests, is a \"general purpose\" allocator. You can use it for every type\nof task. In the example below, I'm allocating enough space to store a single integer in the object `some_number`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    const some_number = try allocator.create(u32);\n    defer allocator.destroy(some_number);\n\n    some_number.* = @as(u32, 45);\n}\n```\n:::\n\n\n\n\n\nWhile useful, you might want to use the `c_allocator()`, which is a alias to the C standard allocator `malloc()`. So, yes, you can use\n`malloc()` in Zig if you want to. Just use the `c_allocator()` from the Zig standard library. However,\nif you do use `c_allocator()`, you must link to Libc when compiling your source code with the\n`zig` compiler, by including the flag `-lc` in your compilation process.\nIf you do not link your source code to Libc, Zig will not be able to find the\n`malloc()` implementation in your system.\n\n### Page allocator\n\nThe `page_allocator()` is an allocator that allocates full pages of memory in the heap. In other words,\nevery time you allocate memory with `page_allocator()`, a full page of memory in the heap is allocated,\ninstead of just a small piece of it.\n\nThe size of this page depends on the system you are using.\nMost systems use a page size of 4KB in the heap, so, that is the amount of memory that is normally\nallocated in each call by `page_allocator()`. That is why, `page_allocator()` is considered a\nfast, but also \"wasteful\" allocator in Zig. Because it allocates a big amount of memory\nin each call, and you most likely will not need that much memory in your program.\n\n### Buffer allocators\n\nThe `FixedBufferAllocator()` and `ThreadSafeFixedBufferAllocator()` are allocator objects that\nwork with a fixed sized buffer object at the back. In other words, they use a fixed sized buffer\nobject as the basis for the memory. When you ask these allocator objects to allocate some memory for you,\nthey are essentially reserving some amount of space inside this fixed sized buffer object for you to use.\n\nThis means that, in order to use these allocators, you must first create a buffer object in your code,\nand then, give this buffer object as an input to these allocators.\n\nThis also means that, these allocator objects can allocate memory both in the stack or in the heap.\nEverything depends on where the buffer object that you provide lives. If this buffer object lives\nin the stack, then, the memory allocated is \"stack-based\". But if it lives on the heap, then,\nthe memory allocated is \"heap-based\".\n\n\nIn the example below, I'm creating a `buffer` object on the stack that is 10 elements long.\nNotice that I give this `buffer` object to the `FixedBufferAllocator()` constructor.\nNow, because this `buffer` object is 10 elements long, this means that I am limited to this space.\nI cannot allocate more than 10 elements with this allocator object. If I try to\nallocate more than that, the `alloc()` method will return an `OutOfMemory` error value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar buffer: [10]u8 = undefined;\nfor (0..buffer.len) |i| {\n    buffer[i] = 0; // Initialize to zero\n}\n\nvar fba = std.heap.FixedBufferAllocator.init(&buffer);\nconst allocator = fba.allocator();\nconst input = try allocator.alloc(u8, 5);\ndefer allocator.free(input);\n```\n:::\n\n\n\n\nRemember, the memory allocated by these allocator objects can be either from\nthe stack, or, from the heap. It all depends on where the buffer object that you provide lives.\nIn the above example, the `buffer` object lives in the stack, and, therefore, the memory allocated\nis based in the stack. But what if it was based on the heap?\n\nAs we described in @sec-stack-overflow, one of the main reasons why you would use the heap,\ninstead of the stack, is to allocate huge amounts of space to store very big objects.\nThus, let's suppose you wanted to use a very big buffer object as the basis for your\nallocator objects. You would have to allocate this very big buffer object on the heap.\nThe example below demonstrates this case.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst heap = std.heap.page_allocator;\nconst memory_buffer = try heap.alloc(\n    u8, 100 * 1024 * 1024 // 100 MB memory\n);\ndefer heap.free(memory_buffer);\nvar fba = std.heap.FixedBufferAllocator.init(\n    memory_buffer\n);\nconst allocator = fba.allocator();\n\nconst input = try allocator.alloc(u8, 1000);\ndefer allocator.free(input);\n```\n:::\n\n\n\n\n\n\n### Arena allocator {#sec-arena-allocator}\n\nThe `ArenaAllocator()` is an allocator object that takes a child allocator as input. The idea behind the `ArenaAllocator()` in Zig\nis similar to the concept of \"arenas\" in the programming language Go[^go-arena]. It's an allocator object that allows you\nto allocate memory as many times you want, but free all memory only once.\nIn other words, if you have, for example, called 5 times the method `alloc()` of an `ArenaAllocator()` object, you can\nfree all the memory you allocated over these 5 calls at once, by simply calling the `deinit()` method of the same `ArenaAllocator()` object.\n\n[^go-arena]: \n\nIf you give, for example, a `GeneralPurposeAllocator()` object as input to the `ArenaAllocator()` constructor, like in the example below, then, the allocations\nyou perform with `alloc()` will actually be made with the underlying object `GeneralPurposeAllocator()` that was passed.\nSo, with an arena allocator, any new memory you ask for is allocated by the child allocator. The only thing that an arena allocator\nreally does is help you to free all the memory you allocated multiple times with just a single command. In the example\nbelow, I called `alloc()` 3 times. So, if I did not use an arena allocator, then, I would need to call\n`free()` 3 times to free all the allocated memory.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nvar aa = std.heap.ArenaAllocator.init(gpa.allocator());\ndefer aa.deinit();\nconst allocator = aa.allocator();\n\nconst in1 = try allocator.alloc(u8, 5);\nconst in2 = try allocator.alloc(u8, 10);\nconst in3 = try allocator.alloc(u8, 15);\n_ = in1; _ = in2; _ = in3;\n```\n:::\n\n\n\n\n\n\n### The `alloc()` and `free()` methods\n\nIn the code example below, we are accessing the `stdin`, which is\nthe standard input channel, to receive an input from the\nuser. We read the input given by the user with the `readUntilDelimiterOrEof()`\nmethod.\n\nNow, after reading the input of the user, we need to store this input somewhere in\nour program. That is why I use an allocator in this example. I use it to allocate some\namount of memory to store this input given by the user. More specifically, the method `alloc()`\nof the allocator object is used to allocate an array capable of storing 50 `u8` values.\n\nNotice that this `alloc()` method receives two inputs. The first one, is a type.\nThis defines what type of values the allocated array will store. In the example\nbelow, we are allocating an array of unsigned 8-bit integers (`u8`). But\nyou can create an array to store any type of value you want. Next, in the second argument, we\ndefine the size of the allocated array, by specifying how many elements\nthis array will contain. In the case below, we are allocating an array of 50 elements.\n\nIn @sec-zig-strings we described that strings in Zig are simply arrays of characters.\nEach character is represented by a `u8` value. So, this means that the array that\nwas allocated in the object `input` is capable of storing a string that is\n50-characters long.\n\nSo, in essence, the expression `var input: [50]u8 = undefined` would create\nan array for 50 `u8` values in the stack of the current scope. But, you\ncan allocate the same array in the heap by using the expression `var input = try allocator.alloc(u8, 50)`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdin = std.io.getStdIn();\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    var input = try allocator.alloc(u8, 50);\n    defer allocator.free(input);\n    for (0..input.len) |i| {\n        input[i] = 0; // initialize all fields to zero.\n    }\n    // read user input\n    const input_reader = stdin.reader();\n    _ = try input_reader.readUntilDelimiterOrEof(\n        input,\n        '\\n'\n    );\n    std.debug.print(\"{s}\\n\", .{input});\n}\n```\n:::\n\n\n\n\nAlso, notice that in this example, we use the `defer` keyword (which I described in @sec-defer) to run a small\npiece of code at the end of the current scope, which is the expression `allocator.free(input)`.\nWhen you execute this expression, the allocator will free the memory that it allocated\nfor the `input` object.\n\nWe have talked about this in @sec-heap. You **should always** explicitly free any memory that you allocate\nusing an allocator! You do that by using the `free()` method of the same allocator object you\nused to allocate this memory. The `defer` keyword is used in this example only to help us execute\nthis free operation at the end of the current scope.\n\n\n### The `create()` and `destroy()` methods\n\nWith the `alloc()` and `free()` methods, you can allocate memory to store multiple elements\nat once. In other words, with these methods, we always allocate an array to store multiple elements at once.\nBut what if you need enough space to store just a single item? Should you\nallocate an array of a single element through `alloc()`?\n\nThe answer is no! In this case,\nyou should use the `create()` method of the allocator object.\nEvery allocator object offers the `create()` and `destroy()` methods,\nwhich are used to allocate and free memory for a single item, respectively.\n\nSo, in essence, if you want to allocate memory to store an array of elements, you\nshould use `alloc()` and `free()`. But if you need to store just a single item,\nthen, the `create()` and `destroy()` methods are ideal for you.\n\nIn the example below, I'm defining a struct to represent an user of some sort.\nIt could be a user for a game, or software to manage resources, it doesn't mater.\nNotice that I use the `create()` method this time, to store a single `User` object\nin the program. Also notice that I use the `destroy()` method to free the memory\nused by this object at the end of the scope.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst User = struct {\n    id: usize,\n    name: []const u8,\n\n    pub fn init(id: usize, name: []const u8) User {\n        return .{ .id = id, .name = name };\n    }\n};\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    const user = try allocator.create(User);\n    defer allocator.destroy(user);\n\n    user.* = User.init(0, \"Pedro\");\n}\n```\n:::\n",
    -    "supporting": [
    -      "01-memory_files"
    -    ],
    +    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n# Memory and Allocators\n\n\nIn this chapter, we will talk about memory. How does Zig control memory? What\ncommon tools are used? Are there any important aspects that make memory\ndifferent/special in Zig? You will find the answers here.\n\nComputers fundamentally rely on memory to function. This memory acts as a temporary storage\nspace for the data and values generated during computations. Without memory, the core\nconcepts of \"variables\" and \"objects\" in programming languages would be impossible.\n\n\n\n\n## Memory spaces\n\nEvery object that you create in your Zig source code needs to be stored somewhere,\nin your computer's memory. Depending on where and how you define your object, Zig\nwill use a different \"memory space\", or a different\ntype of memory to store this object.\n\nEach type of memory normally serves for different purposes.\nIn Zig, there are 3 types of memory (or 3 different memory spaces) that we care about. They are:\n\n- Global data register (or the \"global data section\");\n- Stack;\n- Heap;\n\n\n### Compile-time known versus runtime known {#sec-compile-time}\n\nOne strategy that Zig uses to decide where it will store each object that you declare, is by looking\nat the value of this particular object. More specifically, by investigating if this value is\nknown at \"compile-time\" or at \"runtime\".\n\nWhen you write a program in Zig, the values of some of the objects that you write in your program are *known\nat compile time*. Meaning that, when you compile your Zig source code, during the compilation process,\nthe `zig` compiler can figure out the exact value of a particular object\nthat exists in your source code.\nKnowing the length (or the size) of each object is also important. So the length (or the size) of each object that you write in your program is,\nin some cases, *known at compile time*.\n\nThe `zig` compiler cares more about knowing the length (or the size) of a particular object\n, than to know its actual value. But, if the `zig` compiler knows the value of the object, then, it\nautomatically knows the size of this object. Because it can simply calculate the\nsize of the object by looking at the size of the value.\n\nTherefore, the priority for the `zig` compiler is to discover the size of each object in your source code.\nIf the value of the object in question is known at compile-time, then, the `zig` compiler\nautomatically knows the size/length of this object. But if the value of this object is not\nknown at compile-time, then, the size of this object is only known at compile-time if,\nand only if, the type of this object has a known fixed size.\n\nIn order for a type to have a known fixed size, this type must have data members whose size is fixed.\nIf this type includes, for example, a variable sized array in it, then, this type does not have a known\nfixed size. Because this array can have any size at runtime\n(i.e., it can be an array of 2 elements, or 50 elements, or 1 thousand elements, etc.).\n\nFor example, a string object, which internally is an array of constant u8 values (`[]const u8`)\nhas a variable size. It can be a string object with 100 or 500 characters in it. If we do not\nknow at compile-time, which exact string will be stored inside this string object, then, we cannot calculate\nthe size of this string object at compile-time. So, any type, or any struct declaration that you make, that\nincludes a string data member that does not have an explicit fixed size, makes this type, or this\nnew struct that you are declaring, a type that does not have a known fixed size at compile-time.\n\nIn contrast, if the type of this struct that you are declaring, includes a data member that is an array,\nbut this array has a known fixed size, like `[60]u8` (which declares an array of 60 `u8` values), then,\nthis type, or, this struct that you are declaring, becomes a type with a known fixed size at compile-time.\nAnd because of that, in this case, the `zig` compiler does not need to know at compile-time the exact value of\nany object of this type. Since the compiler can find the necessary size to store this object by\nlooking at the size of its type.\n\n\nLet's look at an example. In the source code below, we have two constant objects (`name` and `array`) declared.\nBecause the values of these particular objects are written down, in the source code itself (`\"Pedro\"`\nand the number sequence from 1 to 4), the `zig` compiler can easily discover the values of these constant\nobjects (`name` and `array`) during the compilation process.\nThis is what \"known at compile time\" means. It refers to any object that you have in your Zig source code\nwhose value can be identified at compile time.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn input_length(input: []const u8) usize {\n    const n = input.len;\n    return n;\n}\n\npub fn main() !void {\n    const name = \"Pedro\";\n    const array = [_]u8{1, 2, 3, 4};\n    _ = name; _ = array;\n}\n```\n:::\n\n\nThe other side of the spectrum are objects whose values are not known at compile time.\nFunction arguments are a classic example of this. Because the value of each function\nargument depends on the value that you assign to this particular argument,\nwhen you call the function.\n\nFor example, the function `input_length()` contains an argument named `input`, which is an array of constant `u8` integers (`[]const u8`).\nIt's impossible to know the value of this particular argument at compile time. And it also is impossible to know the size/length\nof this particular argument. Because it's an array that does not have a fixed size specified explicitly in the argument type annotation.\n\nSo, we know that this `input` argument will be an array of `u8` integers. But we do not know at compile-time, its value, and neither its size.\nThis information is known only at runtime, which is the period of time when you program is executed.\nAs a consequence, the value of the expression `input.len` is also known only at runtime.\nThis is an intrinsic characteristic of any function. Just remember that the value of function arguments is usually not \"compile-time known\".\n\nHowever, as I mentioned earlier, what really matters to the compiler is to know the size of the object\nat compile-time, and not necessarily its value. So, although we don't know the value of the object `n`, which is the result of the expression\n`input.len`, at compile-time, we do know its size. Because the expression `input.len` always returns a value of type `usize`,\nand the type `usize` has a known fixed size.\n\n\n\n### Global data register\n\nThe global data register is a specific section of the executable of your Zig program, that is responsible\nfor storing any value that is known at compile time.\n\nEvery constant object whose value is known at compile time that you declare in your source code,\nis stored in the global data register. Also, every literal value that you write in your source code,\nsuch as the string `\"this is a string\"`, or the integer `10`, or a boolean value such as `true`,\nis also stored in the global data register.\n\nHonestly, you don't need to care much about this memory space. Because you can't control it,\nyou can't deliberately access it or use it for your own purposes.\nAlso, this memory space does not affect the logic of your program.\nIt simply exists in your program.\n\n\n### Stack vs Heap\n\nIf you are familiar with systems programming, or just low-level programming in general, you\nprobably have heard of the \"duel\" between Stack vs Heap. These are two different types of memory,\nor different memory spaces, which are both available in Zig.\n\nThese two types of memory don't actually duel with\neach other. This is a common mistake that beginners have, when seeing \"x vs y\" styles of\ntabloid headlines. These two types of memory are actually complementary to each other.\nSo, in almost every Zig program that you ever write, you will likely use a combination of both.\nI will describe each memory space in detail over the next sections. But for now, I just want to\nstablish the main difference between these two types of memory.\n\nIn essence, the stack memory is normally used to store values whose length is fixed and known\nat compile time. In contrast, the heap memory is a *dynamic* type of memory space, meaning that, it's\nused to store values whose length might grow during the execution (runtime) of your program [@jenny2022].\n\nLengths that grow during runtime are intrinsically associated with \"runtime known\" type of values.\nIn other words, if you have an object whose length might grow during runtime, then, the length\nof this object becomes not known at compile time. If the length is not known at compile-time,\nthe value of this object also becomes not known at compile-time.\nThese types of objects should be stored in the heap memory space, which is\na dynamic memory space, which can grow or shrink to fit the size of your objects.\n\n\n\n### Stack {#sec-stack}\n\nThe stack is a type of memory that uses the power of the *stack data structure*, hence the name.\nA \"stack\" is a type of *data structure* that uses a \"last in, first out\" (LIFO) mechanism to store the values\nyou give it to. I imagine you are familiar with this data structure.\nBut, if you are not, the [Wikipedia page](https://en.wikipedia.org/wiki/Stack_(abstract_data_type))[^wiki-stack]\n, or, the [Geeks For Geeks page](https://www.geeksforgeeks.org/stack-data-structure/)[^geek-stack] are both\nexcellent and easy resources to fully understand how this data structure works.\n\n[^wiki-stack]: \n[^geek-stack]: \n\nSo, the stack memory space is a type of memory that stores values using a stack data structure.\nIt adds and removes values from the memory by following a \"last in, first out\" (LIFO) principle.\n\nEvery time you make a function call in Zig, an amount of space in the stack is\nreserved for this particular function call [@jenny2022; @zigdocs].\nThe value of each function argument given to the function in this function call is stored in this\nstack space. Also, every local object that you declare inside the function scope is\nusually stored in this same stack space.\n\n\nLooking at the example below, the object `result` is a local object declared inside the scope of the `add()`\nfunction. Because of that, this object is stored inside the stack space reserved for the `add()` function.\nThe `r` object (which is declared outside of the `add()` function scope) is also stored in the stack.\nBut since it's declared in the \"outer\" scope, this object is stored in the\nstack space that belongs to this outer scope.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn add(x: u8, y: u8) u8 {\n    const result = x + y;\n    return result;\n}\n\npub fn main() !void {\n    const r = add(5, 27);\n    _ = r;\n}\n```\n:::\n\n\n\nSo, any object that you declare inside the scope of a function is always stored inside\nthe space that was reserved for that particular function in the stack memory. This\nalso counts for any object declared inside the scope of your `main()` function for example.\nAs you would expect, in this case, they\nare stored inside the stack space reserved for the `main()` function.\n\nOne very important detail about the stack memory is that **it frees itself automatically**.\nThis is very important, remember that. When objects are stored in the stack memory,\nyou don't have the work (or the responsibility) of freeing/destroying these objects.\nBecause they will be automatically destroyed once the stack space is freed at the end of the function scope.\n\nSo, once the function call returns (or ends, if you prefer to call it this way)\nthe space that was reserved in the stack is destroyed, and all of the objects that were in that space goes away with it.\nThis mechanism exists because this space, and the objects within it, are not necessary anymore,\nsince the function \"finished its business\".\nUsing the `add()` function that we exposed above as an example, it means that the object `result` is automatically\ndestroyed once the function returns.\n\n::: {.callout-important}\nLocal objects that are stored in the stack space of a function are automatically\nfreed/destroyed at the end of the function scope.\n:::\n\n\nThis same logic applies to any other special structure in Zig that has its own scope by surrounding\nit with curly braces (`{}`).\nFor loops, while loops, if else statements, etc. For example, if you declare any local\nobject in the scope of a for loop, this local object is accessible only within the scope\nof this particular for loop. Because once the scope of this for loop ends, the space in the stack\nreserved for this for loop is freed.\nThe example below demonstrates this idea.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This does not compile successfully!\nconst a = [_]u8{0, 1, 2, 3, 4};\nfor (0..a.len) |i| {\n    const index = i;\n    _ = index;\n}\n// Trying to use an object that was\n// declared in the for loop scope,\n// and that does not exist anymore.\nstd.debug.print(\"{d}\\n\", .{index});\n```\n:::\n\n\n\n\nOne important consequence of this mechanism is that, once the function returns, you can no longer access any memory\naddress that was inside the space in the stack reserved for this particular function. Because this space was\ndestroyed. This means that, if this local object is stored in the stack,\nyou cannot make a function that **returns a pointer to this object**.\n\nThink about that for a second. If all local objects in the stack are destroyed at the end of the function scope, why\nwould you even consider returning a pointer to one of these objects? This pointer is at best,\ninvalid, or, more likely, \"undefined\".\n\nIn conclusion, it's totally fine to write a function that returns the local object\nitself as result, because then, you return the value of that object as the result.\nBut, if this local object is stored in the stack, you should never write a function\nthat returns a pointer to this local object. Because the memory address pointed by the pointer\nno longer exists.\n\n\nSo, using again the `add()` function as an example, if you rewrite this function so that it\nreturns a pointer to the local object `result`, the `zig` compiler will actually compile\nyour program, with no warnings or errors. At first glance, it looks like this is good code\nthat works as expected. But this is a lie!\n\nIf you try to take a look at the value inside of the `r` object,\nor, if you try to use this `r` object in another expression\nor function call, then, you would have undefined behaviour, and major\nbugs in your program [@zigdocs, see \"Lifetime and Ownership\"[^life] and \"Undefined Behaviour\"[^undef] sections].\n\n[^life]: \n[^undef]: \n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn add(x: u8, y: u8) *const u8 {\n    const result = x + y;\n    return &result;\n}\n\npub fn main() !void {\n    // This code compiles successfully. But it has\n    // undefined behaviour. Never do this!!!\n    // The `r` object is undefined!\n    const r = add(5, 27); _ = r;\n}\n```\n:::\n\n\nThis \"invalid pointer to stack variable\" problem is well known across many programming language communities.\nIf you try to do the same thing, for example, in a C or C++ program (i.e., returning an address to\na local object stored in the stack), you would also get undefined behaviour\nin the program.\n\n::: {.callout-important}\nIf a local object in your function is stored in the stack, you should never\nreturn a pointer to this local object from the function. Because\nthis pointer will always become undefined after the function returns, since the stack space of the function\nis destroyed at the end of its scope.\n:::\n\nBut what if you really need to use this local object in some way after your function returns?\nHow can you do this? The answer is: \"in the same way you would do if this were a C or C++ program. By returning\nan address to an object stored in the heap\". The heap memory has a much more flexible lifecycle,\nand allows you to get a valid pointer to a local object of a function that already returned\nfrom its scope.\n\n\n### Heap {#sec-heap}\n\nOne important limitation of the stack, is that, only objects whose length/size is known at compile-time can be\nstored in it. In contrast, the heap is a much more dynamic\n(and flexible) type of memory. It's the perfect type of memory to use\nfor objects whose size/length might grow during the execution of your program.\n\nVirtually any application that behaves as a server is a classic use case of the heap.\nA HTTP server, a SSH server, a DNS server, a LSP server, ... any type of server.\nIn summary, a server is a type of application that runs for long periods of time,\nand that serves (or \"deals with\") any incoming request that reaches this particular server.\n\nThe heap is a good choice for this type of system, mainly because the server does not know upfront\nhow many requests it will receive from users, while it is active. It could be a single request,\n5 thousand requests, or even zero requests.\nThe server needs to have the ability to allocate and manage its memory according to how many requests it receives.\n\nAnother key difference between the stack and the heap, is that the heap is a type\nof memory that you, the programmer, have complete control over. This makes the heap a\nmore flexible type of memory, but it also makes it harder to work with. Because you,\nthe programmer, is responsible for managing everything related to it. Including where the memory is allocated,\nhow much memory is allocated, and where this memory is freed.\n\n> Unlike stack memory, heap memory is allocated explicitly by programmers and it won’t be deallocated until it is explicitly freed [@jenny2022].\n\nTo store an object in the heap, you, the programmer, needs to explicitly tells Zig to do so,\nby using an allocator to allocate some space in the heap. In @sec-allocators, I will present how you can use allocators to allocate memory\nin Zig.\n\n::: {.callout-important}\nEvery memory you allocate in the heap needs to be explicitly freed by you, the programmer.\n:::\n\nThe majority of allocators in Zig do allocate memory on the heap. But some exceptions to this rule are\n`ArenaAllocator()` and `FixedBufferAllocator()`. The `ArenaAllocator()` is a special\ntype of allocator that works in conjunction with a second type of allocator.\nOn the other side, the `FixedBufferAllocator()` is an allocator that works based on\nbuffer objects created on the stack. This means that the `FixedBufferAllocator()` makes\nallocations only on the stack.\n\n\n\n\n### Summary\n\nAfter discussing all of these boring details, we can quickly recap what we learned.\nIn summary, the Zig compiler will use the following rules to decide where each\nobject you declare is stored:\n\n1. every literal value (such as `\"this is string\"`, `10`, or `true`) is stored in the global data section.\n1. every constant object (`const`) whose value **is known at compile-time** is also stored in the global data section.\n1. every object (constant or not) whose length/size **is known at compile time** is stored in the stack space for the current scope.\n1. if an object is created with the method `alloc()` or `create()` of an allocator object, this object is stored in the memory space used by this particular allocator object. Most of allocators available in Zig use the heap memory, so, this object is likely stored in the heap (`FixedBufferAllocator()` is an exception to that).\n1. the heap can only be accessed through allocators. If your object was not created through the `alloc()` or `create()` methods of an allocator object, then, it is most certainly not an object stored in the heap.\n\n\n## Stack overflows {#sec-stack-overflow}\n\nAllocating memory on the stack is generally faster than allocating it on the heap.\nBut this better performance comes with many restrictions. We have already discussed\nmany of these restrictions of the stack in @sec-stack. But there is one more important\nlimitation that I want to talk about, which is the size of the stack itself.\n\nThe stack is limited in size. This size varies from computer to computer, and it depends on\na lot of things (the computer architecture, the operating system, etc.). Nevertheless, this size is usually\nnot that big. This is why we normally use the stack to store only temporary and small objects in memory.\n\nIn essence, if you try to make an allocation on the stack, that is so big that exceeds the stack size limit,\na *stack overflow* happens, and your program just crashes as a result of that. In other words, a stack overflow happens when\nyou attempt to use more space than is available on the stack.\n\nThis type of problem is very similar to a *buffer overflow*, i.e., you are trying to use more space\nthan is available in the \"buffer object\". However, a stack overflow always causes your program to crash,\nwhile a buffer overflow does not always cause your program to crash (although it often does).\n\nYou can see an example of a stack overflow in the example below. We are trying to allocate a very big array of `u64` values\non the stack. You can see below that this program does not run successfully, because it crashed\nwith a \"segmentation fault\" error message.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar very_big_alloc: [1000 * 1000 * 24]u64 = undefined;\n@memset(very_big_alloc[0..], 0);\n```\n:::\n\n\n```\nSegmentation fault (core dumped)\n```\n\nThis segmentation fault error is a result of the stack overflow that was caused by the big\nmemory allocation made on the stack, to store the `very_big_alloc` object.\nThis is why very big objects are usually stored on the heap, instead of the stack.\n\n\n\n## Allocators {#sec-allocators}\n\nOne key aspect about Zig, is that there are \"no hidden-memory allocations\" in Zig.\nWhat that really means, is that \"no allocations happen behind your back in the standard library\" [@zigguide].\n\nThis is a known problem, especially in C++. Because in C++, there are some operators that do allocate\nmemory behind the scene, and there is no way for you to know that, until you actually read the\nsource code of these operators, and find the memory allocation calls.\nMany programmers find this behaviour annoying and hard to keep track of.\n\nBut, in Zig, if a function, an operator, or anything from the standard library\nneeds to allocate some memory during its execution, then, this function/operator needs to receive (as input) an allocator\nprovided by the user, to actually be able to allocate the memory it needs.\n\nThis creates a clear distinction between functions that \"do not\" from those that \"actually do\"\nallocate memory. Just look at the arguments of this function.\nIf a function, or operator, has an allocator object as one of its inputs/arguments, then, you know for\nsure that this function/operator will allocate some memory during its execution.\n\nAn example is the `allocPrint()` function from the Zig Standard Library. With this function, you can\nwrite a new string using format specifiers. So, this function is, for example, very similar to the function `sprintf()` in C.\nIn order to write such a new string, the `allocPrint()` function needs to allocate some memory to store the\noutput string.\n\nThat is why, the first argument of this function is an allocator object that you, the user/programmer, gives\nas input to the function. In the example below, I am using the `GeneralPurposeAllocator()` as my allocator\nobject. But I could easily use any other type of allocator object from the Zig Standard Library.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nconst name = \"Pedro\";\nconst output = try std.fmt.allocPrint(\n    allocator,\n    \"Hello {s}!!!\",\n    .{name}\n);\ntry stdout.print(\"{s}\\n\", .{output});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello Pedro!!!\n```\n\n\n:::\n:::\n\n\n\nYou get a lot of control over where and how much memory this function can allocate.\nBecause it is you, the user/programmer, that provides the allocator for the function to use.\nThis makes \"total control\" over memory management easier to achieve in Zig.\n\n### What are allocators?\n\nAllocators in Zig are objects that you can use to allocate memory for your program.\nThey are similar to the memory allocating functions in C, like `malloc()` and `calloc()`.\nSo, if you need to use more memory than you initially have, during the execution of your program, you can simply ask\nfor more memory by using an allocator object.\n\nZig offers different types of allocators, and they are usually available through the `std.heap` module of\nthe standard library. Thus, just import the Zig Standard Library into your Zig module (with `@import(\"std\")`), and you can start\nusing these allocators in your code.\n\nFurthermore, every allocator object is built on top of the `Allocator` interface in Zig.\nThis means that, every allocator object you find in Zig must have the methods `alloc()`,\n`create()`, `free()` and `destroy()`. So, you can change the type of allocator you are using,\nbut you don't need to change the function calls to the methods that do the memory allocation\n(and the free memory operations) for your program.\n\n### Why you need an allocator?\n\nAs we described in @sec-stack, everytime you make a function call in Zig,\na space in the stack is reserved for this function call. But the stack\nhas a key limitation which is: every object stored in the stack has a\nknown fixed length.\n\nBut in reality, there are two very common instances where this \"fixed length limitation\" of the stack is a deal braker:\n\n1. the objects that you create inside your function might grow in size during the execution of the function.\n1. sometimes, it's impossible to know upfront how many inputs you will receive, or how big this input will be.\n\nAlso, there is another instance where you might want to use an allocator, which is when you want to write a function that returns a pointer\nto a local object. As I described in @sec-stack, you cannot do that if this local object is stored in the\nstack. However, if this object is stored in the heap, then, you can return a pointer to this object at the\nend of the function. Because you (the programmer) control the lifetime of any heap memory that you allocate. You decide\nwhen this memory gets destroyed/freed.\n\nThese are common situations for which the stack is not good.\nThat is why you need a different memory management strategy to\nstore these objects inside your function. You need to use\na memory type that can grow together with your objects, or that you\ncan control the lifetime of this memory.\nThe heap fits this description.\n\nAllocating memory on the heap is commonly known as dynamic memory management. As the objects you create grow in size\nduring the execution of your program, you grow the amount of memory\nyou have by allocating more memory in the heap to store these objects.\nAnd you do that in Zig, by using an allocator object.\n\n\n### The different types of allocators\n\n\nAt the moment of the writing of this book, in Zig, we have 6 different\nallocators available in the standard library:\n\n- `GeneralPurposeAllocator()`.\n- `page_allocator()`.\n- `FixedBufferAllocator()` and `ThreadSafeFixedBufferAllocator()`.\n- `ArenaAllocator()`.\n- `c_allocator()` (requires you to link to libc).\n\n\nEach allocator has its own perks and limitations. All allocators, except `FixedBufferAllocator()` and `ArenaAllocator()`,\nare allocators that use the heap memory. So any memory that you allocate with\nthese allocators, will be placed in the heap.\n\n### General-purpose allocators\n\nThe `GeneralPurposeAllocator()`, as the name suggests, is a \"general purpose\" allocator. You can use it for every type\nof task. In the example below, I'm allocating enough space to store a single integer in the object `some_number`.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    const some_number = try allocator.create(u32);\n    defer allocator.destroy(some_number);\n\n    some_number.* = @as(u32, 45);\n}\n```\n:::\n\n\n\nWhile useful, you might want to use the `c_allocator()`, which is a alias to the C standard allocator `malloc()`. So, yes, you can use\n`malloc()` in Zig if you want to. Just use the `c_allocator()` from the Zig standard library. However,\nif you do use `c_allocator()`, you must link to Libc when compiling your source code with the\n`zig` compiler, by including the flag `-lc` in your compilation process.\nIf you do not link your source code to Libc, Zig will not be able to find the\n`malloc()` implementation in your system.\n\n### Page allocator\n\nThe `page_allocator()` is an allocator that allocates full pages of memory in the heap. In other words,\nevery time you allocate memory with `page_allocator()`, a full page of memory in the heap is allocated,\ninstead of just a small piece of it.\n\nThe size of this page depends on the system you are using.\nMost systems use a page size of 4KB in the heap, so, that is the amount of memory that is normally\nallocated in each call by `page_allocator()`. That is why, `page_allocator()` is considered a\nfast, but also \"wasteful\" allocator in Zig. Because it allocates a big amount of memory\nin each call, and you most likely will not need that much memory in your program.\n\n### Buffer allocators\n\nThe `FixedBufferAllocator()` and `ThreadSafeFixedBufferAllocator()` are allocator objects that\nwork with a fixed sized buffer object at the back. In other words, they use a fixed sized buffer\nobject as the basis for the memory. When you ask these allocator objects to allocate some memory for you,\nthey are essentially reserving some amount of space inside this fixed sized buffer object for you to use.\n\nThis means that, in order to use these allocators, you must first create a buffer object in your code,\nand then, give this buffer object as an input to these allocators.\n\nThis also means that, these allocator objects can allocate memory both in the stack or in the heap.\nEverything depends on where the buffer object that you provide lives. If this buffer object lives\nin the stack, then, the memory allocated is \"stack-based\". But if it lives on the heap, then,\nthe memory allocated is \"heap-based\".\n\n\nIn the example below, I'm creating a `buffer` object on the stack that is 10 elements long.\nNotice that I give this `buffer` object to the `FixedBufferAllocator()` constructor.\nNow, because this `buffer` object is 10 elements long, this means that I am limited to this space.\nI cannot allocate more than 10 elements with this allocator object. If I try to\nallocate more than that, the `alloc()` method will return an `OutOfMemory` error value.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar buffer: [10]u8 = undefined;\nfor (0..buffer.len) |i| {\n    buffer[i] = 0; // Initialize to zero\n}\n\nvar fba = std.heap.FixedBufferAllocator.init(&buffer);\nconst allocator = fba.allocator();\nconst input = try allocator.alloc(u8, 5);\ndefer allocator.free(input);\n```\n:::\n\n\nRemember, the memory allocated by these allocator objects can be either from\nthe stack, or, from the heap. It all depends on where the buffer object that you provide lives.\nIn the above example, the `buffer` object lives in the stack, and, therefore, the memory allocated\nis based in the stack. But what if it was based on the heap?\n\nAs we described in @sec-stack-overflow, one of the main reasons why you would use the heap,\ninstead of the stack, is to allocate huge amounts of space to store very big objects.\nThus, let's suppose you wanted to use a very big buffer object as the basis for your\nallocator objects. You would have to allocate this very big buffer object on the heap.\nThe example below demonstrates this case.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst heap = std.heap.page_allocator;\nconst memory_buffer = try heap.alloc(\n    u8, 100 * 1024 * 1024 // 100 MB memory\n);\ndefer heap.free(memory_buffer);\nvar fba = std.heap.FixedBufferAllocator.init(\n    memory_buffer\n);\nconst allocator = fba.allocator();\n\nconst input = try allocator.alloc(u8, 1000);\ndefer allocator.free(input);\n```\n:::\n\n\n\n\n### Arena allocator {#sec-arena-allocator}\n\nThe `ArenaAllocator()` is an allocator object that takes a child allocator as input. The idea behind the `ArenaAllocator()` in Zig\nis similar to the concept of \"arenas\" in the programming language Go[^go-arena]. It's an allocator object that allows you\nto allocate memory as many times you want, but free all memory only once.\nIn other words, if you have, for example, called 5 times the method `alloc()` of an `ArenaAllocator()` object, you can\nfree all the memory you allocated over these 5 calls at once, by simply calling the `deinit()` method of the same `ArenaAllocator()` object.\n\n[^go-arena]: \n\nIf you give, for example, a `GeneralPurposeAllocator()` object as input to the `ArenaAllocator()` constructor, like in the example below, then, the allocations\nyou perform with `alloc()` will actually be made with the underlying object `GeneralPurposeAllocator()` that was passed.\nSo, with an arena allocator, any new memory you ask for is allocated by the child allocator. The only thing that an arena allocator\nreally does is help you to free all the memory you allocated multiple times with just a single command. In the example\nbelow, I called `alloc()` 3 times. So, if I did not use an arena allocator, then, I would need to call\n`free()` 3 times to free all the allocated memory.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nvar aa = std.heap.ArenaAllocator.init(gpa.allocator());\ndefer aa.deinit();\nconst allocator = aa.allocator();\n\nconst in1 = try allocator.alloc(u8, 5);\nconst in2 = try allocator.alloc(u8, 10);\nconst in3 = try allocator.alloc(u8, 15);\n_ = in1; _ = in2; _ = in3;\n```\n:::\n\n\n\n\n### The `alloc()` and `free()` methods\n\nIn the code example below, we are accessing the `stdin`, which is\nthe standard input channel, to receive an input from the\nuser. We read the input given by the user with the `readUntilDelimiterOrEof()`\nmethod.\n\nNow, after reading the input of the user, we need to store this input somewhere in\nour program. That is why I use an allocator in this example. I use it to allocate some\namount of memory to store this input given by the user. More specifically, the method `alloc()`\nof the allocator object is used to allocate an array capable of storing 50 `u8` values.\n\nNotice that this `alloc()` method receives two inputs. The first one, is a type.\nThis defines what type of values the allocated array will store. In the example\nbelow, we are allocating an array of unsigned 8-bit integers (`u8`). But\nyou can create an array to store any type of value you want. Next, in the second argument, we\ndefine the size of the allocated array, by specifying how many elements\nthis array will contain. In the case below, we are allocating an array of 50 elements.\n\nIn @sec-zig-strings we described that strings in Zig are simply arrays of characters.\nEach character is represented by a `u8` value. So, this means that the array that\nwas allocated in the object `input` is capable of storing a string that is\n50-characters long.\n\nSo, in essence, the expression `var input: [50]u8 = undefined` would create\nan array for 50 `u8` values in the stack of the current scope. But, you\ncan allocate the same array in the heap by using the expression `var input = try allocator.alloc(u8, 50)`.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdin = std.io.getStdIn();\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    var input = try allocator.alloc(u8, 50);\n    defer allocator.free(input);\n    for (0..input.len) |i| {\n        input[i] = 0; // initialize all fields to zero.\n    }\n    // read user input\n    const input_reader = stdin.reader();\n    _ = try input_reader.readUntilDelimiterOrEof(\n        input,\n        '\\n'\n    );\n    std.debug.print(\"{s}\\n\", .{input});\n}\n```\n:::\n\n\nAlso, notice that in this example, we use the `defer` keyword (which I described in @sec-defer) to run a small\npiece of code at the end of the current scope, which is the expression `allocator.free(input)`.\nWhen you execute this expression, the allocator will free the memory that it allocated\nfor the `input` object.\n\nWe have talked about this in @sec-heap. You **should always** explicitly free any memory that you allocate\nusing an allocator! You do that by using the `free()` method of the same allocator object you\nused to allocate this memory. The `defer` keyword is used in this example only to help us execute\nthis free operation at the end of the current scope.\n\n\n### The `create()` and `destroy()` methods\n\nWith the `alloc()` and `free()` methods, you can allocate memory to store multiple elements\nat once. In other words, with these methods, we always allocate an array to store multiple elements at once.\nBut what if you need enough space to store just a single item? Should you\nallocate an array of a single element through `alloc()`?\n\nThe answer is no! In this case,\nyou should use the `create()` method of the allocator object.\nEvery allocator object offers the `create()` and `destroy()` methods,\nwhich are used to allocate and free memory for a single item, respectively.\n\nSo, in essence, if you want to allocate memory to store an array of elements, you\nshould use `alloc()` and `free()`. But if you need to store just a single item,\nthen, the `create()` and `destroy()` methods are ideal for you.\n\nIn the example below, I'm defining a struct to represent an user of some sort.\nIt could be a user for a game, or software to manage resources, it doesn't mater.\nNotice that I use the `create()` method this time, to store a single `User` object\nin the program. Also notice that I use the `destroy()` method to free the memory\nused by this object at the end of the scope.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst User = struct {\n    id: usize,\n    name: []const u8,\n\n    pub fn init(id: usize, name: []const u8) User {\n        return .{ .id = id, .name = name };\n    }\n};\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    const user = try allocator.create(User);\n    defer allocator.destroy(user);\n\n    user.* = User.init(0, \"Pedro\");\n}\n```\n:::\n",
    +    "supporting": [],
         "filters": [
           "rmarkdown/pagebreak.lua"
         ],
    diff --git a/_freeze/Chapters/01-zig-weird/execute-results/epub.json b/_freeze/Chapters/01-zig-weird/execute-results/epub.json
    deleted file mode 100644
    index 6385ce4f..00000000
    --- a/_freeze/Chapters/01-zig-weird/execute-results/epub.json
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -{
    -  "hash": "4d435d48922c81726d4668b9e1fc1e4f",
    -  "result": {
    -    "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it's still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. Sometimes, they really make it hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscure the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that gets compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e., where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n    ├── main.zig\n    └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contains Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nWe can use this build system to write small scripts in Zig,\nwhich describe the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e., creating new objects)\nare made in Zig. You can create a new object in Zig by using the syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). In @sec-assignments we talk more about objects in general.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n    return a + b;\n}\n```\n:::\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that in @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIt's worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt's like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n    const stdout = std.io.getStdOut().writer();\n    try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portable C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig  build.zig.zon  main  src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nIn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e., the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. If you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith an \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, on Windows, operations like accessing the `stdout` (or opening a file) depend on\nresources that are available only at *runtime* (you will learn more about compile-time versus runtime\nin @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerges from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n    break :blk asm {\n               ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword in @sec-comptime.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    // SUCCESS: Stdout initialized at runtime.\n    const stdout = std.io.getStdOut().writer();\n    _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation in a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues\n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described in @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig later in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig?\nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar to our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentation.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It's a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (on YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e., identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n    age = 25;\n      ~~^~~\n```\n\nSo, if you want to change the value of your object, you need to transform your immutable (or \"constant\")\nobject into a mutable (or \"variable\") object. You can do that by using the `var` keyword.\nThis keyword stands for \"variable\", and when you apply this keyword to some object, you are\ntelling the Zig compiler that the value associated with this object might change at some point.\n\nThus, if we come back to the previous example, and change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it's a \"variable object\".\n\nHowever, if you take a look at the example below, you will notice that we have not only declared the\n`age` object with the `var` keyword, but we also have explicitly annotated the data type\nof the `age` object with the `u8` type this time. The basic idea is, when we use a variable/mutable object,\nthe Zig compiler ask for us to be more explicit with what we want, to be more clear\nabout what our code does. This translates into being more explicit about the data types that we want\nto use in our objects.\n\nTherefore, if you transform your object into a variable/mutable object, just remember to always\nannotate the type of the object explicitly in your code. Otherwise, the Zig compiler might raise\na compilation error, asking you to transform your object back into a `const` object, or,\nto give your object an \"explicit type\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIt's important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code uses this object while it's uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object.\n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e., if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n```\nt.zig:4:11: error: unused local constant\n    const age = 15;\n          ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to a special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It's discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n```\nt.zig:7:5: error: pointless discard\n    of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also gets discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig has many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e., the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\nIt's worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it has the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it's a slice that\naccesses all elements in the array.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhas 2 elements in it.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" in @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth in @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially in @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned in @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e., both the start and the end of this range)\nis known at compile-time, the slice object that gets created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nin @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that gets created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e., a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can\ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n    1, 2, 3, 4, 5,\n    6, 7, 8, 9, 10\n};\n// This slice has a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n_ = slice;\n```\n:::\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat gets created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, we are reading a file, and then, we try to create a slice object\nthat covers the entire buffer that contains the contents of this file. This is obviously\nan example of a runtime known range, because the end index of the range\nis not known at compile time.\n\nIn other words, the end index of the range is the size of\nthe array `file_contents`. However, the size of `file_contents` is not known at compile time.\nBecause we don't know how many bytes are stored inside this `shop-list.txt` file.\nAnd because this is a file, someone might edit this file tomorrow and add more lines\nor remove lines from it. Therefore, the size of this file might vary drastically from one execution to another.\n\nNow, if the file size can vary from one run to another, then, we can conclude that the value of the expression\n`file_contents.len` exposed in the example below can also vary from one run to another. As consequence,\nthe value of the expression `file_contents.len` is runtime-known only, and, as a consequence of that,\nthe range `0..file_contents.len` is also runtime-known only.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\nfn read_file(allocator: std.mem.Allocator, path: []const u8) ![]u8 {\n    const file = try std.fs.cwd().openFile(path, .{});\n    defer file.close();\n    return try file.reader().readAllAlloc(\n        allocator, std.math.maxInt(usize)\n    );\n}\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    const path = \"../ZigExamples/file-io/shop-list.txt\";\n    const file_contents = try read_file(allocator, path);\n    const slice = file_contents[0..file_contents.len];\n    _ = slice;\n}\n```\n:::\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code has its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e., a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n    y += 1;\n    break :add_one y;\n};\nif (x == 124 and y == 124) {\n    try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nStrings in Zig work very similarly to strings in C, but they come with some extra caveats which adds more safety\nand efficiency to them. You could also say that Zig simply uses a more modern and safe approach to manage\nand use strings.\n\nA string in Zig is essentially an array of arbitrary bytes, or, more specifically, an array of `u8` values.\nThis very similar to a string in C, which is also interpreted as an array of arbitrary bytes, or, in the case\nof C, an array of `char` (which usually represents an unsigned 8-bit integer value in most systems) values.\n\nNow, because a string in Zig is an array, you automatically\nget the length of the string (i.e. the length of the array) embedded in the value itself. This makes\nall the difference! Because now, the Zig compiler can use the length value that is embedded in the string to\ncheck for \"buffer overflow\" or \"wrong memory access\" problems in your code.\n\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need to do something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n    char* array = \"An example of string in C\";\n    int index = 0;\n    while (1) {\n        if (array[index] == '\\0') {\n            break;\n        }\n        index++;\n    }\n    printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible in the string value itself. You can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"This is an example of string literal in Zig\";\n    try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\nAnother point is that Zig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e., a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n    try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\n### Using a slice versus a sentinel-terminated array\n\nIn memory, all string values in Zig are always stored in the same way.\nThey are simply stored as sequences/arrays of arbitrary bytes. But you can use and access\nthis sequence of bytes in two different ways. You can access this sequence of bytes as:\n\n- a sentinel-terminated array of `u8` values.\n- or as a slice of `u8` values.\n\n\n#### Sentinel-terminated arrays\n\nSentinel-terminated arrays in Zig are described in the Language Reference of Zig[^sentinel].\nIn summary a sentinel-terminated array is just a normal array, but, the difference is that they\ncontain a \"sentinel value\" at the last index/element of the array. With a sentinel-terminated array\nyou embed both the length of the array, and also, the sentinel value in the type itself of your object.\n\n[^sentinel]: .\n\nFor example, if you write a string literal value in your code, and ask Zig to print the data type of this value,\nyou usually get a data type in the format `*const [n:0]u8`. The `n` in the data type indicates the size of\nthe string (that is the length of the array). The zero after the `n:` part of the data type is the sentinel\nvalue itself.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n_ = \"A literal value\";\ntry stdout.print(\"{any}\\n\", .{@TypeOf(\"A literal value\")});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n*const [15:0]u8\n```\n\n\n:::\n:::\n\n\n\n\nSo, with this data type `*const [n:0]u8` you are essentially saying that you have an array of `u8` values\nof length `n`, where, the element at the index corresponding to the length `n` in the array is the\nnumber zero. If you really think about this description, you will notice that this is just a fancy way to\ndescribe a string in C, which is a null-terminated array of bytes. The `NULL` value in C is the number\nzero. So, an array that ends in a null/zero value in C is essentially a sentinel-terminated array in Zig,\nwhere the sentinel value of the array is the number zero.\n\nTherefore, a string literal value in Zig is just a pointer to a null-terminated array of bytes (i.e., similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string, and also, the fact that they are \"NULL terminated\",\ninto the data type of the value itself.\n\n\n\n#### Slice\n\nYou can also access and use the arbitrary sequence of bytes that represent your string as a slice of `u8` values.\nThe majority of functions from the Zig standard library usually receive strings as inputs as slices of\n`u8` values (slices were presented in @sec-arrays).\n\nThus, you will see a lot of string values with a data type of `[]u8` or `[]const u8`, depending if the object\nwhere this string is stored is marked as constant with `const`, or as variable with `var`. Now, because\nthe string in this case is being interpreted as a slice, this slice is not necessarilly null-terminated,\nbecause now, the sentinel value is not mandatory. You can include the null/zero value in the slice if you\nwant to, but there is no need to do it.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string value being\n// interpreted as a slice.\nconst str: []const u8 = \"A string value\";\ntry stdout.print(\"{any}\\n\", .{@TypeOf(str)});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n[]const u8\n```\n\n\n:::\n:::\n\n\n\n\n\n### Iterating through the string\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"This is an example\";\n    try stdout.print(\"Bytes that represents the string object: \", .{});\n    for (string_object) |byte| {\n        try stdout.print(\"{X} \", .{byte});\n    }\n    try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n   73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below,\nand also, you can see that this is a null-terminated array, because of the zero value after the `:` character in the data type.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it's a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    const simple_array = [_]i32{1, 2, 3, 4};\n    const string_obj: []const u8 = \"A string object\";\n    std.debug.print(\n        \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n    );\n    std.debug.print(\n        \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n    );\n    std.debug.print(\n        \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n    );\n    std.debug.print(\n        \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n    );\n}\n```\n:::\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIt's important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"Ⱥ\";\n    _ = try stdout.write(\n        \"Bytes that represents the string object: \"\n    );\n    for (string_object) |char| {\n        try stdout.print(\"{X} \", .{char});\n    }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop through the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n    var iterator = utf8.iterator();\n    while (iterator.nextCodepointSlice()) |codepoint| {\n        try stdout.print(\n            \"got codepoint {}\\n\",\n            .{std.fmt.fmtSliceHexUpper(codepoint)},\n        );\n    }\n}\n\n```\n:::\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n    \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n    \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n    allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n    u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig in @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers in @sec-root-file and especially in @sec-assignments.\n- How strings work in Zig in @sec-zig-strings.\n- How to use arrays and slices in @sec-arrays.\n- How to import functionality from other Zig modules in @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* in @sec-structs-and-oop.\n- Basic control flow syntax in @sec-zig-control-flow.\n- Enums in @sec-enum;\n- Pointers and Optionals in @sec-pointer;\n- Error handling with `try` and `catch` in @sec-error-handling;\n- Unit tests in @sec-unittests;\n- Vectors in @sec-vectors-simd;\n- Build System in @sec-build-system;\n",
    -    "supporting": [
    -      "01-zig-weird_files"
    -    ],
    -    "filters": [
    -      "rmarkdown/pagebreak.lua"
    -    ],
    -    "includes": {},
    -    "engineDependencies": {
    -      "knitr": [
    -        "{\"type\":\"list\",\"attributes\":{},\"value\":[]}"
    -      ]
    -    },
    -    "preserve": null,
    -    "postProcess": false
    -  }
    -}
    \ No newline at end of file
    diff --git a/_freeze/Chapters/01-zig-weird/execute-results/html.json b/_freeze/Chapters/01-zig-weird/execute-results/html.json
    index 4920b2b5..6ef9bbe0 100644
    --- a/_freeze/Chapters/01-zig-weird/execute-results/html.json
    +++ b/_freeze/Chapters/01-zig-weird/execute-results/html.json
    @@ -2,7 +2,7 @@
       "hash": "4d435d48922c81726d4668b9e1fc1e4f",
       "result": {
         "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it's still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. Sometimes, they really make it hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscure the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that gets compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e., where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n    ├── main.zig\n    └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contains Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nWe can use this build system to write small scripts in Zig,\nwhich describe the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e., creating new objects)\nare made in Zig. You can create a new object in Zig by using the syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). In @sec-assignments we talk more about objects in general.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n    return a + b;\n}\n```\n:::\n\n\n\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that in @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIt's worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt's like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n    const stdout = std.io.getStdOut().writer();\n    try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\n\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portable C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig  build.zig.zon  main  src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nIn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e., the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. If you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith an \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, on Windows, operations like accessing the `stdout` (or opening a file) depend on\nresources that are available only at *runtime* (you will learn more about compile-time versus runtime\nin @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerges from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n    break :blk asm {\n               ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword in @sec-comptime.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    // SUCCESS: Stdout initialized at runtime.\n    const stdout = std.io.getStdOut().writer();\n    _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation in a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues\n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described in @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig later in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig?\nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar to our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentation.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It's a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (on YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e., identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n    age = 25;\n      ~~^~~\n```\n\nSo, if you want to change the value of your object, you need to transform your immutable (or \"constant\")\nobject into a mutable (or \"variable\") object. You can do that by using the `var` keyword.\nThis keyword stands for \"variable\", and when you apply this keyword to some object, you are\ntelling the Zig compiler that the value associated with this object might change at some point.\n\nThus, if we come back to the previous example, and change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it's a \"variable object\".\n\nHowever, if you take a look at the example below, you will notice that we have not only declared the\n`age` object with the `var` keyword, but we also have explicitly annotated the data type\nof the `age` object with the `u8` type this time. The basic idea is, when we use a variable/mutable object,\nthe Zig compiler ask for us to be more explicit with what we want, to be more clear\nabout what our code does. This translates into being more explicit about the data types that we want\nto use in our objects.\n\nTherefore, if you transform your object into a variable/mutable object, just remember to always\nannotate the type of the object explicitly in your code. Otherwise, the Zig compiler might raise\na compilation error, asking you to transform your object back into a `const` object, or,\nto give your object an \"explicit type\".\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIt's important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code uses this object while it's uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\n\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object.\n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e., if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n\n\n\n```\nt.zig:4:11: error: unused local constant\n    const age = 15;\n          ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to a special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\n\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It's discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: pointless discard\n    of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also gets discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig has many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e., the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\n\n\n\nIt's worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\n\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it has the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\n\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it's a slice that\naccesses all elements in the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhas 2 elements in it.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" in @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\n\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth in @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially in @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned in @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e., both the start and the end of this range)\nis known at compile-time, the slice object that gets created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nin @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that gets created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e., a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can\ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n    1, 2, 3, 4, 5,\n    6, 7, 8, 9, 10\n};\n// This slice has a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n_ = slice;\n```\n:::\n\n\n\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat gets created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, we are reading a file, and then, we try to create a slice object\nthat covers the entire buffer that contains the contents of this file. This is obviously\nan example of a runtime known range, because the end index of the range\nis not known at compile time.\n\nIn other words, the end index of the range is the size of\nthe array `file_contents`. However, the size of `file_contents` is not known at compile time.\nBecause we don't know how many bytes are stored inside this `shop-list.txt` file.\nAnd because this is a file, someone might edit this file tomorrow and add more lines\nor remove lines from it. Therefore, the size of this file might vary drastically from one execution to another.\n\nNow, if the file size can vary from one run to another, then, we can conclude that the value of the expression\n`file_contents.len` exposed in the example below can also vary from one run to another. As consequence,\nthe value of the expression `file_contents.len` is runtime-known only, and, as a consequence of that,\nthe range `0..file_contents.len` is also runtime-known only.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\nfn read_file(allocator: std.mem.Allocator, path: []const u8) ![]u8 {\n    const file = try std.fs.cwd().openFile(path, .{});\n    defer file.close();\n    return try file.reader().readAllAlloc(\n        allocator, std.math.maxInt(usize)\n    );\n}\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    const path = \"../ZigExamples/file-io/shop-list.txt\";\n    const file_contents = try read_file(allocator, path);\n    const slice = file_contents[0..file_contents.len];\n    _ = slice;\n}\n```\n:::\n\n\n\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code has its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e., a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n    y += 1;\n    break :add_one y;\n};\nif (x == 124 and y == 124) {\n    try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nStrings in Zig work very similarly to strings in C, but they come with some extra caveats which adds more safety\nand efficiency to them. You could also say that Zig simply uses a more modern and safe approach to manage\nand use strings.\n\nA string in Zig is essentially an array of arbitrary bytes, or, more specifically, an array of `u8` values.\nThis very similar to a string in C, which is also interpreted as an array of arbitrary bytes, or, in the case\nof C, an array of `char` (which usually represents an unsigned 8-bit integer value in most systems) values.\n\nNow, because a string in Zig is an array, you automatically\nget the length of the string (i.e. the length of the array) embedded in the value itself. This makes\nall the difference! Because now, the Zig compiler can use the length value that is embedded in the string to\ncheck for \"buffer overflow\" or \"wrong memory access\" problems in your code.\n\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need to do something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n    char* array = \"An example of string in C\";\n    int index = 0;\n    while (1) {\n        if (array[index] == '\\0') {\n            break;\n        }\n        index++;\n    }\n    printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible in the string value itself. You can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"This is an example of string literal in Zig\";\n    try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\n\n\n\nAnother point is that Zig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e., a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n    try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### Using a slice versus a sentinel-terminated array\n\nIn memory, all string values in Zig are always stored in the same way.\nThey are simply stored as sequences/arrays of arbitrary bytes. But you can use and access\nthis sequence of bytes in two different ways. You can access this sequence of bytes as:\n\n- a sentinel-terminated array of `u8` values.\n- or as a slice of `u8` values.\n\n\n#### Sentinel-terminated arrays\n\nSentinel-terminated arrays in Zig are described in the Language Reference of Zig[^sentinel].\nIn summary a sentinel-terminated array is just a normal array, but, the difference is that they\ncontain a \"sentinel value\" at the last index/element of the array. With a sentinel-terminated array\nyou embed both the length of the array, and also, the sentinel value in the type itself of your object.\n\n[^sentinel]: .\n\nFor example, if you write a string literal value in your code, and ask Zig to print the data type of this value,\nyou usually get a data type in the format `*const [n:0]u8`. The `n` in the data type indicates the size of\nthe string (that is the length of the array). The zero after the `n:` part of the data type is the sentinel\nvalue itself.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n_ = \"A literal value\";\ntry stdout.print(\"{any}\\n\", .{@TypeOf(\"A literal value\")});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n*const [15:0]u8\n```\n\n\n:::\n:::\n\n\n\n\n\n\nSo, with this data type `*const [n:0]u8` you are essentially saying that you have an array of `u8` values\nof length `n`, where, the element at the index corresponding to the length `n` in the array is the\nnumber zero. If you really think about this description, you will notice that this is just a fancy way to\ndescribe a string in C, which is a null-terminated array of bytes. The `NULL` value in C is the number\nzero. So, an array that ends in a null/zero value in C is essentially a sentinel-terminated array in Zig,\nwhere the sentinel value of the array is the number zero.\n\nTherefore, a string literal value in Zig is just a pointer to a null-terminated array of bytes (i.e., similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string, and also, the fact that they are \"NULL terminated\",\ninto the data type of the value itself.\n\n\n\n#### Slice\n\nYou can also access and use the arbitrary sequence of bytes that represent your string as a slice of `u8` values.\nThe majority of functions from the Zig standard library usually receive strings as inputs as slices of\n`u8` values (slices were presented in @sec-arrays).\n\nThus, you will see a lot of string values with a data type of `[]u8` or `[]const u8`, depending if the object\nwhere this string is stored is marked as constant with `const`, or as variable with `var`. Now, because\nthe string in this case is being interpreted as a slice, this slice is not necessarilly null-terminated,\nbecause now, the sentinel value is not mandatory. You can include the null/zero value in the slice if you\nwant to, but there is no need to do it.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string value being\n// interpreted as a slice.\nconst str: []const u8 = \"A string value\";\ntry stdout.print(\"{any}\\n\", .{@TypeOf(str)});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n[]const u8\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### Iterating through the string\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"This is an example\";\n    try stdout.print(\"Bytes that represents the string object: \", .{});\n    for (string_object) |byte| {\n        try stdout.print(\"{X} \", .{byte});\n    }\n    try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n   73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below,\nand also, you can see that this is a null-terminated array, because of the zero value after the `:` character in the data type.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it's a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    const simple_array = [_]i32{1, 2, 3, 4};\n    const string_obj: []const u8 = \"A string object\";\n    std.debug.print(\n        \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n    );\n    std.debug.print(\n        \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n    );\n    std.debug.print(\n        \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n    );\n    std.debug.print(\n        \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n    );\n}\n```\n:::\n\n\n\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIt's important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"Ⱥ\";\n    _ = try stdout.write(\n        \"Bytes that represents the string object: \"\n    );\n    for (string_object) |char| {\n        try stdout.print(\"{X} \", .{char});\n    }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop through the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n    var iterator = utf8.iterator();\n    while (iterator.nextCodepointSlice()) |codepoint| {\n        try stdout.print(\n            \"got codepoint {}\\n\",\n            .{std.fmt.fmtSliceHexUpper(codepoint)},\n        );\n    }\n}\n\n```\n:::\n\n\n\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n    \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n    \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\n\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n    allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n    u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig in @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers in @sec-root-file and especially in @sec-assignments.\n- How strings work in Zig in @sec-zig-strings.\n- How to use arrays and slices in @sec-arrays.\n- How to import functionality from other Zig modules in @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* in @sec-structs-and-oop.\n- Basic control flow syntax in @sec-zig-control-flow.\n- Enums in @sec-enum;\n- Pointers and Optionals in @sec-pointer;\n- Error handling with `try` and `catch` in @sec-error-handling;\n- Unit tests in @sec-unittests;\n- Vectors in @sec-vectors-simd;\n- Build System in @sec-build-system;\n",
    +    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n# Introducing Zig\n\nIn this chapter, I want to introduce you to the world of Zig.\nZig is a very young language that is being actively developed.\nAs a consequence, its world is still very wild and to be explored.\nThis book is my attempt to help you on your personal journey for\nunderstanding and exploring the exciting world of Zig.\n\nI assume you have previous experience with some programming\nlanguage in this book, not necessarily with a low-level one.\nSo, if you have experience with Python, or Javascript, for example, it will be fine.\nBut, if you do have experience with low-level languages, such as C, C++, or\nRust, you will probably learn faster throughout this book.\n\n## What is Zig?\n\nZig is a modern, low-level, and general-purpose programming language. Some programmers think of\nZig as a modern and better version of C.\n\nIn the author's personal interpretation, Zig is tightly connected with \"less is more\".\nInstead of trying to become a modern language by adding more and more features,\nmany of the core improvements that Zig brings to the\ntable are actually about removing annoying behaviours/features from C and C++.\nIn other words, Zig tries to be better by simplifying the language, and by having more consistent and robust behaviour.\nAs a result, analyzing, writing and debugging applications become much easier and simpler in Zig, than it is in C or C++.\n\nThis philosophy becomes clear with the following phrase from the official website of Zig:\n\n> \"Focus on debugging your application rather than debugging your programming language knowledge\".\n\nThis phrase is specially true for C++ programmers. Because C++ is a gigantic language,\nwith tons of features, and also, there are lots of different \"flavors of C++\". These elements\nare what makes C++ so complex and hard to learn. Zig tries to go in the opposite direction.\nZig is a very simple language, more closely related to other simple languages such as C and Go.\n\nThe phrase above is still important for C programmers too. Because, even C being a simple\nlanguage, it's still hard sometimes to read and understand C code. For example, pre-processor macros in\nC are a frequent source of confusion. Sometimes, they really make it hard to debug\nC programs. Because macros are essentially a second language embedded in C that obscures\nyour C code. With macros, you are no longer 100% sure about which pieces\nof the code are being sent to the compiler, i.e.\nthey obscure the actual source code that you wrote.\n\nYou don't have macros in Zig. In Zig, the code you write, is the actual code that gets compiled by the compiler.\nYou also don't have a hidden control flow happening behind the scenes. And, you also\ndon't have functions or operators from the standard library that make\nhidden memory allocations behind your back.\n\nBy being a simpler language, Zig becomes much more clear and easier to read/write,\nbut at the same time, it also achieves a much more robust state, with more consistent\nbehaviour in edge situations. Once again, less is more.\n\n\n## Hello world in Zig\n\nWe begin our journey in Zig by creating a small \"Hello World\" program.\nTo start a new Zig project in your computer, you simply call the `init` command\nfrom the `zig` compiler.\nJust create a new directory in your computer, then, init a new Zig project\ninside this directory, like this:\n\n```bash\nmkdir hello_world\ncd hello_world\nzig init\n```\n\n```\ninfo: created build.zig\ninfo: created build.zig.zon\ninfo: created src/main.zig\ninfo: created src/root.zig\ninfo: see `zig build --help` for a menu of options\n```\n\n### Understanding the project files {#sec-project-files}\n\nAfter you run the `init` command from the `zig` compiler, some new files\nare created inside of your current directory. First, a \"source\" (`src`) directory\nis created, containing two files, `main.zig` and `root.zig`. Each `.zig` file\nis a separate Zig module, which is simply a text file that contains some Zig code.\n\nBy convention, the `main.zig` module is where your main function lives. Thus,\nif you are building an executable program in Zig, you need to declare a `main()` function,\nwhich represents the entrypoint of your program, i.e., where the execution of your program begins.\n\nHowever, if you are building a library (instead of an executable program), then,\nthe normal procedure is to delete this `main.zig` file and start with the `root.zig` module.\nBy convention, the `root.zig` module is the root source file of your library.\n\n```bash\ntree .\n```\n\n```\n.\n├── build.zig\n├── build.zig.zon\n└── src\n    ├── main.zig\n    └── root.zig\n\n1 directory, 4 files\n```\n\nThe `init` command also creates two additional files in our working directory:\n`build.zig` and `build.zig.zon`. The first file (`build.zig`) represents a build script written in Zig.\nThis script is executed when you call the `build` command from the `zig` compiler.\nIn other words, this file contains Zig code that executes the necessary steps to build the entire project.\n\n\nLow-level languages normally use a compiler to build your\nsource code into binary executables or binary libraries.\nNevertheless, this process of compiling your source code and building\nbinary executables or binary libraries from it, became a real challenge\nin the programming world, once the projects became bigger and bigger.\nAs a result, programmers created \"build systems\", which are a second set of tools designed to make this process\nof compiling and building complex projects, easier.\n\nExamples of build systems are CMake, GNU Make, GNU Autoconf and Ninja,\nwhich are used to build complex C and C++ projects.\nWith these systems, you can write scripts, which are called \"build scripts\".\nThey simply are scripts that describes the necessary steps to compile/build\nyour project.\n\nHowever, these are separate tools, that do not\nbelong to C/C++ compilers, like `gcc` or `clang`.\nAs a result, in C/C++ projects, you have not only to install and\nmanage your C/C++ compilers, but you also have to install and manage\nthese build systems separately.\n\nIn Zig, we don't need to use a separate set of tools to build our projects,\nbecause a build system is embedded inside the language itself.\nWe can use this build system to write small scripts in Zig,\nwhich describe the necessary steps to build/compile our Zig project[^zig-build-system].\nSo, everything you need to build a complex Zig project is the\n`zig` compiler, and nothing more.\n\n[^zig-build-system]: .\n\n\nThe second generated file (`build.zig.zon`) is a JSON-like file, in which you can describe\nyour project, and also, declare a set of dependencies of your project that you want to fetch from the internet.\nIn other words, you can use this `build.zig.zon` file to include a list of external libraries in your project.\n\nOne possible way to include an external Zig library in your project, is to manually build\nand install the library in your system, and just link your source code\nwith the library at the build step of your project.\n\nHowever, if this external Zig library is available on GitHub for example,\nand it has a valid `build.zig.zon` file in root folder of the project,\nwhich describes the project, you can easily include this library in\nyour project by simply listing this external library in your `build.zig.zon` file.\n\nIn other words, this `build.zig.zon` file works similarly to the `package.json`\nfile in Javascript projects, or the `Pipfile` file in Python projects,\nor the `Cargo.toml` file in Rust projects. You can read more about this\nspecific file in a couple of articles on the internet[^zig-zon][^zig-zon2], and\nyou can also see the expected schema for this `build.zig.zon` file\nin a documentation file inside the official repository of Zig[^zig-zon-schema].\n\n[^zig-zon]: \n[^zig-zon2]: \n[^zig-zon-schema]: \n\n### The file `root.zig` {#sec-root-file}\n\nLet's take a look into the `root.zig` file.\nYou might have noticed that every line of code with an expression ends with a semicolon (`;`).\nThis follows the syntax of a C-family programming language[^c-family].\n\n[^c-family]: \n\nAlso, notice the `@import()` call at the first line. We use this built-in function\nto import functionality from other Zig modules into our current module.\nThis `@import()` function works similarly to the `#include` pre-processor\nin C or C++, or, to the `import` statement in Python or Javascript code.\nIn this example, we are importing the `std` module,\nwhich gives you access to the Zig Standard Library.\n\nIn this `root.zig` file, we can also see how assignments (i.e., creating new objects)\nare made in Zig. You can create a new object in Zig by using the syntax\n`(const|var) name = value;`. In the example below, we are creating two constant\nobjects (`std` and `testing`). In @sec-assignments we talk more about objects in general.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst testing = std.testing;\n\nexport fn add(a: i32, b: i32) i32 {\n    return a + b;\n}\n```\n:::\n\n\nFunctions in Zig are declared using the `fn` keyword.\nIn this `root.zig` module, we are declaring a function called `add()`, which has two arguments named `a` and `b`.\nThe function returns an integer of the type `i32` as result.\n\n\nZig is a strongly-typed language. There are some specific situations where you can (if you want to) omit\nthe type of an object in your code, if this type can be inferred by the `zig` compiler (we talk more\nabout that in @sec-type-inference). But there are other situations where you do need to be explicit.\nFor example, you do have to explicitly specify the type of each function argument, and also,\nthe return type of every function that you create in Zig.\n\nWe specify the type of an object or a function argument in Zig by\nusing a colon character (`:`) followed by the type after the name of this object/function argument.\nWith the expressions `a: i32` and `b: i32`, we know that both `a` and `b` arguments have type `i32`,\nwhich is a signed 32 bit integer. In this part,\nthe syntax in Zig is identical to the syntax in Rust, which also specifies types by\nusing the colon character.\n\nLastly, we have the return type of the function at the end of the line, before we open\nthe curly braces to start writing the function's body. In the example above, this type is also\na signed 32 bit integer (`i32`) value.\n\nNotice that we also have an `export` keyword before the function declaration. This keyword\nis similar to the `extern` keyword in C. It exposes the function\nto make it available in the library API. Therefore, if you are writing\na library for other people to use, you have to expose the functions\nyou write in the public API of this library by using this `export` keyword.\nIf we removed the `export` keyword from the `add()` function declaration,\nthen, this function would be no longer exposed in the library object built\nby the `zig` compiler.\n\n\n### The `main.zig` file {#sec-main-file}\n\nNow that we have learned a lot about Zig's syntax from the `root.zig` file,\nlet's take a look at the `main.zig` file.\nA lot of the elements we saw in `root.zig` are also present in `main.zig`.\nBut there are some other elements that we haven't seen yet, so let's dive in.\n\nFirst, look at the return type of the `main()` function in this file.\nWe can see a small change. The return type of the function (`void`) is accompanied by an exclamation mark (`!`).\nThis exclamation mark tells us that this `main()` function might return an error.\n\nIt's worth noting that, a `main()` function in Zig is allowed to return nothing (`void`),\nor an unsigned 8-bit integer (`u8`) value[^u8-example], or an error. In other words, you can write your `main()` function in Zig\nto return essentially nothing (`void`), or, if you prefer, you can also write a more C-like `main()` function,\nwhich returns an integer value that usually serves as a \"status code\" for the process.\n\n[^u8-example]: You can see an example of a `main()` function that returns an `u8` value in the `return-integer.zig` file, \n\nIn this example, the return type annotation of `main()` indicates that this function can either\nreturn nothing (`void`), or return an error. This exclamation mark in the return type annotation\nis an interesting and powerful feature of Zig. In summary, if you write a function and something inside\nthe body of this function might return an error, then, you are forced to:\n\n- either add the exclamation mark to the return type of the function and make it clear that\nthis function might return an error.\n- explicitly handle this error inside the function.\n\nIn most programming languages, we normally handle (or deal with) an error through\na *try catch* pattern. Zig does have both `try` and `catch` keywords. But they work\na little differently than what you're probably used to in other languages.\n\nIf we look at the `main()` function below, you can see that we do have a `try` keyword\non the 5th line. But we do not have a `catch` keyword in this code.\nIn Zig, we use the `try` keyword to execute an expression that might return an error,\nwhich, in this example, is the `stdout.print()` expression.\n\nIn essence, the `try` keyword executes the expression `stdout.print()`. If this expression\nreturns a valid value, then, the `try` keyword does absolutely nothing. It only passes the value forward.\nIt's like if this `try` keyword was never there. However, if the expression does return an error, then,\nthe `try` keyword will unwrap the error value, then, it returns this error from the function\nand also prints the current stack trace to `stderr`.\n\nThis might sound weird to you if you come from a high-level language. Because in\nhigh-level languages, such as Python, if an error occurs somewhere, this error is automatically\nreturned and the execution of your program will automatically stop even if you don't want\nto stop the execution. You are obligated to face the error.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n\npub fn main() !void {\n    const stdout = std.io.getStdOut().writer();\n    try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n:::\n\n\nAnother thing that you might have noticed in this code example, is that\nthe `main()` function is marked with the `pub` keyword. It marks the `main()`\nfunction as a *public function* from this module. Every function in your Zig\nmodule is by default private to this Zig module and can only be called from within the module.\nUnless, you explicitly mark this function as a public function with the `pub` keyword.\n\nIf you think about it, this `pub` keyword in Zig does essentially the opposite of what the `static` keyword\ndo in C/C++. By making a function \"public\" you allow other Zig modules to access and call this function.\nA calling Zig module imports another module by using the `@import()` built-in function, which makes\nall public functions from the imported module visible to the calling Zig module.\n\n\n### Compiling your source code {#sec-compile-code}\n\nYou can compile your Zig modules into a binary executable by running the `build-exe` command\nfrom the `zig` compiler. You simply list all the Zig modules that you want to build after\nthe `build-exe` command, separated by spaces. In the example below, we are compiling the module `main.zig`.\n\n```bash\nzig build-exe src/main.zig\n```\n\nSince we are building an executable, the `zig` compiler will look for a `main()` function\ndeclared in any of the files that you list after the `build-exe` command. If\nthe compiler does not find a `main()` function declared somewhere, a\ncompilation error will be raised, warning about this mistake.\n\nThe `zig` compiler also offers a `build-lib` and `build-obj` commands, which work\nthe exact same way as the `build-exe` command. The only difference is that, they compile your\nZig modules into a portable C ABI library, or, into object files, respectively.\n\nIn the case of the `build-exe` command, a binary executable file is created by the `zig`\ncompiler in the root directory of your project.\nIf we take a look now at the contents of our current directory, with a simple `ls` command, we can\nsee the binary file called `main` that was created by the compiler.\n\n```bash\nls\n```\n\n```\nbuild.zig  build.zig.zon  main  src\n```\n\nIf I execute this binary executable, I get the \"Hello World\" message in the terminal\n, as we expected.\n\n```bash\n./main\n```\n\n```\nHello, world!\n```\n\n\n### Compile and execute at the same time {#sec-compile-run-code}\n\nIn the previous section, I presented the `zig build-exe` command, which\ncompiles Zig modules into an executable file. However, this means that,\nin order to execute the executable file, we have to run two different commands.\nFirst, the `zig build-exe` command, and then, we call the executable file\ncreated by the compiler.\n\nBut what if we wanted to perform these two steps,\nall at once, in a single command? We can do that by using the `zig run`\ncommand.\n\n```bash\nzig run src/main.zig\n```\n\n```\nHello, world!\n```\n\n\n### Important note for Windows users\n\nFirst of all, this is a Windows-specific thing, and, therefore, does not apply to other\noperating systems, such as Linux and macOS. In summary, if you have a piece of Zig code that\nincludes some global variables whose initialization rely on runtime resources, then,\nyou might have some troubles while trying to compile this Zig code on Windows.\n\nAn example of that is accessing the `stdout` (i.e., the *standard output* of your system), which is usually\ndone in Zig by using the expression `std.io.getStdOut()`. If you use this expression to instantiate\na global variable in a Zig module, then, the compilation of your Zig code will very likely fail on Windows,\nwith an \"unable to evaluate comptime expression\" error message.\n\nThis failure in the compilation process happens because all global variables in Zig are initialized\nat *compile-time*. However, on Windows, operations like accessing the `stdout` (or opening a file) depend on\nresources that are available only at *runtime* (you will learn more about compile-time versus runtime\nin @sec-compile-time).\n\nFor example, if you try to compile this code example on Windows, you will likely get the error message\nexposed below:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n// ERROR! Compile-time error that emerges from\n// this next line, on the `stdout` object\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n```\nt.zig:2107:28: error: unable to evaluate comptime expression\n    break :blk asm {\n               ^~~\n```\n\n\n\nTo avoid this problem on Windows, we need to force the `zig` compiler to instantiate this\n`stdout` object only at runtime, instead of instantiating it at compile-time. We can achieve\nthat by simply moving the expression to a function body.\n\nThis solves the problem because all expressions that are inside a function body in Zig\nare evaluated only at runtime, unless you use the `comptime` keyword explicitly to change this behaviour.\nYou will learn more about this `comptime` keyword in @sec-comptime.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    // SUCCESS: Stdout initialized at runtime.\n    const stdout = std.io.getStdOut().writer();\n    _ = try stdout.write(\"Hello\\n\");\n}\n```\n:::\n\n\n```\nHello\n```\n\nYou can read more details about this Windows-specific limitation in a couple of\nGitHub issues opened at the official Zig repository. More specifically, the issues\n17186 [^cissue1] and 19864 [^cissue2].\n\n[^cissue1]: \n[^cissue2]: \n\n\n### Compiling the entire project {#sec-compile-project}\n\nJust as I described in @sec-project-files, as our project grows in size and\ncomplexity, we usually prefer to organize the compilation and build process\nof the project into a build script, using some sort of \"build system\".\n\nIn other words, as our project grows in size and complexity,\nthe `build-exe`, `build-lib` and `build-obj` commands become\nharder to use directly. Because then, we start to list\nmultiple and multiple modules at the same time. We also\nstart to add built-in compilation flags to customize the\nbuild process for our needs, etc. It becomes a lot of work\nto write the necessary commands by hand.\n\nIn C/C++ projects, programmers normally opt to use CMake, Ninja, `Makefile` or `configure` scripts\nto organize this process. However, in Zig, we have a native build system in the language itself.\nSo, we can write build scripts in Zig to compile and build Zig projects. Then, all we\nneed to do, is to call the `zig build` command to build our project.\n\nSo, when you execute the `zig build` command, the `zig` compiler will search\nfor a Zig module named `build.zig` inside your current directory, which\nshould be your build script, containing the necessary code to compile and\nbuild your project. If the compiler does find this `build.zig` file in your directory,\nthen, the compiler will essentially execute a `zig run` command\nover this `build.zig` file, to compile and execute this build\nscript, which in turn, will compile and build your entire project.\n\n\n```bash\nzig build\n```\n\n\nAfter you execute this \"build project\" command, a `zig-out` directory\nis created in the root of your project directory, where you can find\nthe binary executables and libraries created from your Zig modules\naccordingly to the build commands that you specified at `build.zig`.\nWe will talk more about the build system in Zig later in this book.\n\nIn the example below, I'm executing the binary executable\nnamed `hello_world` that was generated by the compiler after the\n`zig build` command.\n\n```bash\n./zig-out/bin/hello_world\n```\n\n```\nHello, world!\n```\n\n\n\n## How to learn Zig?\n\nWhat are the best strategies to learn Zig?\nFirst of all, of course this book will help you a lot on your journey through Zig.\nBut you will also need some extra resources if you want to be really good at Zig.\n\nAs a first tip, you can join a community with Zig programmers to get some help\n, when you need it:\n\n- Reddit forum: ;\n- Ziggit community: ;\n- Discord, Slack, Telegram, and others: ;\n\nNow, one of the best ways to learn Zig is to simply read Zig code. Try\nto read Zig code often, and things will become more clear.\nA C/C++ programmer would also probably give you this same tip.\nBecause this strategy really works!\n\nNow, where can you find Zig code to read?\nI personally think that, the best way of reading Zig code is to read the source code of the\nZig Standard Library. The Zig Standard Library is available at the [`lib/std` folder](https://github.com/ziglang/zig/tree/master/lib/std)[^zig-lib-std] on\nthe official GitHub repository of Zig. Access this folder, and start exploring the Zig modules.\n\nAlso, a great alternative is to read code from other large Zig\ncodebases, such as:\n\n1. the [Javascript runtime Bun](https://github.com/oven-sh/bun)[^bunjs].\n1. the [game engine Mach](https://github.com/hexops/mach)[^mach].\n1. a [LLama 2 LLM model implementation in Zig](https://github.com/cgbur/llama2.zig/tree/main)[^ll2].\n1. the [financial transactions database `tigerbeetle`](https://github.com/tigerbeetle/tigerbeetle)[^tiger].\n1. the [command-line arguments parser `zig-clap`](https://github.com/Hejsil/zig-clap)[^clap].\n1. the [UI framework `capy`](https://github.com/capy-ui/capy)[^capy].\n1. the [Language Protocol implementation for Zig, `zls`](https://github.com/zigtools/zls)[^zls].\n1. the [event-loop library `libxev`](https://github.com/mitchellh/libxev)[^xev].\n\n[^xev]: \n[^zls]: \n[^capy]: \n[^clap]: \n[^tiger]: \n[^ll2]: \n[^mach]: \n[^bunjs]: .\n\nAll these assets are available on GitHub,\nand this is great, because we can use the GitHub search bar to our advantage,\nto find Zig code that fits our description.\nFor example, you can always include `lang:Zig` in the GitHub search bar when you\nare searching for a particular pattern. This will limit the search to only Zig modules.\n\n[^zig-lib-std]: \n\nAlso, a great alternative is to consult online resources and documentation.\nHere is a quick list of resources that I personally use from time to time to learn\nmore about the language each day:\n\n- Zig Language Reference: ;\n- Zig Standard Library Reference: ;\n- Zig Guide: ;\n- Karl Seguin Blog: ;\n- Zig News: ;\n- Read the code written by one of the Zig core team members: ;\n- Some livecoding sessions are transmitted in the Zig Showtime Youtube Channel: ;\n\n\nAnother great strategy to learn Zig, or honestly, to learn any language you want,\nis to practice it by solving exercises. For example, there is a famous repository\nin the Zig community called [Ziglings](https://ziglings.org)[^ziglings]\n, which contains more than 100 small exercises that you can solve. It's a repository of\ntiny programs written in Zig that are currently broken, and your responsibility is to\nfix these programs, and make them work again.\n\n[^ziglings]: .\n\nA famous tech YouTuber known as *The Primeagen* also posted some videos (on YouTube)\nwhere he solves these exercises from Ziglings. The first video is named\n[\"Trying Zig Part 1\"](https://www.youtube.com/watch?v=OPuztQfM3Fg&t=2524s&ab_channel=TheVimeagen)[^prime1].\n\n[^prime1]: .\n\nAnother great alternative, is to solve the [Advent of Code exercises](https://adventofcode.com/)[^advent-code].\nThere are people that already took the time to learn and solve the exercises, and they posted\ntheir solutions on GitHub as well, so, in case you need some resource to compare while solving\nthe exercises, you can look at these two repositories:\n\n- ;\n- ;\n\n[^advent-code]: \n\n\n\n\n\n\n## Creating new objects in Zig (i.e., identifiers) {#sec-assignments}\n\nLet's talk more about objects in Zig. Readers that have past experience\nwith other programming languages might know this concept through\na different name, such as: \"variable\" or \"identifier\". In this book, I choose\nto use the term \"object\" to refer to this concept.\n\nTo create a new object (or a new \"identifier\") in Zig, we use\nthe keywords `const` or `var`. These keywords specify if the object\nthat you are creating is mutable or not.\nIf you use `const`, then the object you are\ncreating is a constant (or immutable) object, which means that once you declare this object, you\ncan no longer change the value stored inside this object.\n\nOn the other side, if you use `var`, then, you are creating a variable (or mutable) object.\nYou can change the value of this object as many times you want. Using the\nkeyword `var` in Zig is similar to using the keywords `let mut` in Rust.\n\n### Constant objects vs variable objects\n\nIn the code example below, we are creating a new constant object called `age`.\nThis object stores a number representing the age of someone. However, this code example\ndoes not compile successfully. Because on the next line of code, we are trying to change the value\nof the object `age` to 25.\n\nThe `zig` compiler detects that we are trying to change\nthe value of an object/identifier that is constant, and because of that,\nthe compiler will raise a compilation error, warning us about the mistake.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 24;\n// The line below is not valid!\nage = 25;\n```\n:::\n\n\n```\nt.zig:10:5: error: cannot assign to constant\n    age = 25;\n      ~~^~~\n```\n\nSo, if you want to change the value of your object, you need to transform your immutable (or \"constant\")\nobject into a mutable (or \"variable\") object. You can do that by using the `var` keyword.\nThis keyword stands for \"variable\", and when you apply this keyword to some object, you are\ntelling the Zig compiler that the value associated with this object might change at some point.\n\nThus, if we come back to the previous example, and change the declaration of the\n`age` object to use the `var` keyword, then, the program gets compiled successfully.\nBecause now, the `zig` compiler detects that we are changing the value of an\nobject that allows this behaviour, because it's a \"variable object\".\n\nHowever, if you take a look at the example below, you will notice that we have not only declared the\n`age` object with the `var` keyword, but we also have explicitly annotated the data type\nof the `age` object with the `u8` type this time. The basic idea is, when we use a variable/mutable object,\nthe Zig compiler ask for us to be more explicit with what we want, to be more clear\nabout what our code does. This translates into being more explicit about the data types that we want\nto use in our objects.\n\nTherefore, if you transform your object into a variable/mutable object, just remember to always\nannotate the type of the object explicitly in your code. Otherwise, the Zig compiler might raise\na compilation error, asking you to transform your object back into a `const` object, or,\nto give your object an \"explicit type\".\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = 24;\nage = 25;\n```\n:::\n\n\n\n### Declaring without an initial value\n\nBy default, when you declare a new object in Zig, you must give it\nan initial value. In other words, this means\nthat we have to declare, and, at the same time, initialize every object we\ncreate in our source code.\n\nOn the other hand, you can, in fact, declare a new object in your source code,\nand not give it an explicit value. But we need to use a special keyword for that,\nwhich is the `undefined` keyword.\n\nIt's important to emphasize that, you should avoid using `undefined` as much as possible.\nBecause when you use this keyword, you leave your object uninitialized, and, as a consequence,\nif for some reason, your code uses this object while it's uninitialized, then, you will definitely\nhave undefined behaviour and major bugs in your program.\n\nIn the example below, I'm declaring the `age` object again. But this time,\nI do not give it an initial value. The variable is only initialized at\nthe second line of code, where I store the number 25 in this object.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar age: u8 = undefined;\nage = 25;\n```\n:::\n\n\nHaving these points in mind, just remember that you should avoid as much as possible to use `undefined` in your code.\nAlways declare and initialize your objects. Because this gives you much more safety in your program.\nBut in case you really need to declare an object without initializing it... the\n`undefined` keyword is the way to do it in Zig.\n\n\n### There is no such thing as unused objects\n\nEvery object (being constant or variable) that you declare in Zig **must be used in some way**. You can give this object\nto a function call, as a function argument, or, you can use it in another expression\nto calculate the value of another object, or, you can call a method that belongs to this\nparticular object.\n\nIt doesn't matter in which way you use it. As long as you use it.\nIf you try to break this rule, i.e., if your try to declare a object, but not use it,\nthe `zig` compiler will not compile your Zig source code, and it will issue a error\nmessage warning that you have unused objects in your code.\n\nLet's demonstrate this with an example. In the source code below, we declare a constant object\ncalled `age`. If you try to compile a simple Zig program with this line of code below,\nthe compiler will return an error as demonstrated below:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst age = 15;\n```\n:::\n\n\n```\nt.zig:4:11: error: unused local constant\n    const age = 15;\n          ^~~\n```\n\nEverytime you declare a new object in Zig, you have two choices:\n\n1. you either use the value of this object;\n1. or you explicitly discard the value of the object;\n\nTo explicitly discard the value of any object (constant or variable), all you need to do is to assign\nthis object to a special character in Zig, which is the underscore (`_`).\nWhen you assign an object to a underscore, like in the example below, the `zig` compiler will automatically\ndiscard the value of this particular object.\n\nYou can see in the example below that, this time, the compiler did not\ncomplain about any \"unused constant\", and successfully compiled our source code.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It compiles!\nconst age = 15;\n_ = age;\n```\n:::\n\n\nNow, remember, everytime you assign a particular object to the underscore, this object\nis essentially destroyed. It's discarded by the compiler. This means that you can no longer\nuse this object further in your code. It doesn't exist anymore.\n\nSo if you try to use the constant `age` in the example below, after we discarded it, you\nwill get a loud error message from the compiler (talking about a \"pointless discard\")\nwarning you about this mistake.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// It does not compile.\nconst age = 15;\n_ = age;\n// Using a discarded value!\nstd.debug.print(\"{d}\\n\", .{age + 2});\n```\n:::\n\n\n```\nt.zig:7:5: error: pointless discard\n    of local constant\n```\n\n\nThis same rule applies to variable objects. Every variable object must also be used in\nsome way. And if you assign a variable object to the underscore,\nthis object also gets discarded, and you can no longer use this object.\n\n\n\n### You must mutate every variable objects\n\nEvery variable object that you create in your source code must be mutated at some point.\nIn other words, if you declare an object as a variable\nobject, with the keyword `var`, and you do not change the value of this object\nat some point in the future, the `zig` compiler will detect this,\nand it will raise an error warning you about this mistake.\n\nThe concept behind this is that every object you create in Zig should be preferably a\nconstant object, unless you really need an object whose value will\nchange during the execution of your program.\n\nSo, if I try to declare a variable object such as `where_i_live` below,\nand I do not change the value of this object in some way,\nthe `zig` compiler raises an error message with the phrase \"variable is never mutated\".\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar where_i_live = \"Belo Horizonte\";\n_ = where_i_live;\n```\n:::\n\n\n```\nt.zig:7:5: error: local variable is never mutated\nt.zig:7:5: note: consider using 'const'\n```\n\n## Primitive Data Types {#sec-primitive-data-types}\n\nZig has many different primitive data types available for you to use.\nYou can see the full list of available data types at the official\n[Language Reference page](https://ziglang.org/documentation/master/#Primitive-Types)[^lang-data-types].\n\n[^lang-data-types]: .\n\nBut here is a quick list:\n\n- Unsigned integers: `u8`, 8-bit integer; `u16`, 16-bit integer; `u32`, 32-bit integer; `u64`, 64-bit integer; `u128`, 128-bit integer.\n- Signed integers: `i8`, 8-bit integer; `i16`, 16-bit integer; `i32`, 32-bit integer; `i64`, 64-bit integer; `i128`, 128-bit integer.\n- Float number: `f16`, 16-bit floating point; `f32`, 32-bit floating point; `f64`, 64-bit floating point; `f128`, 128-bit floating point;\n- Boolean: `bool`, represents true or false values.\n- C ABI compatible types: `c_long`, `c_char`, `c_short`, `c_ushort`, `c_int`, `c_uint`, and many others.\n- Pointer sized integers: `isize` and `usize`.\n\n\n\n\n\n\n\n## Arrays {#sec-arrays}\n\nYou create arrays in Zig by using a syntax that resembles the C syntax.\nFirst, you specify the size of the array (i.e., the number of elements that will be stored in the array)\nyou want to create inside a pair of brackets.\n\nThen, you specify the data type of the elements that will be stored inside this array.\nAll elements present in an array in Zig must have the same data type. For example, you cannot mix elements\nof type `f32` with elements of type `i32` in the same array.\n\nAfter that, you simply list the values that you want to store in this array inside\na pair of curly braces.\nIn the example below, I am creating two constant objects that contain different arrays.\nThe first object contains an array of 4 integer values, while the second object,\nan array of 3 floating point values.\n\nNow, you should notice that in the object `ls`, I am\nnot explicitly specifying the size of the array inside of the brackets. Instead\nof using a literal value (like the value 4 that I used in the `ns` object), I am\nusing the special character underscore (`_`). This syntax tells the `zig` compiler\nto fill this field with the number of elements listed inside of the curly braces.\nSo, this syntax `[_]` is for lazy (or smart) programmers who leave the job of\ncounting how many elements there are in the curly braces for the compiler.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst ls = [_]f64{432.1, 87.2, 900.05};\n_ = ns; _ = ls;\n```\n:::\n\n\nIt's worth noting that these are static arrays, meaning that\nthey cannot grow in size.\nOnce you declare your array, you cannot change the size of it.\nThis is very common in low level languages.\nBecause low level languages normally wants to give you (the programmer) full control over memory,\nand the way in which arrays are expanded is tightly related to\nmemory management.\n\n\n### Selecting elements of the array {#sec-select-array-elem}\n\nOne very common activity is to select specific portions of an array\nyou have in your source code.\nIn Zig, you can select a specific element from your\narray, by simply providing the index of this particular\nelement inside brackets after the object name.\nIn the example below, I am selecting the third element from the\n`ns` array. Notice that Zig is a \"zero-index\" based language,\nlike C, C++, Rust, Python, and many other languages.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\ntry stdout.print(\"{d}\\n\", .{ ns[2] });\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n12\n```\n\n\n:::\n:::\n\n\nIn contrast, you can also select specific slices (or sections) of your array, by using a\nrange selector. Some programmers also call these selectors of \"slice selectors\",\nand they also exist in Rust, and have the exact same syntax as in Zig.\nAnyway, a range selector is a special expression in Zig that defines\na range of indexes, and it has the syntax `start..end`.\n\nIn the example below, at the second line of code,\nthe `sl` object stores a slice (or a portion) of the\n`ns` array. More precisely, the elements at index 1 and 2\nin the `ns` array.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\n_ = sl;\n```\n:::\n\n\nWhen you use the `start..end` syntax,\nthe \"end tail\" of the range selector is non-inclusive,\nmeaning that, the index at the end is not included in the range that is\nselected from the array.\nTherefore, the syntax `start..end` actually means `start..end - 1` in practice.\n\nYou can for example, create a slice that goes from the first to the\nlast elements of the array, by using `ar[0..ar.len]` syntax\nIn other words, it's a slice that\naccesses all elements in the array.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [4]u8{48, 24, 12, 6};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\nYou can also use the syntax `start..` in your range selector.\nWhich tells the `zig` compiler to select the portion of the array\nthat begins at the `start` index until the last element of the array.\nIn the example below, we are selecting the range from index 1\nuntil the end of the array.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..];\n_ = sl;\n```\n:::\n\n\n\n### More on slices\n\nAs we discussed before, in Zig, you can select specific portions of an existing\narray. This is called *slicing* in Zig [@zigguide], because when you select a portion\nof an array, you are creating a slice object from that array.\n\nA slice object is essentially a pointer object accompanied by a length number.\nThe pointer object points to the first element in the slice, and the\nlength number tells the `zig` compiler how many elements there are in this slice.\n\n> Slices can be thought of as a pair of `[*]T` (the pointer to the data) and a `usize` (the element count) [@zigguide].\n\nThrough the pointer contained inside the slice you can access the elements (or values)\nthat are inside this range (or portion) that you selected from the original array.\nBut the length number (which you can access through the `len` property of your slice object)\nis the really big improvement (over C arrays for example) that Zig brings to the table here.\n\nBecause with this length number\nthe `zig` compiler can easily check if you are trying to access an index that is out of the bounds of this particular slice,\nor, if you are causing any buffer overflow problems. In the example below,\nwe access the `len` property of the slice `sl`, which tells us that this slice\nhas 2 elements in it.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [4]u8{48, 24, 12, 6};\nconst sl = ns[1..3];\ntry stdout.print(\"{d}\\n\", .{sl.len});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n2\n```\n\n\n:::\n:::\n\n\n\n### Array operators\n\nThere are two array operators available in Zig that are very useful.\nThe array concatenation operator (`++`), and the array multiplication operator (`**`). As the name suggests,\nthese are array operators.\n\nOne important detail about these two operators is that they work\nonly when both operands have a size (or \"length\") that is compile-time known.\nWe are going to talk more about\nthe differences between \"compile-time known\" and \"runtime known\" in @sec-compile-time.\nBut for now, keep this information in mind, that you cannot use these operators in every situation.\n\nIn summary, the `++` operator creates a new array that is the concatenation,\nof both arrays provided as operands. So, the expression `a ++ b` produces\na new array which contains all the elements from arrays `a` and `b`.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst b = [_]u8{4,5};\nconst c = a ++ b;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 4, 5 }\n```\n\n\n:::\n:::\n\n\nThis `++` operator is particularly useful to concatenate strings together.\nStrings in Zig are described in depth in @sec-zig-strings. In summary, a string object in Zig\nis essentially an arrays of bytes. So, you can use this array concatenation operator\nto effectively concatenate strings together.\n\nIn contrast, the `**` operator is used to replicate an array multiple\ntimes. In other words, the expression `a ** 3` creates a new array\nwhich contains the elements of the array `a` repeated 3 times.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a = [_]u8{1,2,3};\nconst c = a ** 2;\ntry stdout.print(\"{any}\\n\", .{c});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 1, 2, 3, 1, 2, 3 }\n```\n\n\n:::\n:::\n\n\n\n### Runtime versus compile-time known length in slices\n\nWe are going to talk a lot about the differences between compile-time known\nand runtime known across this book, especially in @sec-compile-time.\nBut the basic idea is that a thing is compile-time known, when we know\neverything (the value, the attributes and the characteristics) about this thing at compile-time.\nIn contrast, a runtime known thing is when the exact value of a thing is calculated only at runtime.\nTherefore, we don't know the value of this thing at compile-time, only at runtime.\n\nWe have learned in @sec-select-array-elem that slices are created by using a *range selector*,\nwhich represents a range of indexes. When this \"range of indexes\" (i.e., both the start and the end of this range)\nis known at compile-time, the slice object that gets created is actually, under the hood, just\na single-item pointer to an array.\n\nYou don't need to precisely understand what that means now. We are going to talk a lot about pointers\nin @sec-pointer. For now, just understand that, when the range of indexes is known at compile-time,\nthe slice that gets created is just a pointer to an array, accompanied by a length value that\ntells the size of the slice.\n\nIf you have a slice object like this, i.e., a slice that has a compile-time known range,\nyou can use common pointer operations over this slice object. For example, you can\ndereference the pointer of this slice, by using the `.*` method, like you would\ndo on a normal pointer object.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst arr1 = [10]u64 {\n    1, 2, 3, 4, 5,\n    6, 7, 8, 9, 10\n};\n// This slice has a compile-time known range.\n// Because we know both the start and end of the range.\nconst slice = arr1[1..4];\n_ = slice;\n```\n:::\n\n\n\nOn the other hand, if the range of indexes is not known at compile time, then, the slice object\nthat gets created is not a pointer anymore, and, thus, it does not support pointer operations.\nFor example, maybe the start index is known at compile time, but the end index is not. In such\ncase, the range of the slice becomes runtime known only.\n\nIn the example below, we are reading a file, and then, we try to create a slice object\nthat covers the entire buffer that contains the contents of this file. This is obviously\nan example of a runtime known range, because the end index of the range\nis not known at compile time.\n\nIn other words, the end index of the range is the size of\nthe array `file_contents`. However, the size of `file_contents` is not known at compile time.\nBecause we don't know how many bytes are stored inside this `shop-list.txt` file.\nAnd because this is a file, someone might edit this file tomorrow and add more lines\nor remove lines from it. Therefore, the size of this file might vary drastically from one execution to another.\n\nNow, if the file size can vary from one run to another, then, we can conclude that the value of the expression\n`file_contents.len` exposed in the example below can also vary from one run to another. As consequence,\nthe value of the expression `file_contents.len` is runtime-known only, and, as a consequence of that,\nthe range `0..file_contents.len` is also runtime-known only.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\n\nfn read_file(allocator: std.mem.Allocator, path: []const u8) ![]u8 {\n    const file = try std.fs.cwd().openFile(path, .{});\n    defer file.close();\n    return try file.reader().readAllAlloc(\n        allocator, std.math.maxInt(usize)\n    );\n}\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    const allocator = gpa.allocator();\n    const path = \"../ZigExamples/file-io/shop-list.txt\";\n    const file_contents = try read_file(allocator, path);\n    const slice = file_contents[0..file_contents.len];\n    _ = slice;\n}\n```\n:::\n\n\n\n## Blocks and scopes {#sec-blocks}\n\nBlocks are created in Zig by a pair of curly braces. A block is just a group of\nexpressions (or statements) contained inside of a pair of curly braces. All of these expressions that\nare contained inside of this pair of curly braces belongs to the same scope.\n\nIn other words, a block just delimits a scope in your code.\nThe objects that you define inside the same block belongs to the same\nscope, and, therefore, are accessible from within this scope.\nAt the same time, these objects are not accessible outside of this scope.\nSo, you could also say that blocks are used to limit the scope of the objects that you create in\nyour source code. In less technical terms, blocks are used to specify where in your source code\nyou can access whatever object you have in your source code.\n\nSo, a block is just a group of expressions contained inside a pair of curly braces.\nAnd every block have its own scope separated from the others.\nThe body of a function is a classic example of a block. If statements, for and while loops\n(and any other structure in the language that uses the pair of curly braces)\nare also examples of blocks.\n\nThis means that, every if statement, or for loop,\netc., that you create in your source code has its own separate scope.\nThat is why you can't access the objects that you defined inside\nof your for loop (or if statement) in an outer scope, i.e., a scope outside of the for loop.\nBecause you are trying to access an object that belongs to a scope that is different\nthan your current scope.\n\n\nYou can create blocks within blocks, with multiple levels of nesting.\nYou can also (if you want to) give a label to a particular block, with the colon character (`:`).\nJust write `label:` before you open the pair of curly braces that delimits your block. When you label a block\nin Zig, you can use the `break` keyword to return a value from this block, like as if it\nwas a function's body. You just write the `break` keyword, followed by the block label in the format `:label`,\nand the expression that defines the value that you want to return.\n\nLike in the example below, where we are returning the value from the `y` object\nfrom the block `add_one`, and saving the result inside the `x` object.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar y: i32 = 123;\nconst x = add_one: {\n    y += 1;\n    break :add_one y;\n};\nif (x == 124 and y == 124) {\n    try stdout.print(\"Hey!\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHey!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n## How strings work in Zig? {#sec-zig-strings}\n\nThe first project that we are going to build and discuss in this book is a base64 encoder/decoder (@sec-base64).\nBut in order for us to build such a thing, we need to get a better understanding on how strings work in Zig.\nSo let's discuss this specific aspect of Zig.\n\nStrings in Zig work very similarly to strings in C, but they come with some extra caveats which adds more safety\nand efficiency to them. You could also say that Zig simply uses a more modern and safe approach to manage\nand use strings.\n\nA string in Zig is essentially an array of arbitrary bytes, or, more specifically, an array of `u8` values.\nThis very similar to a string in C, which is also interpreted as an array of arbitrary bytes, or, in the case\nof C, an array of `char` (which usually represents an unsigned 8-bit integer value in most systems) values.\n\nNow, because a string in Zig is an array, you automatically\nget the length of the string (i.e. the length of the array) embedded in the value itself. This makes\nall the difference! Because now, the Zig compiler can use the length value that is embedded in the string to\ncheck for \"buffer overflow\" or \"wrong memory access\" problems in your code.\n\n\nTo achieve this same kind of safety in C, you have to do a lot of work that kind of seems pointless.\nSo getting this kind of safety is not automatic and much harder to do in C. For example, if you want\nto track the length of your string throughout your program in C, then, you first need to loop through\nthe array of bytes that represents this string, and find the null element (`'\\0'`) position to discover\nwhere exactly the array ends, or, in other words, to find how much elements the array of bytes contain.\n\nTo do that, you would need to do something like this in C. In this example, the C string stored in\nthe object `array` is 25 bytes long:\n\n\n::: {.cell}\n\n```{.c .cell-code}\n#include \nint main() {\n    char* array = \"An example of string in C\";\n    int index = 0;\n    while (1) {\n        if (array[index] == '\\0') {\n            break;\n        }\n        index++;\n    }\n    printf(\"Number of elements in the array: %d\\n\", index);\n}\n```\n:::\n\n\n```\nNumber of elements in the array: 25\n```\n\n\nYou don't have this kind of work in Zig. Because the length of the string is always\npresent and accessible in the string value itself. You can easily access the length of the string\nthrough the `len` attribute. As an example, the `string_object` object below is 43 bytes long:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"This is an example of string literal in Zig\";\n    try stdout.print(\"{d}\\n\", .{string_object.len});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n43\n```\n\n\n:::\n:::\n\n\n\nAnother point is that Zig always assumes that the sequence of bytes in your string is UTF-8 encoded. This might not be true for every\nsequence of bytes you're working with, but is not really Zig's job to fix the encoding of your strings\n(you can use [`iconv`](https://www.gnu.org/software/libiconv/)[^libiconv] for that).\nToday, most of the text in our modern world, especially on the web, should be UTF-8 encoded.\nSo if your string literal is not UTF-8 encoded, then, you will likely have problems in Zig.\n\n[^libiconv]: \n\nLet's take for example the word \"Hello\". In UTF-8, this sequence of characters (H, e, l, l, o)\nis represented by the sequence of decimal numbers 72, 101, 108, 108, 111. In hexadecimal, this\nsequence is `0x48`, `0x65`, `0x6C`, `0x6C`, `0x6F`. So if I take this sequence of hexadecimal values,\nand ask Zig to print this sequence of bytes as a sequence of characters (i.e., a string), then,\nthe text \"Hello\" will be printed into the terminal:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};\n    try stdout.print(\"{s}\\n\", .{bytes});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello\n```\n\n\n:::\n:::\n\n\n\n\n### Using a slice versus a sentinel-terminated array\n\nIn memory, all string values in Zig are always stored in the same way.\nThey are simply stored as sequences/arrays of arbitrary bytes. But you can use and access\nthis sequence of bytes in two different ways. You can access this sequence of bytes as:\n\n- a sentinel-terminated array of `u8` values.\n- or as a slice of `u8` values.\n\n\n#### Sentinel-terminated arrays\n\nSentinel-terminated arrays in Zig are described in the Language Reference of Zig[^sentinel].\nIn summary a sentinel-terminated array is just a normal array, but, the difference is that they\ncontain a \"sentinel value\" at the last index/element of the array. With a sentinel-terminated array\nyou embed both the length of the array, and also, the sentinel value in the type itself of your object.\n\n[^sentinel]: .\n\nFor example, if you write a string literal value in your code, and ask Zig to print the data type of this value,\nyou usually get a data type in the format `*const [n:0]u8`. The `n` in the data type indicates the size of\nthe string (that is the length of the array). The zero after the `n:` part of the data type is the sentinel\nvalue itself.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string literal value:\n_ = \"A literal value\";\ntry stdout.print(\"{any}\\n\", .{@TypeOf(\"A literal value\")});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n*const [15:0]u8\n```\n\n\n:::\n:::\n\n\n\nSo, with this data type `*const [n:0]u8` you are essentially saying that you have an array of `u8` values\nof length `n`, where, the element at the index corresponding to the length `n` in the array is the\nnumber zero. If you really think about this description, you will notice that this is just a fancy way to\ndescribe a string in C, which is a null-terminated array of bytes. The `NULL` value in C is the number\nzero. So, an array that ends in a null/zero value in C is essentially a sentinel-terminated array in Zig,\nwhere the sentinel value of the array is the number zero.\n\nTherefore, a string literal value in Zig is just a pointer to a null-terminated array of bytes (i.e., similar to a C string).\nBut in Zig, a string literal value also embeds the length of the string, and also, the fact that they are \"NULL terminated\",\ninto the data type of the value itself.\n\n\n\n#### Slice\n\nYou can also access and use the arbitrary sequence of bytes that represent your string as a slice of `u8` values.\nThe majority of functions from the Zig standard library usually receive strings as inputs as slices of\n`u8` values (slices were presented in @sec-arrays).\n\nThus, you will see a lot of string values with a data type of `[]u8` or `[]const u8`, depending if the object\nwhere this string is stored is marked as constant with `const`, or as variable with `var`. Now, because\nthe string in this case is being interpreted as a slice, this slice is not necessarilly null-terminated,\nbecause now, the sentinel value is not mandatory. You can include the null/zero value in the slice if you\nwant to, but there is no need to do it.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// This is a string value being\n// interpreted as a slice.\nconst str: []const u8 = \"A string value\";\ntry stdout.print(\"{any}\\n\", .{@TypeOf(str)});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n[]const u8\n```\n\n\n:::\n:::\n\n\n\n\n### Iterating through the string\n\nIf you want to see the actual bytes that represents a string in Zig, you can use\na `for` loop to iterate through each byte in the string, and ask Zig to print each byte as an hexadecimal\nvalue to the terminal. You do that by using a `print()` statement with the `X` formatting specifier,\nlike you would normally do with the [`printf()` function](https://cplusplus.com/reference/cstdio/printf/)[^printfs] in C.\n\n[^printfs]: \n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"This is an example\";\n    try stdout.print(\"Bytes that represents the string object: \", .{});\n    for (string_object) |byte| {\n        try stdout.print(\"{X} \", .{byte});\n    }\n    try stdout.print(\"\\n\", .{});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: 54 68 69 \n   73 20 69 73 20 61 6E 20 65 78 61 6D 70 6C 65 \n```\n\n\n:::\n:::\n\n\n\n\n### A better look at the object type\n\nNow, we can inspect better the type of objects that Zig create. To check the type of any object in Zig, you can use the\n`@TypeOf()` function. If we look at the type of the `simple_array` object below, you will find that this object\nis an array of 4 elements. Each element is a signed integer of 32 bits which corresponds to the data type `i32` in Zig.\nThat is what an object of type `[4]i32` is.\n\nBut if we look closely at the type of the string literal value exposed below, you will find that this object is a\nconstant pointer (hence the `*const` annotation) to an array of 16 elements (or 16 bytes). Each element is a\nsingle byte (more precisely, an unsigned 8 bit integer - `u8`), that is why we have the `[16:0]u8` portion of the type below,\nand also, you can see that this is a null-terminated array, because of the zero value after the `:` character in the data type.\nIn other words, the string literal value exposed below is 16 bytes long.\n\nNow, if we create an pointer to the `simple_array` object, then, we get a constant pointer to an array of 4 elements (`*const [4]i32`),\nwhich is very similar to the type of the string literal value. This demonstrates that a string literal value\nin Zig is already a pointer to a null-terminated array of bytes.\n\nFurthermore, if we take a look at the type of the `string_obj` object, you will see that it's a\nslice object (hence the `[]` portion of the type) to a sequence of constant `u8` values (hence\nthe `const u8` portion of the type).\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    const simple_array = [_]i32{1, 2, 3, 4};\n    const string_obj: []const u8 = \"A string object\";\n    std.debug.print(\n        \"Type 1: {}\\n\", .{@TypeOf(simple_array)}\n    );\n    std.debug.print(\n        \"Type 2: {}\\n\", .{@TypeOf(\"A string literal\")}\n    );\n    std.debug.print(\n        \"Type 3: {}\\n\", .{@TypeOf(&simple_array)}\n    );\n    std.debug.print(\n        \"Type 4: {}\\n\", .{@TypeOf(string_obj)}\n    );\n}\n```\n:::\n\n\n```\nType 1: [4]i32\nType 2: *const [16:0]u8\nType 3: *const [4]i32\nType 4: []const u8\n```\n\n\n\n### Byte vs unicode points\n\nIt's important to point out that each byte in the array is not necessarily a single character.\nThis fact arises from the difference between a single byte and a single unicode point.\n\nThe encoding UTF-8 works by assigning a number (which is called a unicode point) to each character in\nthe string. For example, the character \"H\" is stored in UTF-8 as the decimal number 72. This means that\nthe number 72 is the unicode point for the character \"H\". Each possible character that can appear in a\nUTF-8 encoded string have its own unicode point.\n\nFor example, the Latin Capital Letter A With Stroke (Ⱥ) is represented by the number (or the unicode point)\n570. However, this decimal number (570) is higher than the maximum number stored inside a single byte, which\nis 255. In other words, the maximum decimal number that can be represented with a single byte is 255. That is why,\nthe unicode point 570 is actually stored inside the computer’s memory as the bytes `C8 BA`.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n    const string_object = \"Ⱥ\";\n    _ = try stdout.write(\n        \"Bytes that represents the string object: \"\n    );\n    for (string_object) |char| {\n        try stdout.print(\"{X} \", .{char});\n    }\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nBytes that represents the string object: C8 BA \n```\n\n\n:::\n:::\n\n\n\nThis means that to store the character Ⱥ in an UTF-8 encoded string, we need to use two bytes together\nto represent the number 570. That is why the relationship between bytes and unicode points is not always\n1 to 1. Each unicode point is a single character in the string, but not always a single byte corresponds\nto a single unicode point.\n\nAll of this means that if you loop through the elements of a string in Zig, you will be looping through the\nbytes that represents that string, and not through the characters of that string. In the Ⱥ example above,\nthe for loop needed two iterations (instead of a single iteration) to print the two bytes that represents this Ⱥ letter.\n\nNow, all english letters (or ASCII letters if you prefer) can be represented by a single byte in UTF-8. As a\nconsequence, if your UTF-8 string contains only english letters (or ASCII letters), then, you are lucky. Because\nthe number of bytes will be equal to the number of characters in that string. In other words, in this specific\nsituation, the relationship between bytes and unicode points is 1 to 1.\n\nBut on the other side, if your string contains other types of letters… for example, you might be working with\ntext data that contains, chinese, japanese or latin letters, then, the number of bytes necessary to represent\nyour UTF-8 string will likely be much higher than the number of characters in that string.\n\nIf you need to iterate through the characters of a string, instead of its bytes, then, you can use the\n`std.unicode.Utf8View` struct to create an iterator that iterates through the unicode points of your string.\n\nIn the example below, we loop through the japanese characters “アメリカ”. Each of the four characters in\nthis string is represented by three bytes. But the for loop iterates four times, one iteration for each\ncharacter/unicode point in this string:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    var utf8 = try std.unicode.Utf8View.init(\"アメリカ\");\n    var iterator = utf8.iterator();\n    while (iterator.nextCodepointSlice()) |codepoint| {\n        try stdout.print(\n            \"got codepoint {}\\n\",\n            .{std.fmt.fmtSliceHexUpper(codepoint)},\n        );\n    }\n}\n\n```\n:::\n\n\n```\ngot codepoint E382A2\ngot codepoint E383A1\ngot codepoint E383AA\ngot codepoint E382AB\n```\n\n\n### Some useful functions for strings {#sec-strings-useful-funs}\n\nIn this section, I just want to quickly describe some functions from the Zig Standard Library\nthat are very useful to use when working with strings. Most notably:\n\n- `std.mem.eql()`: to compare if two strings are equal.\n- `std.mem.splitScalar()`: to split a string into an array of substrings given a delimiter value.\n- `std.mem.splitSequence()`: to split a string into an array of substrings given a substring delimiter.\n- `std.mem.startsWith()`: to check if string starts with substring.\n- `std.mem.endsWith()`: to check if string ends with substring.\n- `std.mem.trim()`: to remove specific values from both start and end of the string.\n- `std.mem.concat()`: to concatenate strings together.\n- `std.mem.count()`: to count the occurrences of substring in the string.\n- `std.mem.replace()`: to replace the occurrences of substring in the string.\n\nNotice that all of these functions come from the `mem` module of\nthe Zig Standard Library. This module contains multiple functions and methods\nthat are useful to work with memory and sequences of bytes in general.\n\nThe `eql()` function is used to check if two arrays of data are equal or not.\nSince strings are just arbitrary arrays of bytes, we can use this function to compare two strings together.\nThis function returns a boolean value indicating if the two strings are equal\nor not. The first argument of this function is the data type of the elements of the arrays\nthat are being compared.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n    \"{any}\\n\", .{std.mem.eql(u8, name, \"Pedro\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\nThe `splitScalar()` and `splitSequence()` functions are useful to split\na string into multiple fragments, like the `split()` method from Python strings. The difference between these two\nmethods is that the `splitScalar()` uses a single character as the separator to\nsplit the string, while `splitSequence()` uses a sequence of characters (a.k.a. a substring)\nas the separator. There is a practical example of these functions later in the book.\n\nThe `startsWith()` and `endsWith()` functions are pretty straightforward. They\nreturn a boolean value indicating if the string (or, more precisely, if the array of data)\nbegins (`startsWith`) or ends (`endsWith`) with the sequence provided.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name: []const u8 = \"Pedro\";\ntry stdout.print(\n    \"{any}\\n\", .{std.mem.startsWith(u8, name, \"Pe\")}\n);\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ntrue\n```\n\n\n:::\n:::\n\n\nThe `concat()` function, as the name suggests, concatenate two or more strings together.\nBecause the process of concatenating the strings involves allocating enough space to\naccomodate all the strings together, this `concat()` function receives an allocator\nobject as input.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nconst str2 = \" you!\";\nconst str3 = try std.mem.concat(\n    allocator, u8, &[_][]const u8{ str1, str2 }\n);\ntry stdout.print(\"{s}\\n\", .{str3});\n```\n:::\n\n\n\nAs you can imagine, the `replace()` function is used to replace substrings in a string by another substring.\nThis function works very similarly to the `replace()` method from Python strings. Therefore, you\nprovide a substring to search, and every time that the `replace()` function finds\nthis substring within the input string, it replaces this substring with the \"replacement substring\"\nthat you provided as input.\n\nIn the example below, we are taking the input string \"Hello\", and replacing all occurrences\nof the substring \"el\" inside this input string with \"34\", and saving the results inside the\n`buffer` object. As result, the `replace()` function returns an `usize` value that\nindicates how many replacements were performed.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst str1 = \"Hello\";\nvar buffer: [5]u8 = undefined;\nconst nrep = std.mem.replace(\n    u8, str1, \"el\", \"34\", buffer[0..]\n);\ntry stdout.print(\"New string: {s}\\n\", .{buffer});\ntry stdout.print(\"N of replacements: {d}\\n\", .{nrep});\n```\n:::\n\n\n```\nNew string: H34lo\nN of replacements: 1\n```\n\n\n\n\n\n\n## Safety in Zig\n\nA general trend in modern low-level programming languages is safety. As our modern world\nbecomes more interconnected with technology and computers,\nthe data produced by all of this technology becomes one of the most important\n(and also, one of the most dangerous) assets that we have.\n\nThis is probably the main reason why modern low-level programming languages\nhave been giving great attention to safety, especially memory safety, because\nmemory corruption is still the main target for hackers to exploit.\nThe reality is that we don't have an easy solution for this problem.\nFor now, we only have techniques and strategies that mitigates these\nproblems.\n\nAs Richard Feldman explains on his [most recent GOTO conference talk](https://www.youtube.com/watch?v=jIZpKpLCOiU&ab_channel=GOTOConferences)[^gotop]\n, we haven't figured it out yet a way to achieve **true safety in technology**.\nIn other words, we haven't found a way to build software that won't be exploited\nwith 100% certainty. We can greatly reduce the risks of our software being\nexploited, by ensuring memory safety for example. But this is not enough\nto achieve \"true safety\" territory.\n\nBecause even if you write your program in a \"safe language\", hackers can still\nexploit failures in the operating system where your program is running (e.g. maybe the\nsystem where your code is running has a \"backdoor exploit\" that can still\naffect your code in unexpected ways), or also, they can exploit the features\nfrom the architecture of your computer. A recently found exploit\nthat involves memory invalidation through a feature of \"memory tags\"\npresent in ARM chips is an example of that [@exploit1].\n\n[^gotop]: \n\nThe question is: what have Zig and other languages been doing to mitigate this problem?\nIf we take Rust as an example, Rust is, for the most part[^rust-safe], a memory safe\nlanguage by enforcing specific rules to the developer. In other words, the key feature\nof Rust, the *borrow checker*, forces you to follow a specific logic when you are writing\nyour Rust code, and the Rust compiler will always complain everytime you try to go out of this\npattern.\n\n[^rust-safe]: Actually, a lot of existing Rust code is still memory unsafe, because they communicate with external libraries through FFI (*foreign function interface*), which disables the borrow-checker features through the `unsafe` keyword.\n\n\nIn contrast, the Zig language is not a memory safe language by default.\nThere are some memory safety features that you get for free in Zig,\nespecially in arrays and pointer objects. But there are other tools\noffered by the language, that are not used by default.\nIn other words, the `zig` compiler does not obligate you to use such tools.\n\nThe tools listed below are related to memory safety. That is, they help you to achieve\nmemory safety in your Zig code:\n\n- `defer` allows you to keep free operations physically close to allocations. This helps you to avoid memory leaks, \"use after free\", and also \"double-free\" problems. Furthermore, it also keeps free operations logically tied to the end of the current scope, which greatly reduces the mental overhead about object lifetime.\n- `errdefer` helps you to guarantee that your program frees the allocated memory, even if a runtime error occurs.\n- pointers and objects are non-nullable by default. This helps you to avoid memory problems that might arise from de-referencing null pointers.\n- Zig offers some native types of allocators (called \"testing allocators\") that can detect memory leaks and double-frees. These types of allocators are widely used on unit tests, so they transform your unit tests into a weapon that you can use to detect memory problems in your code.\n- arrays and slices in Zig have their lengths embedded in the object itself, which makes the `zig` compiler very effective on detecting \"index out-of-range\" type of errors, and avoiding buffer overflows.\n\n\nDespite these features that Zig offers that are related to memory safety issues, the language\nalso has some rules that help you to achieve another type of safety, which is more related to\nprogram logic safety. These rules are:\n\n- pointers and objects are non-nullable by default. Which eliminates an edge case that might break the logic of your program.\n- switch statements must exaust all possible options.\n- the `zig` compiler forces you to handle every possible error in your program.\n\n\n## Other parts of Zig\n\nWe already learned a lot about Zig's syntax, and also, some pretty technical\ndetails about it. Just as a quick recap:\n\n- We talked about how functions are written in Zig in @sec-root-file and @sec-main-file.\n- How to create new objects/identifiers in @sec-root-file and especially in @sec-assignments.\n- How strings work in Zig in @sec-zig-strings.\n- How to use arrays and slices in @sec-arrays.\n- How to import functionality from other Zig modules in @sec-root-file.\n\n\nBut, for now, this amount of knowledge is enough for us to continue with this book.\nLater, over the next chapters we will still talk more about other parts of\nZig's syntax that are also equally important. Such as:\n\n\n- How Object-Oriented programming can be done in Zig through *struct declarations* in @sec-structs-and-oop.\n- Basic control flow syntax in @sec-zig-control-flow.\n- Enums in @sec-enum;\n- Pointers and Optionals in @sec-pointer;\n- Error handling with `try` and `catch` in @sec-error-handling;\n- Unit tests in @sec-unittests;\n- Vectors in @sec-vectors-simd;\n- Build System in @sec-build-system;\n",
         "supporting": [],
         "filters": [
           "rmarkdown/pagebreak.lua"
    diff --git a/_freeze/Chapters/02-debugging/execute-results/epub.json b/_freeze/Chapters/02-debugging/execute-results/epub.json
    deleted file mode 100644
    index 933510c4..00000000
    --- a/_freeze/Chapters/02-debugging/execute-results/epub.json
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -{
    -  "hash": "f6eea7230762e3b8cde487458c00b745",
    -  "result": {
    -    "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Debugging Zig applications\n\nBeing able to debug your applications is essential for any programmer who wants to\ndo serious programming in any language. That is why, in this chapter, we are going to talk about the\navailable strategies and tools to debug applications written in Zig.\n\n\n## Print debugging\n\nWe begin with the classic and battle-tested *print debugging* strategy.\nThe key advantage that debugging offers you is *visibility*.\nWith *print statements* you can easily see what results and objects\nare being produced by your application.\n\nThis is the essence of *print debugging* - using\nprint expressions to see the values that are being generated by your program,\nand, as a result, get a much better understanding of how your program\nis behaving.\n\nMany programmers often resort to the print functions in Zig, such as the `stdout.print()`,\nor, the `std.debug.print()`, to get a better understanding of their programs.\nThis is a known and old strategy that is very simple and effective, and it's better known within\nthe programming community as *print debugging*.\nIn Zig, you can print information to the `stdout` or `stderr` streams of your system.\n\nLet's begin with `stdout`. First, you\nneed to get access to the `stdout`, by calling the `getStdOut()` method, from\nthe Zig Standard Library. This method returns a *file descriptor* object,\nand, through this object you can read/write to the `stdout`.\nI recommend you to check out all methods available in this object, by [checking the page in\nthe Zig Standard Library Official Reference for the type `File`](https://ziglang.org/documentation/master/std/#std.fs.File)[^zig-fiile-reference].\n\n[^zig-fiile-reference]: .\n\nFor our purpose here, which is to write something to the `stdout`, especially to debug our\nprogram, I recommend you to use the `writer()` method, which gives you a *writer* object.\nThis *writer* object offers some helper methods to write stuff into the file descriptor object\nthat represents the `stdout` stream. In special, the `print()` method.\n\n\nThe `print()` method from this *writer* object is a \"print formatter\" type of a function.\nIn other words, this method works exactly like the `printf()` function from C,\nor, like `println!()` from Rust.\nIn the first argument of the function, you specify a template string, and,\nin the second argument, you provide a list of values (or objects) that you want to insert\ninto your template message.\n\nIdeally, the template string in the first argument should contain some format specifier.\nEach format specifier is matched to a value (or object) that you have listed in the second argument.\nSo, if you provided 5 different objects in the second argument, then, the template string\nshould contain 5 format specifiers, one for each object provided.\n\nEach format specifier is represented by a single letter, and\nyou provide this format specifier inside a pair of curly braces. So, if you want to format\nyour object using the string specifier (`s`), then, you can insert the text `{s}` in your template string.\nHere is a quick list of the most used format specifiers:\n\n- `d`: for printing integers and floating-point numbers.\n- `c`: for printing characters.\n- `s`: for printing strings.\n- `p`: for printing memory addresses.\n- `x`: for printing hexadecimal values.\n- `any`: use any compatible format specifier (i.e., it automatically selects a format specifier for you).\n\nThe code example below gives you an example of use of this `print()` method\nwith the `d` format specifier.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn add(x: u8, y: u8) u8 {\n    return x + y;\n}\n\npub fn main() !void {\n    const result = add(34, 16);\n    try stdout.print(\"Result: {d}\", .{result});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 50\n```\n\n\n:::\n:::\n\n\n\nIt's important to emphasize that, the `stdout.print()` method, as you would expect,\nprints your template string into the `stdout` stream of your system.\nHowever, you can also print your template string into the `stderr` stream\nif your prefer. All you need to do, is to replace the `stdout.print()`\ncall with the function `std.debug.print()`. Like this:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add(x: u8, y: u8) u8 {\n    return x + y;\n}\n\npub fn main() !void {\n    const result = add(34, 16);\n    std.debug.print(\"Result: {d}\\n\", .{result});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 50\n```\n\n\n:::\n:::\n\n\n\n\nYou could also achieve the exact same result by getting a file descriptor object to `stderr`,\nthen, creating a *writer* object to `stderr`, then, using the `print()` method of this\n*writer* object, like in the example below:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stderr = std.io.getStdErr().writer();\n// some more lines ...\ntry stderr.print(\"Result: {d}\", .{result});\n```\n:::\n\n\n\n\n\n## Debugging through debuggers\n\nAlthough *print debugging* is a valid and very useful strategy,\nmost programmers prefer to use a debugger to debug their programs.\nSince Zig is a low-level language, you can use either GDB (GNU Debugger),\nor LLDB (LLVM Project Debugger) as your debugger.\n\nBoth debuggers can work with Zig code, and it's a matter of taste here.\nYou choose the debugger of your preference, and you work with it.\nIn this book, I will use LLDB as my debugger in the examples.\n\n\n### Compile your source code in debug mode {#sec-compile-debug-mode}\n\nIn order to debug your program through a debugger, you must compile\nyour source code in `Debug` mode. Because when you compile your\nsource code in other modes (such as `Release`), the compiler usually\nstrips out some essential information that is used by the debugger\nto read and track your program, like PDB (*Program Database*) files.\n\nBy compiling your source code in `Debug` mode, you ensure that the debugger\nwill find the necessary information in your program to debug it.\nBy default, the compiler uses the `Debug` mode when compiling your code.\nHaving this in mind, when you compile your program with the `build-exe`\ncommand (which was described in @sec-compile-code), if you don't specify\nan explicit mode through the `-O` command-line [^oargument]\nargument, then, the compiler will compile your code in `Debug` mode.\n\n[^oargument]: See .\n\n\n### Let's debug a program\n\nAs an example, let's use LLDB to navigate and investigate the following\npiece of Zig code:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\nfn add_and_increment(a: u8, b: u8) u8 {\n    const sum = a + b;\n    const incremented = sum + 1;\n    return incremented;\n}\n\npub fn main() !void {\n    var n = add_and_increment(2, 3);\n    n = add_and_increment(n, n);\n    try stdout.print(\"Result: {d}!\\n\", .{n});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 13!\n```\n\n\n:::\n:::\n\n\n\nThere is nothing wrong with this program. But it's\na good start for us. First, we need to compile\nthis program with the `zig build-exe` command.\nFor this example, suppose that I have compiled the above\nZig code into a binary executable called `add_program`.\n\n```bash\nzig build-exe add_program.zig\n```\n\nNow, we can start LLDB with `add_program`, like this:\n\n```bash\nlldb add_program\n```\n\nFrom now on, LLDB is started, and you can know that I'm\nexecuting LLDB commands by looking at the prefix `(lldb)`.\nIf something is prefixed with `(lldb)`, then you know\nthat it's a LLDB command.\n\nThe first thing I will do, is to set a breakpoint at\nthe `main()` function, by executing `b main`.\nAfter that, I just start the execution of the program\nwith `run`.\nYou can see in the output below, that the execution\nstopped at the first line in the function `main()`, as we expected.\n\n```bash\n(lldb) b main\nBreakpoint 1: where = debugging`debug1.main + 22\n    at debug1.zig:11:30, address = 0x00000000010341a6\n(lldb) run\nProcess 8654 launched: 'add_program' (x86_64)\nProcess 8654 stopped\n* thread #1, name = 'add_program',\n    stop reason = breakpoint 1.1 frame #0: 0x10341a6\n    add_program`debug1.main at add_program.zig:11:30\n   8   \t}\n   9\n   10  \tpub fn main() !void {\n-> 11  \t    var n = add_and_increment(2, 3);\n   12  \t    n = add_and_increment(n, n);\n   13  \t    try stdout.print(\"Result: {d}!\\n\", .{n});\n   14  \t}\n```\n\nI can start navigating through the code, and checking the objects\nthat are being generated. If you are not familiar with the commands\navailable in LLDB, I recommend you to read the official documentation\nof the project[^lldb].\nYou can also look for cheat sheets, which quickly describes all commands\navailable for you[^lldb-quick-list].\n\n[^lldb]: \n[^lldb-quick-list]: .\n\nCurrently, we are in the first line at the `main()` function. In this line, we create\nthe `n` object, by executing the `add_and_increment()` function.\nTo execute the current line of code, and go to the next line, we can\nrun the `n` LLDB command. Let's execute this command.\n\nAfter we executed this line, we can also look at the value stored inside this `n` object\nby using the `p` LLDB command. The syntax for this command is `p `.\n\nIf we take a look at the value stored in the `n` object (`p n`),\nnotice that it stores the hexadecimal value `0x06`, which\nis the number 6 in decimal. We can also see that this value has a type of `unsigned char`,\nwhich is an unsigned 8-bit integer.\nWe have talked already about this in @sec-zig-strings, that `u8` integers in Zig are equivalent\nto the C data type `unsigned char`.\n\n\n\n```bash\n(lldb) n\nProcess 4798 stopped\n* thread #1, name = 'debugging',\n    stop reason = step over frame #0: 0x10341ae\n    debugging`debug1.main at debug1.zig:12:26\n   9\n   10  \tpub fn main() !void {\n   11  \t    var n = add_and_increment(2, 3);\n-> 12  \t    n = add_and_increment(n, n);\n   13  \t    try stdout.print(\"Result: {d}!\\n\", .{n});\n   14  \t}\n(lldb) p n\n(unsigned char) $1 = '\\x06'\n```\n\nNow, on the next line of code, we are executing the `add_and_increment()` function once again.\nWhy not step inside this function? Shall we? We can do that, by executing the `s` LLDB command.\nNotice in the example below that, after executing this command, we have entered into the context of the\n`add_and_increment()` function.\n\nAlso notice in the example below that, I have walked two more lines in the function's body, then,\nI execute the `frame variable` LLDB command, to see at once, the value stored in each of the variables\nthat were created inside the current scope.\n\nYou can see in the output below that, the object `sum` stores the value `\\f`,\nwhich represents the *form feed* character. This character in the ASCII table,\ncorresponds to the hexadecimal value `0x0C`, or, in decimal, the number 12.\nSo, this means that the result of the expression `a + b` executed at line\n5, resulted in the number 12.\n\n```bash\n(lldb) s\nProcess 4798 stopped\n* thread #1, name = 'debugging',\n    stop reason = step in frame #0: 0x10342de\n    debugging`debug1.add_and_increment(a='\\x02', b='\\x03')\n    at debug1.zig:4:39\n-> 4   \tfn add_and_increment(a: u8, b: u8) u8 {\n   5   \t    const sum = a + b;\n   6   \t    const incremented = sum + 1;\n   7   \t    return incremented;\n(lldb) n\n(lldb) n\n(lldb) frame variable\n(unsigned char) a = '\\x06'\n(unsigned char) b = '\\x06'\n(unsigned char) sum = '\\f'\n(unsigned char) incremented = '\\x06'\n```\n\n\n\n## How to investigate the data type of your objects\n\nSince Zig is a strongly-typed language, the data types associated with your objects\nare very important for your program. So, debugging the data types associated\nwith your objects might be important to understand bugs and errors in your program.\n\nWhen you walk through your program with a debugger, you can inspect the types of\nyour objects by simply printing them to the console, with the LLDB `p` command.\nBut you also have alternatives embedded in the language itself to access the data\ntypes of your objects.\n\nIn Zig, you can retrieve the data type of an object, by using the built-in function\n`@TypeOf()`. Just apply this function over the object, and you get access to\nthe data type of the object.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst expect = std.testing.expect;\n\npub fn main() !void {\n    const number: i32 = 5;\n    try expect(@TypeOf(number) == i32);\n    try stdout.print(\"{any}\\n\", .{@TypeOf(number)});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ni32\n```\n\n\n:::\n:::\n\n\n\nThis function is similar to the `type()` built-in function from Python,\nor, the `typeof` operator in Javascript.\n",
    -    "supporting": [
    -      "02-debugging_files"
    -    ],
    -    "filters": [
    -      "rmarkdown/pagebreak.lua"
    -    ],
    -    "includes": {},
    -    "engineDependencies": {
    -      "knitr": [
    -        "{\"type\":\"list\",\"attributes\":{},\"value\":[]}"
    -      ]
    -    },
    -    "preserve": null,
    -    "postProcess": false
    -  }
    -}
    \ No newline at end of file
    diff --git a/_freeze/Chapters/02-debugging/execute-results/html.json b/_freeze/Chapters/02-debugging/execute-results/html.json
    index 2068b83e..739f1f0c 100644
    --- a/_freeze/Chapters/02-debugging/execute-results/html.json
    +++ b/_freeze/Chapters/02-debugging/execute-results/html.json
    @@ -2,10 +2,8 @@
       "hash": "f6eea7230762e3b8cde487458c00b745",
       "result": {
         "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Debugging Zig applications\n\nBeing able to debug your applications is essential for any programmer who wants to\ndo serious programming in any language. That is why, in this chapter, we are going to talk about the\navailable strategies and tools to debug applications written in Zig.\n\n\n## Print debugging\n\nWe begin with the classic and battle-tested *print debugging* strategy.\nThe key advantage that debugging offers you is *visibility*.\nWith *print statements* you can easily see what results and objects\nare being produced by your application.\n\nThis is the essence of *print debugging* - using\nprint expressions to see the values that are being generated by your program,\nand, as a result, get a much better understanding of how your program\nis behaving.\n\nMany programmers often resort to the print functions in Zig, such as the `stdout.print()`,\nor, the `std.debug.print()`, to get a better understanding of their programs.\nThis is a known and old strategy that is very simple and effective, and it's better known within\nthe programming community as *print debugging*.\nIn Zig, you can print information to the `stdout` or `stderr` streams of your system.\n\nLet's begin with `stdout`. First, you\nneed to get access to the `stdout`, by calling the `getStdOut()` method, from\nthe Zig Standard Library. This method returns a *file descriptor* object,\nand, through this object you can read/write to the `stdout`.\nI recommend you to check out all methods available in this object, by [checking the page in\nthe Zig Standard Library Official Reference for the type `File`](https://ziglang.org/documentation/master/std/#std.fs.File)[^zig-fiile-reference].\n\n[^zig-fiile-reference]: .\n\nFor our purpose here, which is to write something to the `stdout`, especially to debug our\nprogram, I recommend you to use the `writer()` method, which gives you a *writer* object.\nThis *writer* object offers some helper methods to write stuff into the file descriptor object\nthat represents the `stdout` stream. In special, the `print()` method.\n\n\nThe `print()` method from this *writer* object is a \"print formatter\" type of a function.\nIn other words, this method works exactly like the `printf()` function from C,\nor, like `println!()` from Rust.\nIn the first argument of the function, you specify a template string, and,\nin the second argument, you provide a list of values (or objects) that you want to insert\ninto your template message.\n\nIdeally, the template string in the first argument should contain some format specifier.\nEach format specifier is matched to a value (or object) that you have listed in the second argument.\nSo, if you provided 5 different objects in the second argument, then, the template string\nshould contain 5 format specifiers, one for each object provided.\n\nEach format specifier is represented by a single letter, and\nyou provide this format specifier inside a pair of curly braces. So, if you want to format\nyour object using the string specifier (`s`), then, you can insert the text `{s}` in your template string.\nHere is a quick list of the most used format specifiers:\n\n- `d`: for printing integers and floating-point numbers.\n- `c`: for printing characters.\n- `s`: for printing strings.\n- `p`: for printing memory addresses.\n- `x`: for printing hexadecimal values.\n- `any`: use any compatible format specifier (i.e., it automatically selects a format specifier for you).\n\nThe code example below gives you an example of use of this `print()` method\nwith the `d` format specifier.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn add(x: u8, y: u8) u8 {\n    return x + y;\n}\n\npub fn main() !void {\n    const result = add(34, 16);\n    try stdout.print(\"Result: {d}\", .{result});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 50\n```\n\n\n:::\n:::\n\n\n\n\nIt's important to emphasize that, the `stdout.print()` method, as you would expect,\nprints your template string into the `stdout` stream of your system.\nHowever, you can also print your template string into the `stderr` stream\nif your prefer. All you need to do, is to replace the `stdout.print()`\ncall with the function `std.debug.print()`. Like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add(x: u8, y: u8) u8 {\n    return x + y;\n}\n\npub fn main() !void {\n    const result = add(34, 16);\n    std.debug.print(\"Result: {d}\\n\", .{result});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 50\n```\n\n\n:::\n:::\n\n\n\n\n\nYou could also achieve the exact same result by getting a file descriptor object to `stderr`,\nthen, creating a *writer* object to `stderr`, then, using the `print()` method of this\n*writer* object, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stderr = std.io.getStdErr().writer();\n// some more lines ...\ntry stderr.print(\"Result: {d}\", .{result});\n```\n:::\n\n\n\n\n\n\n## Debugging through debuggers\n\nAlthough *print debugging* is a valid and very useful strategy,\nmost programmers prefer to use a debugger to debug their programs.\nSince Zig is a low-level language, you can use either GDB (GNU Debugger),\nor LLDB (LLVM Project Debugger) as your debugger.\n\nBoth debuggers can work with Zig code, and it's a matter of taste here.\nYou choose the debugger of your preference, and you work with it.\nIn this book, I will use LLDB as my debugger in the examples.\n\n\n### Compile your source code in debug mode {#sec-compile-debug-mode}\n\nIn order to debug your program through a debugger, you must compile\nyour source code in `Debug` mode. Because when you compile your\nsource code in other modes (such as `Release`), the compiler usually\nstrips out some essential information that is used by the debugger\nto read and track your program, like PDB (*Program Database*) files.\n\nBy compiling your source code in `Debug` mode, you ensure that the debugger\nwill find the necessary information in your program to debug it.\nBy default, the compiler uses the `Debug` mode when compiling your code.\nHaving this in mind, when you compile your program with the `build-exe`\ncommand (which was described in @sec-compile-code), if you don't specify\nan explicit mode through the `-O` command-line [^oargument]\nargument, then, the compiler will compile your code in `Debug` mode.\n\n[^oargument]: See .\n\n\n### Let's debug a program\n\nAs an example, let's use LLDB to navigate and investigate the following\npiece of Zig code:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\nfn add_and_increment(a: u8, b: u8) u8 {\n    const sum = a + b;\n    const incremented = sum + 1;\n    return incremented;\n}\n\npub fn main() !void {\n    var n = add_and_increment(2, 3);\n    n = add_and_increment(n, n);\n    try stdout.print(\"Result: {d}!\\n\", .{n});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 13!\n```\n\n\n:::\n:::\n\n\n\n\nThere is nothing wrong with this program. But it's\na good start for us. First, we need to compile\nthis program with the `zig build-exe` command.\nFor this example, suppose that I have compiled the above\nZig code into a binary executable called `add_program`.\n\n```bash\nzig build-exe add_program.zig\n```\n\nNow, we can start LLDB with `add_program`, like this:\n\n```bash\nlldb add_program\n```\n\nFrom now on, LLDB is started, and you can know that I'm\nexecuting LLDB commands by looking at the prefix `(lldb)`.\nIf something is prefixed with `(lldb)`, then you know\nthat it's a LLDB command.\n\nThe first thing I will do, is to set a breakpoint at\nthe `main()` function, by executing `b main`.\nAfter that, I just start the execution of the program\nwith `run`.\nYou can see in the output below, that the execution\nstopped at the first line in the function `main()`, as we expected.\n\n```bash\n(lldb) b main\nBreakpoint 1: where = debugging`debug1.main + 22\n    at debug1.zig:11:30, address = 0x00000000010341a6\n(lldb) run\nProcess 8654 launched: 'add_program' (x86_64)\nProcess 8654 stopped\n* thread #1, name = 'add_program',\n    stop reason = breakpoint 1.1 frame #0: 0x10341a6\n    add_program`debug1.main at add_program.zig:11:30\n   8   \t}\n   9\n   10  \tpub fn main() !void {\n-> 11  \t    var n = add_and_increment(2, 3);\n   12  \t    n = add_and_increment(n, n);\n   13  \t    try stdout.print(\"Result: {d}!\\n\", .{n});\n   14  \t}\n```\n\nI can start navigating through the code, and checking the objects\nthat are being generated. If you are not familiar with the commands\navailable in LLDB, I recommend you to read the official documentation\nof the project[^lldb].\nYou can also look for cheat sheets, which quickly describes all commands\navailable for you[^lldb-quick-list].\n\n[^lldb]: \n[^lldb-quick-list]: .\n\nCurrently, we are in the first line at the `main()` function. In this line, we create\nthe `n` object, by executing the `add_and_increment()` function.\nTo execute the current line of code, and go to the next line, we can\nrun the `n` LLDB command. Let's execute this command.\n\nAfter we executed this line, we can also look at the value stored inside this `n` object\nby using the `p` LLDB command. The syntax for this command is `p `.\n\nIf we take a look at the value stored in the `n` object (`p n`),\nnotice that it stores the hexadecimal value `0x06`, which\nis the number 6 in decimal. We can also see that this value has a type of `unsigned char`,\nwhich is an unsigned 8-bit integer.\nWe have talked already about this in @sec-zig-strings, that `u8` integers in Zig are equivalent\nto the C data type `unsigned char`.\n\n\n\n```bash\n(lldb) n\nProcess 4798 stopped\n* thread #1, name = 'debugging',\n    stop reason = step over frame #0: 0x10341ae\n    debugging`debug1.main at debug1.zig:12:26\n   9\n   10  \tpub fn main() !void {\n   11  \t    var n = add_and_increment(2, 3);\n-> 12  \t    n = add_and_increment(n, n);\n   13  \t    try stdout.print(\"Result: {d}!\\n\", .{n});\n   14  \t}\n(lldb) p n\n(unsigned char) $1 = '\\x06'\n```\n\nNow, on the next line of code, we are executing the `add_and_increment()` function once again.\nWhy not step inside this function? Shall we? We can do that, by executing the `s` LLDB command.\nNotice in the example below that, after executing this command, we have entered into the context of the\n`add_and_increment()` function.\n\nAlso notice in the example below that, I have walked two more lines in the function's body, then,\nI execute the `frame variable` LLDB command, to see at once, the value stored in each of the variables\nthat were created inside the current scope.\n\nYou can see in the output below that, the object `sum` stores the value `\\f`,\nwhich represents the *form feed* character. This character in the ASCII table,\ncorresponds to the hexadecimal value `0x0C`, or, in decimal, the number 12.\nSo, this means that the result of the expression `a + b` executed at line\n5, resulted in the number 12.\n\n```bash\n(lldb) s\nProcess 4798 stopped\n* thread #1, name = 'debugging',\n    stop reason = step in frame #0: 0x10342de\n    debugging`debug1.add_and_increment(a='\\x02', b='\\x03')\n    at debug1.zig:4:39\n-> 4   \tfn add_and_increment(a: u8, b: u8) u8 {\n   5   \t    const sum = a + b;\n   6   \t    const incremented = sum + 1;\n   7   \t    return incremented;\n(lldb) n\n(lldb) n\n(lldb) frame variable\n(unsigned char) a = '\\x06'\n(unsigned char) b = '\\x06'\n(unsigned char) sum = '\\f'\n(unsigned char) incremented = '\\x06'\n```\n\n\n\n## How to investigate the data type of your objects\n\nSince Zig is a strongly-typed language, the data types associated with your objects\nare very important for your program. So, debugging the data types associated\nwith your objects might be important to understand bugs and errors in your program.\n\nWhen you walk through your program with a debugger, you can inspect the types of\nyour objects by simply printing them to the console, with the LLDB `p` command.\nBut you also have alternatives embedded in the language itself to access the data\ntypes of your objects.\n\nIn Zig, you can retrieve the data type of an object, by using the built-in function\n`@TypeOf()`. Just apply this function over the object, and you get access to\nthe data type of the object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst expect = std.testing.expect;\n\npub fn main() !void {\n    const number: i32 = 5;\n    try expect(@TypeOf(number) == i32);\n    try stdout.print(\"{any}\\n\", .{@TypeOf(number)});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ni32\n```\n\n\n:::\n:::\n\n\n\n\nThis function is similar to the `type()` built-in function from Python,\nor, the `typeof` operator in Javascript.\n",
    -    "supporting": [
    -      "02-debugging_files"
    -    ],
    +    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n# Debugging Zig applications\n\nBeing able to debug your applications is essential for any programmer who wants to\ndo serious programming in any language. That is why, in this chapter, we are going to talk about the\navailable strategies and tools to debug applications written in Zig.\n\n\n## Print debugging\n\nWe begin with the classic and battle-tested *print debugging* strategy.\nThe key advantage that debugging offers you is *visibility*.\nWith *print statements* you can easily see what results and objects\nare being produced by your application.\n\nThis is the essence of *print debugging* - using\nprint expressions to see the values that are being generated by your program,\nand, as a result, get a much better understanding of how your program\nis behaving.\n\nMany programmers often resort to the print functions in Zig, such as the `stdout.print()`,\nor, the `std.debug.print()`, to get a better understanding of their programs.\nThis is a known and old strategy that is very simple and effective, and it's better known within\nthe programming community as *print debugging*.\nIn Zig, you can print information to the `stdout` or `stderr` streams of your system.\n\nLet's begin with `stdout`. First, you\nneed to get access to the `stdout`, by calling the `getStdOut()` method, from\nthe Zig Standard Library. This method returns a *file descriptor* object,\nand, through this object you can read/write to the `stdout`.\nI recommend you to check out all methods available in this object, by [checking the page in\nthe Zig Standard Library Official Reference for the type `File`](https://ziglang.org/documentation/master/std/#std.fs.File)[^zig-fiile-reference].\n\n[^zig-fiile-reference]: .\n\nFor our purpose here, which is to write something to the `stdout`, especially to debug our\nprogram, I recommend you to use the `writer()` method, which gives you a *writer* object.\nThis *writer* object offers some helper methods to write stuff into the file descriptor object\nthat represents the `stdout` stream. In special, the `print()` method.\n\n\nThe `print()` method from this *writer* object is a \"print formatter\" type of a function.\nIn other words, this method works exactly like the `printf()` function from C,\nor, like `println!()` from Rust.\nIn the first argument of the function, you specify a template string, and,\nin the second argument, you provide a list of values (or objects) that you want to insert\ninto your template message.\n\nIdeally, the template string in the first argument should contain some format specifier.\nEach format specifier is matched to a value (or object) that you have listed in the second argument.\nSo, if you provided 5 different objects in the second argument, then, the template string\nshould contain 5 format specifiers, one for each object provided.\n\nEach format specifier is represented by a single letter, and\nyou provide this format specifier inside a pair of curly braces. So, if you want to format\nyour object using the string specifier (`s`), then, you can insert the text `{s}` in your template string.\nHere is a quick list of the most used format specifiers:\n\n- `d`: for printing integers and floating-point numbers.\n- `c`: for printing characters.\n- `s`: for printing strings.\n- `p`: for printing memory addresses.\n- `x`: for printing hexadecimal values.\n- `any`: use any compatible format specifier (i.e., it automatically selects a format specifier for you).\n\nThe code example below gives you an example of use of this `print()` method\nwith the `d` format specifier.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn add(x: u8, y: u8) u8 {\n    return x + y;\n}\n\npub fn main() !void {\n    const result = add(34, 16);\n    try stdout.print(\"Result: {d}\", .{result});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 50\n```\n\n\n:::\n:::\n\n\nIt's important to emphasize that, the `stdout.print()` method, as you would expect,\nprints your template string into the `stdout` stream of your system.\nHowever, you can also print your template string into the `stderr` stream\nif your prefer. All you need to do, is to replace the `stdout.print()`\ncall with the function `std.debug.print()`. Like this:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add(x: u8, y: u8) u8 {\n    return x + y;\n}\n\npub fn main() !void {\n    const result = add(34, 16);\n    std.debug.print(\"Result: {d}\\n\", .{result});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 50\n```\n\n\n:::\n:::\n\n\n\nYou could also achieve the exact same result by getting a file descriptor object to `stderr`,\nthen, creating a *writer* object to `stderr`, then, using the `print()` method of this\n*writer* object, like in the example below:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stderr = std.io.getStdErr().writer();\n// some more lines ...\ntry stderr.print(\"Result: {d}\", .{result});\n```\n:::\n\n\n\n\n## Debugging through debuggers\n\nAlthough *print debugging* is a valid and very useful strategy,\nmost programmers prefer to use a debugger to debug their programs.\nSince Zig is a low-level language, you can use either GDB (GNU Debugger),\nor LLDB (LLVM Project Debugger) as your debugger.\n\nBoth debuggers can work with Zig code, and it's a matter of taste here.\nYou choose the debugger of your preference, and you work with it.\nIn this book, I will use LLDB as my debugger in the examples.\n\n\n### Compile your source code in debug mode {#sec-compile-debug-mode}\n\nIn order to debug your program through a debugger, you must compile\nyour source code in `Debug` mode. Because when you compile your\nsource code in other modes (such as `Release`), the compiler usually\nstrips out some essential information that is used by the debugger\nto read and track your program, like PDB (*Program Database*) files.\n\nBy compiling your source code in `Debug` mode, you ensure that the debugger\nwill find the necessary information in your program to debug it.\nBy default, the compiler uses the `Debug` mode when compiling your code.\nHaving this in mind, when you compile your program with the `build-exe`\ncommand (which was described in @sec-compile-code), if you don't specify\nan explicit mode through the `-O` command-line [^oargument]\nargument, then, the compiler will compile your code in `Debug` mode.\n\n[^oargument]: See .\n\n\n### Let's debug a program\n\nAs an example, let's use LLDB to navigate and investigate the following\npiece of Zig code:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\n\nfn add_and_increment(a: u8, b: u8) u8 {\n    const sum = a + b;\n    const incremented = sum + 1;\n    return incremented;\n}\n\npub fn main() !void {\n    var n = add_and_increment(2, 3);\n    n = add_and_increment(n, n);\n    try stdout.print(\"Result: {d}!\\n\", .{n});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nResult: 13!\n```\n\n\n:::\n:::\n\n\nThere is nothing wrong with this program. But it's\na good start for us. First, we need to compile\nthis program with the `zig build-exe` command.\nFor this example, suppose that I have compiled the above\nZig code into a binary executable called `add_program`.\n\n```bash\nzig build-exe add_program.zig\n```\n\nNow, we can start LLDB with `add_program`, like this:\n\n```bash\nlldb add_program\n```\n\nFrom now on, LLDB is started, and you can know that I'm\nexecuting LLDB commands by looking at the prefix `(lldb)`.\nIf something is prefixed with `(lldb)`, then you know\nthat it's a LLDB command.\n\nThe first thing I will do, is to set a breakpoint at\nthe `main()` function, by executing `b main`.\nAfter that, I just start the execution of the program\nwith `run`.\nYou can see in the output below, that the execution\nstopped at the first line in the function `main()`, as we expected.\n\n```bash\n(lldb) b main\nBreakpoint 1: where = debugging`debug1.main + 22\n    at debug1.zig:11:30, address = 0x00000000010341a6\n(lldb) run\nProcess 8654 launched: 'add_program' (x86_64)\nProcess 8654 stopped\n* thread #1, name = 'add_program',\n    stop reason = breakpoint 1.1 frame #0: 0x10341a6\n    add_program`debug1.main at add_program.zig:11:30\n   8   \t}\n   9\n   10  \tpub fn main() !void {\n-> 11  \t    var n = add_and_increment(2, 3);\n   12  \t    n = add_and_increment(n, n);\n   13  \t    try stdout.print(\"Result: {d}!\\n\", .{n});\n   14  \t}\n```\n\nI can start navigating through the code, and checking the objects\nthat are being generated. If you are not familiar with the commands\navailable in LLDB, I recommend you to read the official documentation\nof the project[^lldb].\nYou can also look for cheat sheets, which quickly describes all commands\navailable for you[^lldb-quick-list].\n\n[^lldb]: \n[^lldb-quick-list]: .\n\nCurrently, we are in the first line at the `main()` function. In this line, we create\nthe `n` object, by executing the `add_and_increment()` function.\nTo execute the current line of code, and go to the next line, we can\nrun the `n` LLDB command. Let's execute this command.\n\nAfter we executed this line, we can also look at the value stored inside this `n` object\nby using the `p` LLDB command. The syntax for this command is `p `.\n\nIf we take a look at the value stored in the `n` object (`p n`),\nnotice that it stores the hexadecimal value `0x06`, which\nis the number 6 in decimal. We can also see that this value has a type of `unsigned char`,\nwhich is an unsigned 8-bit integer.\nWe have talked already about this in @sec-zig-strings, that `u8` integers in Zig are equivalent\nto the C data type `unsigned char`.\n\n\n\n```bash\n(lldb) n\nProcess 4798 stopped\n* thread #1, name = 'debugging',\n    stop reason = step over frame #0: 0x10341ae\n    debugging`debug1.main at debug1.zig:12:26\n   9\n   10  \tpub fn main() !void {\n   11  \t    var n = add_and_increment(2, 3);\n-> 12  \t    n = add_and_increment(n, n);\n   13  \t    try stdout.print(\"Result: {d}!\\n\", .{n});\n   14  \t}\n(lldb) p n\n(unsigned char) $1 = '\\x06'\n```\n\nNow, on the next line of code, we are executing the `add_and_increment()` function once again.\nWhy not step inside this function? Shall we? We can do that, by executing the `s` LLDB command.\nNotice in the example below that, after executing this command, we have entered into the context of the\n`add_and_increment()` function.\n\nAlso notice in the example below that, I have walked two more lines in the function's body, then,\nI execute the `frame variable` LLDB command, to see at once, the value stored in each of the variables\nthat were created inside the current scope.\n\nYou can see in the output below that, the object `sum` stores the value `\\f`,\nwhich represents the *form feed* character. This character in the ASCII table,\ncorresponds to the hexadecimal value `0x0C`, or, in decimal, the number 12.\nSo, this means that the result of the expression `a + b` executed at line\n5, resulted in the number 12.\n\n```bash\n(lldb) s\nProcess 4798 stopped\n* thread #1, name = 'debugging',\n    stop reason = step in frame #0: 0x10342de\n    debugging`debug1.add_and_increment(a='\\x02', b='\\x03')\n    at debug1.zig:4:39\n-> 4   \tfn add_and_increment(a: u8, b: u8) u8 {\n   5   \t    const sum = a + b;\n   6   \t    const incremented = sum + 1;\n   7   \t    return incremented;\n(lldb) n\n(lldb) n\n(lldb) frame variable\n(unsigned char) a = '\\x06'\n(unsigned char) b = '\\x06'\n(unsigned char) sum = '\\f'\n(unsigned char) incremented = '\\x06'\n```\n\n\n\n## How to investigate the data type of your objects\n\nSince Zig is a strongly-typed language, the data types associated with your objects\nare very important for your program. So, debugging the data types associated\nwith your objects might be important to understand bugs and errors in your program.\n\nWhen you walk through your program with a debugger, you can inspect the types of\nyour objects by simply printing them to the console, with the LLDB `p` command.\nBut you also have alternatives embedded in the language itself to access the data\ntypes of your objects.\n\nIn Zig, you can retrieve the data type of an object, by using the built-in function\n`@TypeOf()`. Just apply this function over the object, and you get access to\nthe data type of the object.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst expect = std.testing.expect;\n\npub fn main() !void {\n    const number: i32 = 5;\n    try expect(@TypeOf(number) == i32);\n    try stdout.print(\"{any}\\n\", .{@TypeOf(number)});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\ni32\n```\n\n\n:::\n:::\n\n\nThis function is similar to the `type()` built-in function from Python,\nor, the `typeof` operator in Javascript.\n",
    +    "supporting": [],
         "filters": [
           "rmarkdown/pagebreak.lua"
         ],
    diff --git a/_freeze/Chapters/03-structs/execute-results/epub.json b/_freeze/Chapters/03-structs/execute-results/epub.json
    deleted file mode 100644
    index 7b1a937c..00000000
    --- a/_freeze/Chapters/03-structs/execute-results/epub.json
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -{
    -  "hash": "eb1d22d8dc0121e7c7768b70c606a801",
    -  "result": {
    -    "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n    try stdout.print(\n        \"x > 10!\\n\", .{}\n    );\n} else {\n    try stdout.print(\n        \"x <= 10!\\n\", .{}\n    );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n    SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n    var area: []const u8 = undefined;\n    const role = Role.SE;\n    switch (role) {\n        .PM, .SE, .DPE, .PO => {\n            area = \"Platform\";\n        },\n        .DE, .DA => {\n            area = \"Data & Analytics\";\n        },\n        .KS => {\n            area = \"Sales\";\n        },\n    }\n    try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `role`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object has type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e., four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n    // Many lines ...\n    switch (byte) {\n        '\\n' => try writer.writeAll(\"␊\"),\n        '\\r' => try writer.writeAll(\"␍\"),\n        '\\t' => try writer.writeAll(\"␉\"),\n        else => try writer.writeByte('.'),\n    }\n}\n```\n:::\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n    1, 2 => \"beginner\",\n    3 => \"professional\",\n    else => {\n        @panic(\"Not supported level!\");\n    },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n            @panic(\"Not supported level!\");\n            ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It's important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n    0...25 => \"beginner\",\n    26...75 => \"intermediary\",\n    76...100 => \"professional\",\n    else => {\n        @panic(\"Not supported level!\");\n    },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n    1 => {\n        try stdout.print(\"First branch\\n\", .{});\n        continue :xsw 2;\n    },\n    2 => continue :xsw 3,\n    3 => return,\n    4 => {},\n    else => {\n        try stdout.print(\n            \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n        );\n    },\n}\n```\n:::\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n    defer std.debug.print(\n        \"Exiting function ...\\n\", .{}\n    );\n    try stdout.print(\"Adding some numbers ...\\n\", .{});\n    const x = 2 + 2; _ = x;\n    try stdout.print(\"Multiplying ...\\n\", .{});\n    const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n    try foo();\n}\n```\n:::\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function gets executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, it's worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression gets executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n    var i: usize = 1;\n    errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n    defer i = 2;\n    try foo();\n}\n```\n:::\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n    return error.FooError;\n    ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that gets printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n    var i: usize = 1;\n    defer i = 2;\n    errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n    try foo();\n}\n```\n:::\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n    return error.FooError;\n    ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n    // code to execute\n}\n```\n:::\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n    try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n    try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n    try stdout.print(\"{d} | \", .{i});\n    i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n    try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It's the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e., the logical test is equal to false), the function raises an assertion error.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n    if (i == 10) {\n        break;\n    }\n    i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n    if ((i % 2) == 0) {\n        continue;\n    }\n    try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e., constant) object\".\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n    x = x + 2;\n    return x;\n}\n\npub fn main() !void {\n    const y = add2(4);\n    std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n    x = x + 2;\n    ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e., `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n    const d: u32 = 2;\n    x.* = x.* + d;\n}\n\npub fn main() !void {\n    var x: u32 = 4;\n    add2(&x);\n    std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n    id: u64,\n    name: []const u8,\n    email: []const u8,\n\n    fn init(id: u64,\n            name: []const u8,\n            email: []const u8) User {\n\n        return User {\n            .id = id,\n            .name = name,\n            .email = email\n        };\n    }\n\n    fn print_name(self: User) !void {\n        try stdout.print(\"{s}\\n\", .{self.name});\n    }\n};\n\npub fn main() !void {\n    const u = User.init(1, \"pedro\", \"email@gmail.com\");\n    try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\n\n### The `pub` keyword\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nIn essence, this keyword is short for \"public\", and it makes an item/component available outside of the\nmodule where this item/component is declared. In other words, if I don't apply the `pub` keyword on\nsomething, it means that this \"something\" is available to be called/used only from within the module\nwhere this \"something\" is declared.\n\nTo demonstrate the effect of this keyword let's focus again on the `User` struct that we have\ndeclared on the previous section. For our example here, let's suppose that this `User` struct is declared inside\na Zig module named `user.zig`. If I don't use the `pub` keyword on the `User` struct, it means that I can create\nan `User` object, and call it's methods (`print_name()` and `init()`) only from within the module where the `User`\nstruct is declared, which in this case is the `user.zig` module.\n\nThis is why the previous code example works fine. Because we declare and also use the `User` struct\ninside the same module. But problems start to arise when we try to import and call/use this struct\nfrom another module. For example, if I create a new module called `register.zig`, and import the `user.zig`\nmodule into it, and try to annotate any variable with the `User` type, I get an error from the compiler.\n\n```zig\n// register.zig\nconst user = @import(\"user.zig\");\npub fn main() !void {\n    const u: user.User = undefined;\n    _ = u;\n}\n```\n\n```\nregister.zig:3:18: error: 'User' is not marked 'pub'\n    const u: user.User = undefined;\n             ~~~~^~~~~\nuser.zig:3:1: note: declared here\nconst User = struct {\n^~~~~\n```\n\nTherefore, if you want to use something outside of the module where this \"something\" is declared,\nyou have to mark it with the `pub` keyword. This \"something\" can be a module,\na struct, a function, an object, etc.\n\nFor our example here, if we go back to the `user.zig` module, and add the `pub` keyword\nto the `User` struct declaration, then, I can successfully compile the `register.zig` module.\n\n```zig\n// user.zig\n// Added the `pub` keyword to `User`\npub const User = struct {\n// ...\n```\n\n```zig\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n    const u: user.User = undefined;\n    _ = u;\n}\n```\n\n\nNow, what do you think it will happen if I try to actually call from `register.zig` any of the methods\nof the `User` struct? For example, if I try to call the `init()` method? The answer is: I get a similar error message,\nwarning me that the `init()` method is not marked as `pub`, as you can see below:\n\n```zig\nconst user = @import(\"user.zig\");\npub fn main() !void {\n    const u: user.User = user.User.init(\n        1, \"pedro\", \"email@gmail.com\"\n    );\n    _ = u;\n}\n```\n\n```\nregister.zig:3:35: error: 'init' is not marked 'pub'\n    const u: user.User = user.User.init(\n                         ~~~~~~~~~^~~~~\nuser.zig:8:5: note: declared here\n    fn init(id: u64,\n    ^~~~~~~\n```\n\nThus, just because we have applied the `pub` keyword on the struct declaration,\nthis does not make the methods of that struct public as well. If we want to use\nany method from a struct (such as the `init()` method) outside of the module\nwhere this struct is declared, we have to mark this method with the `pub` keyword\nas well.\n\nGoing back to the `user.zig` module, and marking both the `init()` and `print_name()`\nmethods with the `pub` keyword, makes them both available to the outside world, and,\nas consequence, makes the previous code example work.\n\n\n```zig\n// user.zig\n// Added the `pub` keyword to `User.init`\n    pub fn init(\n// ...\n// Added the `pub` keyword to `User.print_name`\n    pub fn print_name(self: User) !void {\n// ...\n```\n\n```zig\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n    const u: user.User = user.User.init(\n        1, \"pedro\", \"email@gmail.com\"\n    );\n    _ = u;\n}\n```\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n    .id = 1,\n    .name = \"Pedro\",\n    .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    const stdout = std.io.getStdOut().writer();\n    try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n    x: f64,\n    y: f64,\n    z: f64,\n};\n```\n:::\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt's not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n    x: f64,\n    y: f64,\n    z: f64,\n\n    pub fn distance(self: Vec3, other: Vec3) f64 {\n        const xd = m.pow(f64, self.x - other.x, 2.0);\n        const yd = m.pow(f64, self.y - other.y, 2.0);\n        const zd = m.pow(f64, self.z - other.z, 2.0);\n        return m.sqrt(xd + yd + zd);\n    }\n};\n```\n:::\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n    .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n    .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n    \"Distance: {d}\\n\",\n    .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods are affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e., changes the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n    x: f64,\n    y: f64,\n    z: f64,\n\n    pub fn distance(self: Vec3, other: Vec3) f64 {\n        const xd = m.pow(f64, self.x - other.x, 2.0);\n        const yd = m.pow(f64, self.y - other.y, 2.0);\n        const zd = m.pow(f64, self.z - other.z, 2.0);\n        return m.sqrt(xd + yd + zd);\n    }\n\n    pub fn twice(self: *Vec3) void {\n        self.x = self.x * 2.0;\n        self.y = self.y * 2.0;\n        self.z = self.z * 2.0;\n    }\n};\n```\n:::\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n    .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n    pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n        self.x = self.x * 2.0;\n        ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it's not about the input object, it's about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special part in this place. More specifically, it's\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and trying\nto infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n    // many lines of code ...\n    if (builtin.sanitize_thread) {\n        const tsan = struct {\n            extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n            extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n        };\n\n        const addr: *anyopaque = self;\n        return switch (order) {\n            .unordered, .monotonic => @compileError(\n                @tagName(order)\n                ++ \" only applies to atomic loads and stores\"\n            ),\n            .acquire => tsan.__tsan_acquire(addr),\n            .release => tsan.__tsan_release(addr),\n            .acq_rel, .seq_cst => {\n                tsan.__tsan_acquire(addr);\n                tsan.__tsan_release(addr);\n            },\n        };\n    }\n\n    return @fence(order);\n}\n```\n:::\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e., we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it's explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n    const x: usize = 500;\n    const y = @as(u32, x);\n    try expect(@TypeOf(y) == u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3731626c8b4e.test_0...OKAll 1 tests passed\n  d.\n```\n\n\n:::\n:::\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe. There are many situations where these assumptions do not hold. For example,\n\nwhen casting an integer value into a float value, or vice-versa, it's not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n    const x: usize = 565;\n    const y: f32 = @floatFromInt(x);\n    try expect(@TypeOf(y) == f32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file373174d96589.test_0...OKAll 1 tests passed\n  d.\n```\n\n\n:::\n:::\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e., they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n    const bytes align(@alignOf(u32)) = [_]u8{\n        0x12, 0x12, 0x12, 0x12\n    };\n    const u32_ptr: *const u32 = @ptrCast(&bytes);\n    try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file373135327b62.test_0...OKAll 1 tests passed\n  d.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e., a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" gets executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object gets saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n    catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n    catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n    .{ .max_threads = num_threads }\n);\n```\n:::\n",
    -    "supporting": [
    -      "03-structs_files"
    -    ],
    -    "filters": [
    -      "rmarkdown/pagebreak.lua"
    -    ],
    -    "includes": {},
    -    "engineDependencies": {
    -      "knitr": [
    -        "{\"type\":\"list\",\"attributes\":{},\"value\":[]}"
    -      ]
    -    },
    -    "preserve": null,
    -    "postProcess": false
    -  }
    -}
    \ No newline at end of file
    diff --git a/_freeze/Chapters/03-structs/execute-results/html.json b/_freeze/Chapters/03-structs/execute-results/html.json
    index a05f2337..a74310d7 100644
    --- a/_freeze/Chapters/03-structs/execute-results/html.json
    +++ b/_freeze/Chapters/03-structs/execute-results/html.json
    @@ -1,8 +1,8 @@
     {
    -  "hash": "eb1d22d8dc0121e7c7768b70c606a801",
    +  "hash": "5eabe664631237b4e295d88eb82533f3",
       "result": {
         "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n    try stdout.print(\n        \"x > 10!\\n\", .{}\n    );\n} else {\n    try stdout.print(\n        \"x <= 10!\\n\", .{}\n    );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n    SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n    var area: []const u8 = undefined;\n    const role = Role.SE;\n    switch (role) {\n        .PM, .SE, .DPE, .PO => {\n            area = \"Platform\";\n        },\n        .DE, .DA => {\n            area = \"Data & Analytics\";\n        },\n        .KS => {\n            area = \"Sales\";\n        },\n    }\n    try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `role`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object has type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e., four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n    // Many lines ...\n    switch (byte) {\n        '\\n' => try writer.writeAll(\"␊\"),\n        '\\r' => try writer.writeAll(\"␍\"),\n        '\\t' => try writer.writeAll(\"␉\"),\n        else => try writer.writeByte('.'),\n    }\n}\n```\n:::\n\n\n\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n    1, 2 => \"beginner\",\n    3 => \"professional\",\n    else => {\n        @panic(\"Not supported level!\");\n    },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n            @panic(\"Not supported level!\");\n            ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It's important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n    0...25 => \"beginner\",\n    26...75 => \"intermediary\",\n    76...100 => \"professional\",\n    else => {\n        @panic(\"Not supported level!\");\n    },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\n\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n    1 => {\n        try stdout.print(\"First branch\\n\", .{});\n        continue :xsw 2;\n    },\n    2 => continue :xsw 3,\n    3 => return,\n    4 => {},\n    else => {\n        try stdout.print(\n            \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n        );\n    },\n}\n```\n:::\n\n\n\n\n\n\n### The `defer` keyword {#sec-defer}\n\nWith the `defer` keyword you can register an expression to be executed when you exit the current scope.\nTherefore, this keyword has a similar functionality as the `on.exit()` function from R.\nTake the `foo()` function below as an example. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n    defer std.debug.print(\n        \"Exiting function ...\\n\", .{}\n    );\n    try stdout.print(\"Adding some numbers ...\\n\", .{});\n    const x = 2 + 2; _ = x;\n    try stdout.print(\"Multiplying ...\\n\", .{});\n    const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n    try foo();\n}\n```\n:::\n\n\n\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function gets executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, it's worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression gets executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n    var i: usize = 1;\n    errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n    defer i = 2;\n    try foo();\n}\n```\n:::\n\n\n\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n    return error.FooError;\n    ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that gets printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n    var i: usize = 1;\n    defer i = 2;\n    errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n    try foo();\n}\n```\n:::\n\n\n\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n    return error.FooError;\n    ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n    // code to execute\n}\n```\n:::\n\n\n\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n    try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\n\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n    try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n    try stdout.print(\"{d} | \", .{i});\n    i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n    try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It's the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e., the logical test is equal to false), the function raises an assertion error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n    if (i == 10) {\n        break;\n    }\n    i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\n\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n    if ((i % 2) == 0) {\n        continue;\n    }\n    try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e., constant) object\".\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n    x = x + 2;\n    return x;\n}\n\npub fn main() !void {\n    const y = add2(4);\n    std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n    x = x + 2;\n    ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e., `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n    const d: u32 = 2;\n    x.* = x.* + d;\n}\n\npub fn main() !void {\n    var x: u32 = 4;\n    add2(&x);\n    std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n    id: u64,\n    name: []const u8,\n    email: []const u8,\n\n    fn init(id: u64,\n            name: []const u8,\n            email: []const u8) User {\n\n        return User {\n            .id = id,\n            .name = name,\n            .email = email\n        };\n    }\n\n    fn print_name(self: User) !void {\n        try stdout.print(\"{s}\\n\", .{self.name});\n    }\n};\n\npub fn main() !void {\n    const u = User.init(1, \"pedro\", \"email@gmail.com\");\n    try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### The `pub` keyword\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nIn essence, this keyword is short for \"public\", and it makes an item/component available outside of the\nmodule where this item/component is declared. In other words, if I don't apply the `pub` keyword on\nsomething, it means that this \"something\" is available to be called/used only from within the module\nwhere this \"something\" is declared.\n\nTo demonstrate the effect of this keyword let's focus again on the `User` struct that we have\ndeclared on the previous section. For our example here, let's suppose that this `User` struct is declared inside\na Zig module named `user.zig`. If I don't use the `pub` keyword on the `User` struct, it means that I can create\nan `User` object, and call it's methods (`print_name()` and `init()`) only from within the module where the `User`\nstruct is declared, which in this case is the `user.zig` module.\n\nThis is why the previous code example works fine. Because we declare and also use the `User` struct\ninside the same module. But problems start to arise when we try to import and call/use this struct\nfrom another module. For example, if I create a new module called `register.zig`, and import the `user.zig`\nmodule into it, and try to annotate any variable with the `User` type, I get an error from the compiler.\n\n```zig\n// register.zig\nconst user = @import(\"user.zig\");\npub fn main() !void {\n    const u: user.User = undefined;\n    _ = u;\n}\n```\n\n```\nregister.zig:3:18: error: 'User' is not marked 'pub'\n    const u: user.User = undefined;\n             ~~~~^~~~~\nuser.zig:3:1: note: declared here\nconst User = struct {\n^~~~~\n```\n\nTherefore, if you want to use something outside of the module where this \"something\" is declared,\nyou have to mark it with the `pub` keyword. This \"something\" can be a module,\na struct, a function, an object, etc.\n\nFor our example here, if we go back to the `user.zig` module, and add the `pub` keyword\nto the `User` struct declaration, then, I can successfully compile the `register.zig` module.\n\n```zig\n// user.zig\n// Added the `pub` keyword to `User`\npub const User = struct {\n// ...\n```\n\n```zig\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n    const u: user.User = undefined;\n    _ = u;\n}\n```\n\n\nNow, what do you think it will happen if I try to actually call from `register.zig` any of the methods\nof the `User` struct? For example, if I try to call the `init()` method? The answer is: I get a similar error message,\nwarning me that the `init()` method is not marked as `pub`, as you can see below:\n\n```zig\nconst user = @import(\"user.zig\");\npub fn main() !void {\n    const u: user.User = user.User.init(\n        1, \"pedro\", \"email@gmail.com\"\n    );\n    _ = u;\n}\n```\n\n```\nregister.zig:3:35: error: 'init' is not marked 'pub'\n    const u: user.User = user.User.init(\n                         ~~~~~~~~~^~~~~\nuser.zig:8:5: note: declared here\n    fn init(id: u64,\n    ^~~~~~~\n```\n\nThus, just because we have applied the `pub` keyword on the struct declaration,\nthis does not make the methods of that struct public as well. If we want to use\nany method from a struct (such as the `init()` method) outside of the module\nwhere this struct is declared, we have to mark this method with the `pub` keyword\nas well.\n\nGoing back to the `user.zig` module, and marking both the `init()` and `print_name()`\nmethods with the `pub` keyword, makes them both available to the outside world, and,\nas consequence, makes the previous code example work.\n\n\n```zig\n// user.zig\n// Added the `pub` keyword to `User.init`\n    pub fn init(\n// ...\n// Added the `pub` keyword to `User.print_name`\n    pub fn print_name(self: User) !void {\n// ...\n```\n\n```zig\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n    const u: user.User = user.User.init(\n        1, \"pedro\", \"email@gmail.com\"\n    );\n    _ = u;\n}\n```\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n    .id = 1,\n    .name = \"Pedro\",\n    .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\n\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    const stdout = std.io.getStdOut().writer();\n    try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n    x: f64,\n    y: f64,\n    z: f64,\n};\n```\n:::\n\n\n\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt's not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n    x: f64,\n    y: f64,\n    z: f64,\n\n    pub fn distance(self: Vec3, other: Vec3) f64 {\n        const xd = m.pow(f64, self.x - other.x, 2.0);\n        const yd = m.pow(f64, self.y - other.y, 2.0);\n        const zd = m.pow(f64, self.z - other.z, 2.0);\n        return m.sqrt(xd + yd + zd);\n    }\n};\n```\n:::\n\n\n\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n    .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n    .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n    \"Distance: {d}\\n\",\n    .{v1.distance(v2)}\n);\n```\n:::\n\n\n\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods are affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e., changes the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n    x: f64,\n    y: f64,\n    z: f64,\n\n    pub fn distance(self: Vec3, other: Vec3) f64 {\n        const xd = m.pow(f64, self.x - other.x, 2.0);\n        const yd = m.pow(f64, self.y - other.y, 2.0);\n        const zd = m.pow(f64, self.z - other.z, 2.0);\n        return m.sqrt(xd + yd + zd);\n    }\n\n    pub fn twice(self: *Vec3) void {\n        self.x = self.x * 2.0;\n        self.y = self.y * 2.0;\n        self.z = self.z * 2.0;\n    }\n};\n```\n:::\n\n\n\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n    .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n    pub fn twice(self: Vec3) void {\n```\n:::\n\n\n\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n        self.x = self.x * 2.0;\n        ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it's not about the input object, it's about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special part in this place. More specifically, it's\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and trying\nto infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n    // many lines of code ...\n    if (builtin.sanitize_thread) {\n        const tsan = struct {\n            extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n            extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n        };\n\n        const addr: *anyopaque = self;\n        return switch (order) {\n            .unordered, .monotonic => @compileError(\n                @tagName(order)\n                ++ \" only applies to atomic loads and stores\"\n            ),\n            .acquire => tsan.__tsan_acquire(addr),\n            .release => tsan.__tsan_release(addr),\n            .acq_rel, .seq_cst => {\n                tsan.__tsan_acquire(addr);\n                tsan.__tsan_release(addr);\n            },\n        };\n    }\n\n    return @fence(order);\n}\n```\n:::\n\n\n\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e., we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it's explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n    const x: usize = 500;\n    const y = @as(u32, x);\n    try expect(@TypeOf(y) == u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3fc93b4ea641.test_0...OKAll 1 tests passed\n  d.\n```\n\n\n:::\n:::\n\n\n\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe. There are many situations where these assumptions do not hold. For example,\n\nwhen casting an integer value into a float value, or vice-versa, it's not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n    const x: usize = 565;\n    const y: f32 = @floatFromInt(x);\n    try expect(@TypeOf(y) == f32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3fc91795a712.test_0...OKAll 1 tests passed\n  d.\n```\n\n\n:::\n:::\n\n\n\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e., they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n    const bytes align(@alignOf(u32)) = [_]u8{\n        0x12, 0x12, 0x12, 0x12\n    };\n    const u32_ptr: *const u32 = @ptrCast(&bytes);\n    try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3fc945f8b4b0.test_0...OKAll 1 tests passed\n  d.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e., a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\n\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" gets executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object gets saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n    catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n    catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n    .{ .max_threads = num_threads }\n);\n```\n:::\n",
    +    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n# Control flow, structs, modules and types\n\nWe have discussed a lot of Zig's syntax in the last chapter,\nespecially in @sec-root-file and @sec-main-file.\nBut we still need to discuss some other very important\nelements of the language. Elements that you will use constantly on your day-to-day\nroutine.\n\nWe begin this chapter by discussing the different keywords and structures\nin Zig related to control flow (e.g. loops and if statements).\nThen, we talk about structs and how they can be used to do some\nbasic Object-Oriented (OOP) patterns in Zig. We also talk about\ntype inference and type casting.\nFinally, we end this chapter by discussing modules, and how they relate\nto structs.\n\n\n\n## Control flow {#sec-zig-control-flow}\n\nSometimes, you need to make decisions in your program. Maybe you need to decide\nwhether or not to execute a specific piece of code. Or maybe,\nyou need to apply the same operation over a sequence of values. These kinds of tasks,\ninvolve using structures that are capable of changing the \"control flow\" of our program.\n\nIn computer science, the term \"control flow\" usually refers to the order in which expressions (or commands)\nare evaluated in a given language or program. But this term is also used to refer\nto structures that are capable of changing this \"evaluation order\" of the commands\nexecuted by a given language/program.\n\nThese structures are better known\nby a set of terms, such as: loops, if/else statements, switch statements, among others. So,\nloops and if/else statements are examples of structures that can change the \"control\nflow\" of our program. The keywords `continue` and `break` are also examples of symbols\nthat can change the order of evaluation, since they can move our program to the next iteration\nof a loop, or make the loop stop completely.\n\n\n### If/else statements\n\nAn if/else statement performs a \"conditional flow operation\".\nA conditional flow control (or choice control) allows you to execute\nor ignore a certain block of commands based on a logical condition.\nMany programmers and computer science professionals also use\nthe term \"branching\" in this case.\nIn essence, an if/else statement allow us to use the result of a logical test\nto decide whether or not to execute a given block of commands.\n\nIn Zig, we write if/else statements by using the keywords `if` and `else`.\nWe start with the `if` keyword followed by a logical test inside a pair\nof parentheses, followed by a pair of curly braces which contains the lines\nof code to be executed in case the logical test returns the value `true`.\n\nAfter that, you can optionally add an `else` statement. To do that, just add the `else`\nkeyword followed by a pair of curly braces, with the lines of code\nto executed in case the logical test defined at `if` returns `false`.\n\nIn the example below, we are testing if the object `x` contains a number\nthat is greater than 10. Judging by the output printed to the console,\nwe know that this logical test returned `false`. Because the output\nin the console is compatible with the line of code present in the\n`else` branch of the if/else statement.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x = 5;\nif (x > 10) {\n    try stdout.print(\n        \"x > 10!\\n\", .{}\n    );\n} else {\n    try stdout.print(\n        \"x <= 10!\\n\", .{}\n    );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nx <= 10!\n```\n\n\n:::\n:::\n\n\n\n\n### Switch statements {#sec-switch}\n\nSwitch statements are also available in Zig, and they have a very similar syntax to a switch statement in Rust.\nAs you would expect, to write a switch statement in Zig we use the `switch` keyword.\nWe provide the value that we want to \"switch over\" inside a\npair of parentheses. Then, we list the possible combinations (or \"branches\")\ninside a pair of curly braces.\n\nLet's take a look at the code example below. You can see that\nI'm creating an enum type called `Role`. We talk more about enums in @sec-enum.\nBut in summary, this `Role` type is listing different types of roles in a fictitious\ncompany, like `SE` for Software Engineer, `DE` for Data Engineer, `PM` for Product Manager,\netc.\n\nNotice that we are using the value from the `role` object in the\nswitch statement, to discover which exact area we need to store in the `area` variable object.\nAlso notice that we are using type inference inside the switch statement, with the dot character,\nas we are going to describe in @sec-type-inference.\nThis makes the `zig` compiler infer the correct data type of the values (`PM`, `SE`, etc.) for us.\n\nAlso notice that, we are grouping multiple values in the same branch of the switch statement.\nWe just separate each possible value with a comma. For example, if `role` contains either `DE` or `DA`,\nthe `area` variable would contain the value `\"Data & Analytics\"`, instead of `\"Platform\"` or `\"Sales\"`.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Role = enum {\n    SE, DPE, DE, DA, PM, PO, KS\n};\n\npub fn main() !void {\n    var area: []const u8 = undefined;\n    const role = Role.SE;\n    switch (role) {\n        .PM, .SE, .DPE, .PO => {\n            area = \"Platform\";\n        },\n        .DE, .DA => {\n            area = \"Data & Analytics\";\n        },\n        .KS => {\n            area = \"Sales\";\n        },\n    }\n    try stdout.print(\"{s}\\n\", .{area});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nPlatform\n```\n\n\n:::\n:::\n\n\n\n#### Switch statements must exhaust all possibilities\n\nOne very important aspect about switch statements in Zig\nis that they must exhaust all existing possibilities.\nIn other words, all possible values that could be found inside the `role`\nobject must be explicitly handled in this switch statement.\n\nSince the `role` object has type `Role`, the only possible values to\nbe found inside this object are `PM`, `SE`, `DPE`, `PO`, `DE`, `DA` and `KS`.\nThere are no other possible values to be stored in this `role` object.\nThus, the switch statements must have a combination (branch) for each one of these values.\nThis is what \"exhaust all existing possibilities\" means. The switch statement covers\nevery possible case.\n\nTherefore, you cannot write a switch statement in Zig, and leave an edge case\nwith no explicit action to be taken.\nThis is a similar behaviour to switch statements in Rust, which also have to\nhandle all possible cases.\n\n\n\n#### The else branch\n\nTake a look at the `dump_hex_fallible()` function below as an example. This function\ncomes from the Zig Standard Library. More precisely, from the\n[`debug.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/debug.zig)[^debug-mod].\nThere are multiple lines in this function, but I omitted them to focus solely on the\nswitch statement found in this function. Notice that this switch statement has four\npossible cases (i.e., four explicit branches). Also, notice that we used an `else` branch\nin this case.\n\nAn `else` branch in a switch statement works as the \"default branch\".\nWhenever you have multiple cases in your switch statement where\nyou want to apply the exact same action, you can use an `else` branch to do that.\n\n[^debug-mod]: \n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn dump_hex_fallible(bytes: []const u8) !void {\n    // Many lines ...\n    switch (byte) {\n        '\\n' => try writer.writeAll(\"␊\"),\n        '\\r' => try writer.writeAll(\"␍\"),\n        '\\t' => try writer.writeAll(\"␉\"),\n        else => try writer.writeByte('.'),\n    }\n}\n```\n:::\n\n\nMany programmers would also use an `else` branch to handle a \"not supported\" case.\nThat is, a case that cannot be properly handled by your code, or, just a case that\nshould not be \"fixed\". Therefore, you can use an `else` branch to panic (or raise an error)\nin your program to stop the current execution.\n\nTake the code example below. We can see that, we are handling the cases\nfor the `level` object being either 1, 2, or 3. All other possible cases are not supported by default,\nand, as consequence, we raise a runtime error in such cases through the `@panic()` built-in function.\n\nAlso notice that, we are assigning the result of the switch statement to a new object called `category`.\nThis is another thing that you can do with switch statements in Zig. If a branch\noutputs a value as result, you can store the result value of the switch statement into\na new object.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n    1, 2 => \"beginner\",\n    3 => \"professional\",\n    else => {\n        @panic(\"Not supported level!\");\n    },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n:::\n\n\n```\nthread 13103 panic: Not supported level!\nt.zig:9:13: 0x1033c58 in main (switch2)\n            @panic(\"Not supported level!\");\n            ^\n```\n\n\n\n#### Using ranges in switch\n\nFurthermore, you can also use ranges of values in switch statements.\nThat is, you can create a branch in your switch statement that is used\nwhenever the input value is within the specified range. These \"range expressions\"\nare created with the operator `...`. It's important\nto emphasize that the ranges created by this operator are\ninclusive on both ends.\n\nFor example, I could easily change the previous code example to support all\nlevels between 0 and 100. Like this:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst level: u8 = 4;\nconst category = switch (level) {\n    0...25 => \"beginner\",\n    26...75 => \"intermediary\",\n    76...100 => \"professional\",\n    else => {\n        @panic(\"Not supported level!\");\n    },\n};\ntry stdout.print(\"{s}\\n\", .{category});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nbeginner\n```\n\n\n:::\n:::\n\n\nThis is neat, and it works with character ranges too. That is, I could\nsimply write `'a'...'z'`, to match any character value that is a\nlowercase letter, and it would work fine.\n\n\n#### Labeled switch statements\n\nIn @sec-blocks we have talked about labeling blocks, and also, about using these labels\nto return a value from the block. Well, from version 0.14.0 and onwards of the `zig` compiler,\nyou can also apply labels over switch statements, which makes it possible to almost implement a\n\"C `goto`\" like pattern.\n\nFor example, if you give the label `xsw` to a switch statement, you can use this\nlabel in conjunction with the `continue` keyword to go back to the beginning of the switch\nstatement. In the example below, the execution goes back to the beginning of the\nswitch statement two times, before ending at the `3` branch.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nxsw: switch (@as(u8, 1)) {\n    1 => {\n        try stdout.print(\"First branch\\n\", .{});\n        continue :xsw 2;\n    },\n    2 => continue :xsw 3,\n    3 => return,\n    4 => {},\n    else => {\n        try stdout.print(\n            \"Unmatched case, value: {d}\\n\", .{@as(u8, 1)}\n        );\n    },\n}\n```\n:::\n\n\n\n### The `defer` keyword {#sec-defer}\n\nZig has a `defer` keyword, which plays a very important role in control flow, and also, in releasing resources.\nIn summary, the `defer` keyword allows you to register an expression to be executed when you exit the current scope.\n\nAt this point, you might attempt to compare the Zig `defer` keyword to it's sibling in the Go language\n(i.e. [Go also has a `defer` keyword](https://go.dev/tour/flowcontrol/12)).\nHowever, the Go `defer` keyword behaves slightly different\nthan it's sibling in Zig. More specifically, the `defer` keyword in Go always move an expression to be\nexecuted at the **exit of the current function**.\n\nIf you think deeply about this statement, you will notice that the \"exit of the current function\" is something\nslightly different than the \"exit of the current scope\". So, just be careful when comparing the two\nkeywords together. A single function in Zig might contain many different scopes inside of it, and, therefore,\nthe `defer` input expression might be executed at different places of the function, depending on which scope you\nare currently in.\n\nAs a first example, consider the `foo()` function exposed below. When we execute this `foo()` function, the expression\nthat prints the message \"Exiting function ...\" is getting executed only when the function exits\nits scope.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn foo() !void {\n    defer std.debug.print(\n        \"Exiting function ...\\n\", .{}\n    );\n    try stdout.print(\"Adding some numbers ...\\n\", .{});\n    const x = 2 + 2; _ = x;\n    try stdout.print(\"Multiplying ...\\n\", .{});\n    const y = 2 * 8; _ = y;\n}\n\npub fn main() !void {\n    try foo();\n}\n```\n:::\n\n\n```\nAdding some numbers ...\nMultiplying ...\nExiting function ...\n```\n\nTherefore, we can use `defer` to declare an expression that is going to be executed\nwhen your code exits the current scope. Some programmers like to interpret the phrase \"exit of the current scope\"\nas \"the end of the current scope\". But this interpretation might not be entirely correct, depending\non what you consider as \"the end of the current scope\".\n\nI mean, what do you consider as **the end** of the current scope? Is it the closing curly bracket (`}`) of the scope?\nIs it when the last expression in the function gets executed? Is it when the function returns to the previous scope?\nEtc. For example, it would not be correct to interpret the \"exit of the current scope\" as the closing\ncurly bracket of the scope. Because the function might exit from an earlier position than this\nclosing curly bracket (e.g. an error value was generated at a previous line inside the function;\nthe function reached an earlier return statement; etc.). Anyway, just be careful with this interpretation.\n\nNow, if you remember of what we have discussed in @sec-blocks, there are multiple structures in the language\nthat create their own separate scopes. For/while loops, if/else statements,\nfunctions, normal blocks, etc. This also affects the interpretation of `defer`.\nFor example, if you use `defer` inside a for loop, then, the given expression\nwill be executed everytime this specific for loop exits its own scope.\n\nBefore we continue, it's worth emphasizing that the `defer` keyword is an \"unconditional defer\".\nWhich means that the given expression will be executed no matter how the code exits\nthe current scope. For example, your code might exit the current scope because of an error value\nbeing generated, or, because of a return statement, or, a break statement, etc.\n\n\n\n### The `errdefer` keyword {#sec-errdefer1}\n\nOn the previous section, we have discussed the `defer` keyword, which you can use to\nregister an expression to be executed at the exit of the current scope.\nBut this keyword has a brother, which is the `errdefer` keyword. While `defer`\nis an \"unconditional defer\", the `errdefer` keyword is a \"conditional defer\".\nWhich means that the given expression is executed only when you exit the current\nscope on a very specific circumstance.\n\nIn more details, the expression given to `errdefer` is executed only when an error occurs in the current scope.\nTherefore, if the function (or for/while loop, if/else statement, etc.) exits the current scope\nin a normal situation, without errors, the expression given to `errdefer` is not executed.\n\nThis makes the `errdefer` keyword one of the many tools available in Zig for error handling.\nIn this section, we are more concerned with the control flow aspects around `errdefer`.\nBut we are going to discuss `errdefer` later as a error handling tool in @sec-errdefer2.\n\nThe code example below demonstrates three things:\n\n- that `defer` is an \"unconditional defer\", because the given expression gets executed regardless of how the function `foo()` exits its own scope.\n- that `errdefer` is executed because the function `foo()` returned an error value.\n- that `defer` and `errdefer` expressions are executed in a LIFO (*last in, first out*) order.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n    var i: usize = 1;\n    errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n    defer i = 2;\n    try foo();\n}\n```\n:::\n\n\n```\nValue of i: 2\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n    return error.FooError;\n    ^\n```\n\n\nWhen I say that \"defer expressions\" are executed in a LIFO order, what I want to say is that\nthe last `defer` or `errdefer` expressions in the code are the first ones to be executed.\nYou could also interpret this as: \"defer expressions\" are executed from bottom to top, or,\nfrom last to first.\n\nTherefore, if I change the order of the `defer` and `errdefer` expressions, you will notice that\nthe value of `i` that gets printed to the console changes to 1. This doesn't mean that the\n`defer` expression was not executed in this case. This actually means that the `defer` expression\nwas executed only after the `errdefer` expression. The code example below demonstrates this:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn foo() !void { return error.FooError; }\npub fn main() !void {\n    var i: usize = 1;\n    defer i = 2;\n    errdefer std.debug.print(\"Value of i: {d}\\n\", .{i});\n    try foo();\n}\n```\n:::\n\n\n```\nValue of i: 1\nerror: FooError\n/t.zig:6:5: 0x1037e48 in foo (defer)\n    return error.FooError;\n    ^\n```\n\n\n\n\n### For loops\n\nA loop allows you to execute the same lines of code multiple times,\nthus, creating a \"repetition space\" in the execution flow of your program.\nLoops are particularly useful when we want to replicate the same function\n(or the same set of commands) over different inputs.\n\nThere are different types of loops available in Zig. But the most\nessential of them all is probably the *for loop*. A for loop is\nused to apply the same piece of code over the elements of a slice, or, an array.\n\nFor loops in Zig use a syntax that may be unfamiliar to programmers coming from\nother languages. You start with the `for` keyword, then, you\nlist the items that you want to iterate\nover inside a pair of parentheses. Then, inside of a pair of pipes (`|`)\nyou should declare an identifier that will serve as your iterator, or,\nthe \"repetition index of the loop\".\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (items) |value| {\n    // code to execute\n}\n```\n:::\n\n\nTherefore, instead of using a `(value in items)` syntax,\nin Zig, for loops use the syntax `(items) |value|`. In the example\nbelow, you can see that we are looping through the items\nof the array stored at the object `name`, and printing to the\nconsole the decimal representation of each character in this array.\n\nIf we wanted, we could also iterate through a slice (or a portion) of\nthe array, instead of iterating through the entire array stored in the `name` object.\nJust use a range selector to select the section you want. For example,\nI could provide the expression `name[0..3]` to the for loop, to iterate\njust through the first 3 elements in the array.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = [_]u8{'P','e','d','r','o'};\nfor (name) |char| {\n    try stdout.print(\"{d} | \", .{char});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n80 | 101 | 100 | 114 | 111 | \n```\n\n\n:::\n:::\n\n\nIn the above example we are using the value itself of each\nelement in the array as our iterator. But there are many situations where\nwe need to use an index instead of the actual values of the items.\n\nYou can do that by providing a second set of items to iterate over.\nMore precisely, you provide the range selector `0..` to the for loop. So,\nyes, you can use two different iterators at the same time in a for\nloop in Zig.\n\nBut remember from @sec-assignments that, every object\nyou create in Zig must be used in some way. So if you declare two iterators\nin your for loop, you must use both iterators inside the for loop body.\nBut if you want to use just the index iterator, and not use the \"value iterator\",\nthen, you can discard the value iterator by maching the\nvalue items to the underscore character, like in the example below:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst name = \"Pedro\";\nfor (name, 0..) |_, i| {\n    try stdout.print(\"{d} | \", .{i});\n}\n```\n:::\n\n\n```\n0 | 1 | 2 | 3 | 4 |\n```\n\n\n### While loops\n\nA while loop is created from the `while` keyword. A `for` loop\niterates through the items of an array, but a `while` loop\nwill loop continuously, and infinitely, until a logical test\n(specified by you) becomes false.\n\nYou start with the `while` keyword, then, you define a logical\nexpression inside a pair of parentheses, and the body of the\nloop is provided inside a pair of curly braces, like in the example below:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) {\n    try stdout.print(\"{d} | \", .{i});\n    i += 1;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\nYou can also specify the increment expression to be used at the beginning of a while loop.\nTo do that, we write the increment expression inside a pair of parentheses after a colon character (`:`).\nThe code example below demonstrates this other pattern.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: u8 = 1;\nwhile (i < 5) : (i += 1) {\n    try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 2 | 3 | 4 | \n```\n\n\n:::\n:::\n\n\n### Using `break` and `continue`\n\nIn Zig, you can explicitly stop the execution of a loop, or, jump to the next iteration of the loop, by using\nthe keywords `break` and `continue`, respectively. The `while` loop presented in the next code example is,\nat first sight, an infinite loop. Because the logical value inside the parenthese will always be equal to `true`.\nBut what makes this `while` loop stop when the `i` object reaches the count\n10? It's the `break` keyword!\n\nInside the while loop, we have an if statement that is constantly checking if the `i` variable\nis equal to 10. Since we are incrementing the value of `i` at each iteration of the\nwhile loop, this `i` object will eventually be equal to 10, and when it is, the if statement\nwill execute the `break` expression, and, as a result, the execution of the while loop is stopped.\n\nNotice the use of the `expect()` function from the Zig Standard Library after the while loop.\nThis `expect()` function is an \"assert\" type of function.\nThis function checks if the logical test provided is equal to true. If so, the function do nothing.\nOtherwise (i.e., the logical test is equal to false), the function raises an assertion error.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar i: usize = 0;\nwhile (true) {\n    if (i == 10) {\n        break;\n    }\n    i += 1;\n}\ntry std.testing.expect(i == 10);\ntry stdout.print(\"Everything worked!\", .{});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nEverything worked!\n```\n\n\n:::\n:::\n\n\nSince this code example was executed successfully by the `zig` compiler,\nwithout raising any errors, we known that, after the execution of the while loop,\nthe `i` object is equal to 10. Because if it wasn't equal to 10, an error would have\nbeen raised by `expect()`.\n\nNow, in the next example, we have a use case for\nthe `continue` keyword. The if statement is constantly\nchecking if the current index is a multiple of 2. If\nit is, we jump to the next iteration of the loop.\nOtherwise, the loop just prints the current index to the console.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ns = [_]u8{1,2,3,4,5,6};\nfor (ns) |i| {\n    if ((i % 2) == 0) {\n        continue;\n    }\n    try stdout.print(\"{d} | \", .{i});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1 | 3 | 5 | \n```\n\n\n:::\n:::\n\n\n\n\n## Function parameters are immutable {#sec-fun-pars}\n\nWe have already discussed a lot of the syntax behind function declarations in @sec-root-file and @sec-main-file.\nBut I want to emphasize a curious fact about function parameters (a.k.a. function arguments) in Zig.\nIn summary, function parameters are immutable in Zig.\n\nTake the code example below, where we declare a simple function that just tries to add\nsome amount to the input integer, and returns the result back. If you look closely\nat the body of this `add2()` function, you will notice that we try\nto save the result back into the `x` function argument.\n\nIn other words, this function not only uses the value that it received through the function argument\n`x`, but it also tries to change the value of this function argument, by assigning the addition result\ninto `x`. However, function arguments in Zig are immutable. You cannot change their values, or, you\ncannot assign values to them inside the body's function.\n\nThis is the reason why, the code example below does not compile successfully. If you try to compile\nthis code example, you will get a compile error message about \"trying to change the value of a\nimmutable (i.e., constant) object\".\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: u32) u32 {\n    x = x + 2;\n    return x;\n}\n\npub fn main() !void {\n    const y = add2(4);\n    std.debug.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n```\nt.zig:3:5: error: cannot assign to constant\n    x = x + 2;\n    ^\n```\n\n\n### A free optimization\n\nIf a function argument receives as input an object whose data type is\nany of the primitive types that we have listed in @sec-primitive-data-types,\nthis object is always passed by value to the function. In other words, this object\nis copied into the function stack frame.\n\nHowever, if the input object have a more complex data type, for example, it might\nbe a struct instance, or an array, or an union value, etc., in cases like that, the `zig` compiler\nwill take the liberty of deciding for you which strategy is best. Thus, the `zig` compiler will\npass your object to the function either by value, or by reference. The compiler will always\nchoose the strategy that is faster for you.\nThis optimization that you get for free is possible only because function arguments are\nimmutable in Zig.\n\n\n### How to overcome this barrier\n\nThere are some situations where you might need to change the value of your function argument\ndirectly inside the function's body. This happens more often when we are passing\nC structs as inputs to Zig functions.\n\nIn a situation like this, you can overcome this barrier by using a pointer. In other words,\ninstead of passing a value as input to the argument, you can pass a \"pointer to value\" instead.\nYou can change the value that the pointer points to, by dereferencing it.\n\nTherefore, if we take our previous `add2()` example, we can change the value of the\nfunction argument `x` inside the function's body by marking the `x` argument as a\n\"pointer to a `u32` value\" (i.e., `*u32` data type), instead of a `u32` value.\nBy making it a pointer, we can finally alter the value of this function argument directly inside\nthe body of the `add2()` function. You can see that the code example below compiles successfully.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn add2(x: *u32) void {\n    const d: u32 = 2;\n    x.* = x.* + d;\n}\n\npub fn main() !void {\n    var x: u32 = 4;\n    add2(&x);\n    std.debug.print(\"Result: {d}\\n\", .{x});\n}\n```\n:::\n\n\n```\nResult: 6\n```\n\n\nEven in this code example above, the `x` argument is still immutable. Which means that the pointer itself is immutable.\nTherefore, you cannot change the memory address that it points to. However, you can dereference the pointer\nto access the value that it points to, and also, to change this value, if you need to.\n\n\n\n\n\n## Structs and OOP {#sec-structs-and-oop}\n\nZig is a language more closely related to C (which is a procedural language),\nthan it is to C++ or Java (which are object-oriented languages). Because of that, you do not\nhave advanced OOP (Object-Oriented Programming) patterns available in Zig, such as classes, interfaces or\nclass inheritance. Nonetheless, OOP in Zig is still possible by using struct definitions.\n\nWith struct definitions, you can create (or define) a new data type in Zig. These struct definitions work the same way as they work in C.\nYou give a name to this new struct (or, to this new data type you are creating), then, you list the data members of this new struct. You can\nalso register functions inside this struct, and they become the methods of this particular struct (or data type), so that, every object\nthat you create with this new type, will always have these methods available and associated with them.\n\nIn C++, when we create a new class, we normally have a constructor method (or, a constructor function) which\nis used to construct (or, to instantiate) every object of this particular class, and we also have\na destructor method (or a destructor function), which is the function responsible for destroying\nevery object of this class.\n\nIn Zig, we normally declare the constructor and the destructor methods\nof our structs, by declaring an `init()` and a `deinit()` methods inside the struct.\nThis is just a naming convention that you will find across the entire Zig Standard Library.\nSo, in Zig, the `init()` method of a struct is normally the constructor method of the class represented by this struct.\nWhile the `deinit()` method is the method used for destroying an existing instance of that struct.\n\nThe `init()` and `deinit()` methods are both used extensively in Zig code, and you will see both of\nthem being used when we talk about allocators in @sec-allocators.\nBut, as another example, let's build a simple `User` struct to represent a user of some sort of system.\n\nIf you look at the `User` struct below, you can see the `struct` keyword.\nNotice the data members of this struct: `id`, `name` and `email`. Every data member has its\ntype explicitly annotated, with the colon character (`:`) syntax that we described earlier in @sec-root-file.\nBut also notice that every line in the struct body that describes a data member, ends with a comma character (`,`).\nSo every time you declare a data member in your Zig code, always end the line with a comma character, instead\nof ending it with the traditional semicolon character (`;`).\n\nNext, we have registered an `init()` function as a method\nof this `User` struct. This `init()` method is the constructor method that we will use to instantiate\nevery new `User` object. That is why this `init()` function returns a new `User` object as result.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst User = struct {\n    id: u64,\n    name: []const u8,\n    email: []const u8,\n\n    fn init(id: u64,\n            name: []const u8,\n            email: []const u8) User {\n\n        return User {\n            .id = id,\n            .name = name,\n            .email = email\n        };\n    }\n\n    fn print_name(self: User) !void {\n        try stdout.print(\"{s}\\n\", .{self.name});\n    }\n};\n\npub fn main() !void {\n    const u = User.init(1, \"pedro\", \"email@gmail.com\");\n    try u.print_name();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\npedro\n```\n\n\n:::\n:::\n\n\n\n\n### The `pub` keyword\n\nThe `pub` keyword plays an important role in struct declarations, and OOP in Zig.\nIn essence, this keyword is short for \"public\", and it makes an item/component available outside of the\nmodule where this item/component is declared. In other words, if I don't apply the `pub` keyword on\nsomething, it means that this \"something\" is available to be called/used only from within the module\nwhere this \"something\" is declared.\n\nTo demonstrate the effect of this keyword let's focus again on the `User` struct that we have\ndeclared on the previous section. For our example here, let's suppose that this `User` struct is declared inside\na Zig module named `user.zig`. If I don't use the `pub` keyword on the `User` struct, it means that I can create\nan `User` object, and call it's methods (`print_name()` and `init()`) only from within the module where the `User`\nstruct is declared, which in this case is the `user.zig` module.\n\nThis is why the previous code example works fine. Because we declare and also use the `User` struct\ninside the same module. But problems start to arise when we try to import and call/use this struct\nfrom another module. For example, if I create a new module called `register.zig`, and import the `user.zig`\nmodule into it, and try to annotate any variable with the `User` type, I get an error from the compiler.\n\n```zig\n// register.zig\nconst user = @import(\"user.zig\");\npub fn main() !void {\n    const u: user.User = undefined;\n    _ = u;\n}\n```\n\n```\nregister.zig:3:18: error: 'User' is not marked 'pub'\n    const u: user.User = undefined;\n             ~~~~^~~~~\nuser.zig:3:1: note: declared here\nconst User = struct {\n^~~~~\n```\n\nTherefore, if you want to use something outside of the module where this \"something\" is declared,\nyou have to mark it with the `pub` keyword. This \"something\" can be a module,\na struct, a function, an object, etc.\n\nFor our example here, if we go back to the `user.zig` module, and add the `pub` keyword\nto the `User` struct declaration, then, I can successfully compile the `register.zig` module.\n\n```zig\n// user.zig\n// Added the `pub` keyword to `User`\npub const User = struct {\n// ...\n```\n\n```zig\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n    const u: user.User = undefined;\n    _ = u;\n}\n```\n\n\nNow, what do you think it will happen if I try to actually call from `register.zig` any of the methods\nof the `User` struct? For example, if I try to call the `init()` method? The answer is: I get a similar error message,\nwarning me that the `init()` method is not marked as `pub`, as you can see below:\n\n```zig\nconst user = @import(\"user.zig\");\npub fn main() !void {\n    const u: user.User = user.User.init(\n        1, \"pedro\", \"email@gmail.com\"\n    );\n    _ = u;\n}\n```\n\n```\nregister.zig:3:35: error: 'init' is not marked 'pub'\n    const u: user.User = user.User.init(\n                         ~~~~~~~~~^~~~~\nuser.zig:8:5: note: declared here\n    fn init(id: u64,\n    ^~~~~~~\n```\n\nThus, just because we have applied the `pub` keyword on the struct declaration,\nthis does not make the methods of that struct public as well. If we want to use\nany method from a struct (such as the `init()` method) outside of the module\nwhere this struct is declared, we have to mark this method with the `pub` keyword\nas well.\n\nGoing back to the `user.zig` module, and marking both the `init()` and `print_name()`\nmethods with the `pub` keyword, makes them both available to the outside world, and,\nas consequence, makes the previous code example work.\n\n\n```zig\n// user.zig\n// Added the `pub` keyword to `User.init`\n    pub fn init(\n// ...\n// Added the `pub` keyword to `User.print_name`\n    pub fn print_name(self: User) !void {\n// ...\n```\n\n```zig\n// register.zig\n// This works fine now!\nconst user = @import(\"user.zig\");\npub fn main() !void {\n    const u: user.User = user.User.init(\n        1, \"pedro\", \"email@gmail.com\"\n    );\n    _ = u;\n}\n```\n\n\n### Anonymous struct literals {#sec-anonymous-struct-literals}\n\nYou can declare a struct object as a literal value. When we do that, we normally specify the\ndata type of this struct literal by writing its data type just before the opening curly brace.\nFor example, I could write a struct literal value of the type `User` that we have defined\nin the previous section like this:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst eu = User {\n    .id = 1,\n    .name = \"Pedro\",\n    .email = \"someemail@gmail.com\"\n};\n_ = eu;\n```\n:::\n\n\nHowever, in Zig, we can also write an anonymous struct literal. That is, you can write a\nstruct literal, but not specify explicitly the type of this particular struct.\nAn anonymous struct is written by using the syntax `.{}`. So, we essentially\nreplaced the explicit type of the struct literal with a dot character (`.`).\n\nAs we described in @sec-type-inference, when you put a dot before a struct literal,\nthe type of this struct literal is automatically inferred by the `zig` compiler.\nIn essence, the `zig` compiler will look for some hint of what is the type of that struct.\nThis hint can be the type annotation of a function argument,\nor the return type annotation of the function that you are using, or the type annotation\nof an existing object.\nIf the compiler does find such type annotation, it will use this\ntype in your literal struct.\n\nAnonymous structs are very commonly used as inputs to function arguments in Zig.\nOne example that you have seen already constantly, is the `print()`\nfunction from the `stdout` object.\nThis function takes two arguments.\nThe first argument, is a template string, which should\ncontain string format specifiers in it, which tells how the values provided\nin the second argument should be printed into the message.\n\nWhile the second argument is a struct literal that lists the values\nto be printed into the template message specified in the first argument.\nYou normally want to use an anonymous struct literal here, so that the\n`zig` compiler do the job of specifying the type of this particular\nanonymous struct for you.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n    const stdout = std.io.getStdOut().writer();\n    try stdout.print(\"Hello, {s}!\\n\", .{\"world\"});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nHello, world!\n```\n\n\n:::\n:::\n\n\n\n\n### Struct declarations must be constant\n\nTypes in Zig must be `const` or `comptime` (we are going to talk more about comptime in @sec-comptime).\nWhat this means is that you cannot create a new data type, and mark it as variable with the `var` keyword.\nSo struct declarations are always constant. You cannot declare a new struct type using the `var` keyword.\nIt must be `const`.\n\nIn the `Vec3` example below, this declaration is allowed because I'm using the `const` keyword\nto declare this new data type.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Vec3 = struct {\n    x: f64,\n    y: f64,\n    z: f64,\n};\n```\n:::\n\n\n\n### The `self` method argument {#sec-self-arg}\n\nIn every language that have OOP, when we declare a method of some class or struct, we\nusually declare this method as a function that has a `self` argument.\nThis `self` argument is the reference to the object itself from which the method\nis being called from.\n\nIt's not mandatory to use this `self` argument. But why would you not use this `self` argument?\nThere is no reason to not use it. Because the only way to get access to the data stored in the\ndata members of your struct is to access them through this `self` argument.\nIf you don't need to use the data in the data members of your struct inside your method, you very likely don't need\na method. You can just declare this logic as a simple function, outside of your\nstruct declaration.\n\n\nTake the `Vec3` struct below. Inside this `Vec3` struct we declared a method named `distance()`.\nThis method calculates the distance between two `Vec3` objects, by following the distance\nformula in euclidean space. Notice that this `distance()` method takes two `Vec3` objects\nas input, `self` and `other`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n    x: f64,\n    y: f64,\n    z: f64,\n\n    pub fn distance(self: Vec3, other: Vec3) f64 {\n        const xd = m.pow(f64, self.x - other.x, 2.0);\n        const yd = m.pow(f64, self.y - other.y, 2.0);\n        const zd = m.pow(f64, self.z - other.z, 2.0);\n        return m.sqrt(xd + yd + zd);\n    }\n};\n```\n:::\n\n\n\nThe `self` argument corresponds to the `Vec3` object from which this `distance()` method\nis being called from. While the `other` is a separate `Vec3` object that is given as input\nto this method. In the example below, the `self` argument corresponds to the object\n`v1`, because the `distance()` method is being called from the `v1` object,\nwhile the `other` argument corresponds to the object `v2`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = Vec3 {\n    .x = 4.2, .y = 2.4, .z = 0.9\n};\nconst v2 = Vec3 {\n    .x = 5.1, .y = 5.6, .z = 1.6\n};\n\nstd.debug.print(\n    \"Distance: {d}\\n\",\n    .{v1.distance(v2)}\n);\n```\n:::\n\n\n```\nDistance: 3.3970575502926055\n```\n\n\n\n### About the struct state\n\nSometimes you don't need to care about the state of your struct object. Sometimes, you just need\nto instantiate and use the objects, without altering their state. You can notice that when you have methods\ninside your struct declaration that might use the values that are present in the data members, but they\ndo not alter the values in these data members of the struct in anyway.\n\nThe `Vec3` struct that was presented in @sec-self-arg is an example of that.\nThis struct have a single method named `distance()`, and this method does use the values\npresent in all three data members of the struct (`x`, `y` and `z`). But at the same time,\nthis method does not change the values of these data members at any point.\n\nAs a result of that, when we create `Vec3` objects we usually create them as\nconstant objects, like the `v1` and `v2` objects presented in @sec-self-arg.\nWe can create them as variable objects with the `var` keyword,\nif we want to. But because the methods of this `Vec3` struct do not change\nthe state of the objects in any point, it's unnecessary to mark them\nas variable objects.\n\nBut why? Why am I talking about this here? It's because the `self` argument\nin the methods are affected depending on whether the\nmethods present in a struct change or don't change the state of the object itself.\nMore specifically, when you have a method in a struct that changes the state\nof the object (i.e., changes the value of a data member), the `self` argument\nin this method must be annotated in a different manner.\n\nAs I described in @sec-self-arg, the `self` argument in methods of\na struct is the argument that receives as input the object from which the method\nwas called from. We usually annotate this argument in the methods by writing `self`,\nfollowed by the colon character (`:`), and the data type of the struct to which\nthe method belongs to (e.g. `User`, `Vec3`, etc.).\n\nIf we take the `Vec3` struct that we defined in the previous section as an example,\nwe can see in the `distance()` method that this `self` argument is annotated as\n`self: Vec3`. Because the state of the `Vec3` object is never altered by this\nmethod.\n\nBut what if we do have a method that alters the state of the object, by altering the\nvalues of its data members, how should we annotate `self` in this instance? The answer is:\n\"we should annotate `self` as a pointer of `x`, instead of just `x`\".\nIn other words, you should annotate `self` as `self: *x`, instead of annotating it\nas `self: x`.\n\nIf we create a new method inside the `Vec3` object that, for example, expands the\nvector by multiplying its coordinates by a factor of two, then, we need to follow\nthis rule specified in the previous paragraph. The code example below demonstrates\nthis idea:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst m = std.math;\nconst Vec3 = struct {\n    x: f64,\n    y: f64,\n    z: f64,\n\n    pub fn distance(self: Vec3, other: Vec3) f64 {\n        const xd = m.pow(f64, self.x - other.x, 2.0);\n        const yd = m.pow(f64, self.y - other.y, 2.0);\n        const zd = m.pow(f64, self.z - other.z, 2.0);\n        return m.sqrt(xd + yd + zd);\n    }\n\n    pub fn twice(self: *Vec3) void {\n        self.x = self.x * 2.0;\n        self.y = self.y * 2.0;\n        self.z = self.z * 2.0;\n    }\n};\n```\n:::\n\n\nNotice in the code example above that we have added a new method\nto our `Vec3` struct named `twice()`. This method doubles the\ncoordinate values of our vector object. In the\ncase of the `twice()` method, we annotated the `self` argument as `*Vec3`,\nindicating that this argument receives a pointer (or a reference, if you prefer to call it this way)\nto a `Vec3` object as input.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar v3 = Vec3 {\n    .x = 4.2, .y = 2.4, .z = 0.9\n};\nv3.twice();\nstd.debug.print(\"Doubled: {d}\\n\", .{v3.x});\n```\n:::\n\n\n```\nDoubled: 8.4\n```\n\n\n\nNow, if you change the `self` argument in this `twice()` method to `self: Vec3`, like in the\n`distance()` method, you will get the compiler error exposed below as result. Notice that this\nerror message is showing a line from the `twice()` method body,\nindicating that you cannot alter the value of the `x` data member.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// If we change the function signature of double to:\n    pub fn twice(self: Vec3) void {\n```\n:::\n\n\n```\nt.zig:16:13: error: cannot assign to constant\n        self.x = self.x * 2.0;\n        ~~~~^~\n```\n\nThis error message indicates that the `x` data member belongs to a constant object,\nand, because of that, it cannot be changed. Ultimately, this error message\nis telling us that the `self` argument is constant.\n\nIf you take some time, and think hard about this error message, you will understand it.\nYou already have the tools to understand why we are getting this error message.\nWe have talked about it already in @sec-fun-pars.\nSo remember, every function argument is immutable in Zig, and `self`\nis no exception to this rule.\n\nIn this example, we marked the `v3` object as a variable object.\nBut this does not matter. Because it's not about the input object, it's about\nthe function argument.\n\nThe problem begins when we try to alter the value of `self` directly, which is a function argument,\nand, every function argument is immutable by default. You may ask yourself how can we overcome\nthis barrier, and once again, the solution was also discussed in @sec-fun-pars.\nWe overcome this barrier, by explicitly marking the `self` argument as a pointer.\n\n\n::: {.callout-note}\nIf a method of your `x` struct alters the state of the object, by\nchanging the value of any data member, then, remember to use `self: *x`,\ninstead of `self: x` in the function signature of this method.\n:::\n\n\nYou could also interpret the content discussed in this section as:\n\"if you need to alter the state of your `x` struct object in one of its methods,\nyou must explicitly pass the `x` struct object by reference to the `self` argument of this method\".\n\n\n\n## Type inference {#sec-type-inference}\n\nZig is a strongly typed language. But, there are some situations\nwhere you don't have to explicitly write the type of every single object in your source code,\nas you would expect from a traditional strongly typed language, such as C and C++.\n\nIn some situations, the `zig` compiler can use type inference to solve the data types for you, easing some of\nthe burden that you carry as a developer.\nThe most common way this happens is through function arguments that receive struct objects\nas input.\n\nIn general, type inference in Zig is done by using the dot character (`.`).\nEverytime you see a dot character written before a struct literal, or before an enum value, or something like that,\nyou know that this dot character is playing a special part in this place. More specifically, it's\ntelling the `zig` compiler something along the lines of: \"Hey! Can you infer the type of this\nvalue for me? Please!\". In other words, this dot character is playing a similar role as the `auto` keyword in C++.\n\nI gave you some examples of this in @sec-anonymous-struct-literals, where we used anonymous struct literals.\nAnonymous struct literals are, struct literals that use type inference to\ninfer the exact type of this particular struct literal.\nThis type inference is done by looking for some minimal hint of the correct data type to be used.\nYou could say that the `zig` compiler looks for any neighbouring type annotation that might tell it\nwhat the correct type would be.\n\nAnother common place where we use type inference in Zig is at switch statements (which we talked about in @sec-switch).\nI also gave some other examples of type inference in @sec-switch, where we were inferring the data types of enum values listed inside\nof switch statements (e.g. `.DE`).\nBut as another example, take a look at this `fence()` function reproduced below,\nwhich comes from the [`atomic.zig` module](https://github.com/ziglang/zig/blob/master/lib/std/atomic.zig)[^fence-fn]\nof the Zig Standard Library.\n\n[^fence-fn]: .\n\nThere are a lot of things in this function that we haven't talked about yet, such as:\nwhat `comptime` means? `inline`? `extern`?\nLet's just ignore all of these things, and focus solely on the switch statement\nthat is inside this function.\n\nWe can see that this switch statement uses the `order` object as input. This `order`\nobject is one of the inputs of this `fence()` function, and we can see in the type annotation,\nthat this object is of type `AtomicOrder`. We can also see a bunch of values inside the\nswitch statements that begin with a dot character, such as `.release` and `.acquire`.\n\nBecause these weird values contain a dot character before them, we are asking the `zig`\ncompiler to infer the types of these values inside the switch statement. Then, the `zig`\ncompiler is looking into the current context where these values are being used, and trying\nto infer the types of these values.\n\nSince they are being used inside a switch statement, the `zig` compiler looks into the type\nof the input object given to the switch statement, which is the `order` object in this case.\nBecause this object have type `AtomicOrder`, the `zig` compiler infers that these values\nare data members from this type `AtomicOrder`.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub inline fn fence(self: *Self, comptime order: AtomicOrder) void {\n    // many lines of code ...\n    if (builtin.sanitize_thread) {\n        const tsan = struct {\n            extern \"c\" fn __tsan_acquire(addr: *anyopaque) void;\n            extern \"c\" fn __tsan_release(addr: *anyopaque) void;\n        };\n\n        const addr: *anyopaque = self;\n        return switch (order) {\n            .unordered, .monotonic => @compileError(\n                @tagName(order)\n                ++ \" only applies to atomic loads and stores\"\n            ),\n            .acquire => tsan.__tsan_acquire(addr),\n            .release => tsan.__tsan_release(addr),\n            .acq_rel, .seq_cst => {\n                tsan.__tsan_acquire(addr);\n                tsan.__tsan_release(addr);\n            },\n        };\n    }\n\n    return @fence(order);\n}\n```\n:::\n\n\nThis is how basic type inference is done in Zig. If we didn't use the dot character before\nthe values inside this switch statement, then, we would be forced to explicitly write\nthe data types of these values. For example, instead of writing `.release` we would have to\nwrite `AtomicOrder.release`. We would have to do this for every single value\nin this switch statement, and this is a lot of work. That is why type inference\nis commonly used on switch statements in Zig.\n\n\n\n## Type casting {#sec-type-cast}\n\nIn this section, I want to discuss type casting (or, type conversion) with you.\nWe use type casting when we have an object of type \"x\", and we want to convert\nit into an object of type \"y\", i.e., we want to change the data type of the object.\n\nMost languages have a formal way to perform type casting. In Rust for example, we normally\nuse the keyword `as`, and in C, we normally use the type casting syntax, e.g. `(int) x`.\nIn Zig, we use the `@as()` built-in function to cast an object of type \"x\", into\nan object of type \"y\".\n\nThis `@as()` function is the preferred way to perform type conversion (or type casting)\nin Zig. Because it's explicit, and, it also performs the casting only if it\nis unambiguous and safe. To use this function, you just provide the target data type\nin the first argument, and, the object that you want cast as the second argument.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n    const x: usize = 500;\n    const y = @as(u32, x);\n    try expect(@TypeOf(y) == u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file26f81ac33a52.test_0...OKAll 1 tests passed\n  d.\n```\n\n\n:::\n:::\n\n\nThis is the general way to perform type casting in Zig. But remember, `@as()` works only when casting\nis unambiguous and safe. There are many situations where these assumptions do not hold. For example,\n\nwhen casting an integer value into a float value, or vice-versa, it's not clear to the compiler\nhow to perform this conversion safely.\n\nTherefore, we need to use specialized \"casting functions\" in such situations.\nFor example, if you want to cast an integer value into a float value, then, you\nshould use the `@floatFromInt()` function. In the inverse scenario, you should use\nthe `@intFromFloat()` function.\n\nIn these functions, you just provide the object that you want to\ncast as input. Then, the target data type of the \"type casting operation\" is determined by\nthe type annotation of the object where you are saving the results.\nIn the example below, we are casting the object `x` into a value of type `f32`,\nbecause the object `y`, which is where we are saving the results, is annotated\nas an object of type `f32`.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n    const x: usize = 565;\n    const y: f32 = @floatFromInt(x);\n    try expect(@TypeOf(y) == f32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file26f81f277e9b.test_0...OKAll 1 tests passed\n  d.\n```\n\n\n:::\n:::\n\n\nAnother built-in function that is very useful when performing type casting operations is `@ptrCast()`.\nIn essence, we use the `@as()` built-in function when we want to explicit convert (or cast) a Zig value/object\nfrom a type \"x\" to a type \"y\", etc. However, pointers (we are going to discuss pointers\nin more depth in @sec-pointer) are a special type of object in Zig,\ni.e., they are treated differently from \"normal objects\".\n\nEverytime a pointer is involved in some \"type casting operation\" in Zig, the `@ptrCast()` function is used.\nThis function works similarly to `@floatFromInt()`.\nYou just provide the pointer object that you want to cast as input to this function, and the\ntarget data type is, once again, determined by the type annotation of the object where the results are being\nstored.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest {\n    const bytes align(@alignOf(u32)) = [_]u8{\n        0x12, 0x12, 0x12, 0x12\n    };\n    const u32_ptr: *const u32 = @ptrCast(&bytes);\n    try expect(@TypeOf(u32_ptr) == *const u32);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file26f843ae7baf.test_0...OKAll 1 tests passed\n  d.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n## Modules\n\nWe already talked about what modules are, and also, how to import other modules into\nyour current module via *import statements*. Every Zig module (i.e., a `.zig` file) that you write in your project\nis internally stored as a struct object. Take the line exposed below as an example. In this line we are importing the\nZig Standard Library into our current module.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\n```\n:::\n\n\nWhen we want to access the functions and objects from the standard library, we\nare basically accessing the data members of the struct stored in the `std`\nobject. That is why we use the same syntax that we use in normal structs, with the dot operator (`.`)\nto access the data members and methods of the struct.\n\nWhen this \"import statement\" gets executed, the result of this expression is a struct\nobject that contains the Zig Standard Library modules, global variables, functions, etc.\nAnd this struct object gets saved (or stored) inside the constant object named `std`.\n\n\nTake the [`thread_pool.zig` module from the project `zap`](https://github.com/kprotty/zap/blob/blog/src/thread_pool.zig)[^thread]\nas an example. This module is written as if it was\na big struct. That is why we have a top-level and public `init()` method\nwritten in this module. The idea is that all top-level functions written in this\nmodule are methods from the struct, and all top-level objects and struct declarations\nare data members of this struct. The module is the struct itself.\n\n[^thread]: \n\n\nSo you would import and use this module by doing something like this:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst ThreadPool = @import(\"thread_pool.zig\");\nconst num_cpus = std.Thread.getCpuCount()\n    catch @panic(\"failed to get cpu core count\");\nconst num_threads = std.math.cast(u16, num_cpus)\n    catch std.math.maxInt(u16);\nconst pool = ThreadPool.init(\n    .{ .max_threads = num_threads }\n);\n```\n:::\n",
         "supporting": [],
         "filters": [
           "rmarkdown/pagebreak.lua"
    diff --git a/_freeze/Chapters/03-unittests/execute-results/epub.json b/_freeze/Chapters/03-unittests/execute-results/epub.json
    deleted file mode 100644
    index 8a67fd57..00000000
    --- a/_freeze/Chapters/03-unittests/execute-results/epub.json
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -{
    -  "hash": "555cc5c67a26414e89a3511dba578c1d",
    -  "result": {
    -    "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n# Unit tests {#sec-unittests}\n\nIn this chapter, I want to dive in on how unit tests are done in\nZig. We are going to talk about what is the testing workflow in Zig, and\nalso, about the `test` command from the `zig` compiler.\n\n\n## Introducing the `test` block\n\nIn Zig, unit tests are written inside a `test` declaration, or, how I prefer to call it, inside a `test` block.\nEvery `test` block is written by using the keyword `test`.\nYou can optionally use a string literal to write a label, which is responsible for identifying\nthe specific group of unit tests that you are writing inside this specific `test` block.\n\nIn the example below, we are testing if the sum of two objects (`a` and `b`)\nis equal to 4. The `expect()` function from the Zig Standard Library\nis a function that receives a logical test as input. If this logical test\nresults in `true`, then, the test passes. But if it results\nin `false`, then, the test fails.\n\nYou can write any Zig code you want inside a `test` block.\nPart of this code might be some necessary commands to setup your testing\nenvironment, or just initializing some objects that you need to use\nin your unit tests.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest \"testing simple sum\" {\n    const a: u8 = 2;\n    const b: u8 = 2;\n    try expect((a + b) == 4);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3d7d5828b2d3.test.testing simple sum...OKA\n  All 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\nYou can have multiple `test` blocks written on the same Zig module.\nAlso, you can mix `test` blocks with your source code, with no problems\nor consequences. If you mix `test` blocks with your normal source code,\nwhen you execute the `build`, `build-exe`, `build-obj` or `build-lib` commands from the\n`zig` compiler that we exposed in @sec-compile-code, these `test` blocks are automatically\nignored by the compiler.\n\nIn other words, the `zig` compiler builds and execute your unit tests only\nwhen you ask it to. By default, the compiler always ignore `test`\nblocks written in your Zig modules. The compiler normally checks only if\nthere are any syntax errors in these `test` blocks.\n\nIf you take a look at the source code for most of the files present in the\nZig Standard Library[^zig-std-lib], you can see that the `test` blocks\nare written together with the normal source code of the library.\nYou can see this for example, at the [`array_list` module](https://github.com/ziglang/zig/blob/master/lib/std/array_list.zig)[^zig-array].\nSo, the standard that the Zig developers decided to adopt\nis to keep their unit tests together with the source code\nof the functionality that they are testing.\n\nEach programmer might have a different opinion on this.\nSome of them might prefer to keep unit tests separate from the actual\nsource code of their application. If that is your case, you can\nsimply create a separate `tests` folder in your project, and\nstart writing Zig modules that contains only unit tests (as you would normally do\non a Python project with `pytest`, for example), and everything will work fine.\nIt boils down to which is your preference here.\n\n[^zig-std-lib]: \n[^zig-array]: \n\n\n## How to run your tests\n\nIf the `zig` compiler ignores any `test` block by default, how can\nyou compile and run your unit tests? The answer is the `test` command from\nthe `zig` compiler. By running the `zig test` command, the compiler will\nfind every instance of a `test` block in your Zig modules, and, it will\ncompile and run the unit tests that you wrote.\n\n\n```bash\nzig test simple_sum.zig\n```\n\n```\n1/1 simple_sum.test.testing simple sum... OK\nAll 1 tests passed.\n```\n\n\n## Testing memory allocations\n\nOne of the advantages of Zig is that it offers great tools\nthat help us, programmers, to avoid (but also detect) memory problems, such as\nmemory leaks and double-frees. The `defer` keyword\nis especially helpful in this regard.\n\nWhen developing your source code, you, the programmer, are responsible for making\nsure that your code does not produce such problems. However,\nyou can also use a special type of an allocator object in Zig\nthat is capable of automatically detecting such problems for you.\nThis is the `std.testing.allocator` object.\nThis allocator object offers some basic memory safety detection\nfeatures, which are capable of detecting memory leaks.\n\nAs we described in @sec-heap, to allocate memory on the heap, you need\nto use an allocator object, and your functions that use these objects to allocate memory\non the heap, should receive an allocator object as one of its inputs.\nEvery memory on the heap that you allocate using these allocator objects,\nmust also be freed using this same allocator object.\n\nSo, if you want to test the memory allocations performed by your functions,\nand make sure that you don't have problems in these allocations, you can simply\nwrite unit tests for these functions, where you provide the\n`std.testing.allocator` object as input to these functions.\n\nLook at the example below, where I'm defining a function that clearly causes\na memory leak. Because we allocate memory, but, at the same time,\nwe do not free this allocated memory at any point. So, when the function\nreturns, we lose the reference to the `buffer` object, which contains\nthe allocated memory, and, as a result, we can no longer free this memory.\n\nNotice that, inside a `test` block I execute this function with\nthe `std.testing.allocator`. The allocator object was capable\nof looking deeper in our program, and detecting the memory leak. As a result,\nthis allocator object returns an error message of \"memory leaked\", and also,\na stack trace showing the exact point where the memory was leaked.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nfn some_memory_leak(allocator: Allocator) !void {\n    const buffer = try allocator.alloc(u32, 10);\n    _ = buffer;\n    // Return without freeing the\n    // allocated memory\n}\n\ntest \"memory leak\" {\n    const allocator = std.testing.allocator;\n    try some_memory_leak(allocator);\n}\n```\n:::\n\n\n\n```\nTest [1/1] leak_memory.test.memory leak...\n    [gpa] (err): memory address 0x7c1fddf39000 leaked:\n./ZigExamples/debugging/leak_memory.zig:4:39: 0x10395f2\n    const buffer = try allocator.alloc(u32, 10);\n                                      ^\n./ZigExamples/debugging/leak_memory.zig:12:25: 0x10398ea\n    try some_memory_leak(allocator);\n\n... more stack trace\n```\n\n\n## Testing errors\n\nOne common style of unit tests are those that look for\nspecific errors in your functions. In other words, you write\na unit test that tries to assert if a specific function call\nreturns any error, or a specific type of error.\n\nIn C++ you would normally write this style of unit tests using, for example,\nthe functions `REQUIRE_THROWS()` or `CHECK_THROWS()` from the [`Catch2` test framework](https://github.com/catchorg/Catch2/tree/devel)[^catch2].\nIn the case of a Python project, you would probably use the\n[`raises()` function from `pytest`](https://docs.pytest.org/en/7.1.x/reference/reference.html#pytest-raises)[^pytest].\nWhile in Rust, you would probably use `assert_eq!()` in conjunction with `Err()`.\n\n[^pytest]: \n[^catch2]: \n\n\nBut in Zig, we use the `expectError()` function, from the `std.testing` module.\nWith this function, you can test if a specific function call returns the exact\ntype of error that you expect it to return. To use this function, you first write\n`try expectError()`. Then, on the first argument, you provide the type of error that you\nare expecting from the function call. Then, on the second argument, you write\nthe function call that you expect to fail.\n\nThe code example below demonstrates such type of unit test in Zig.\nNotice that, inside the function `alloc_error()` we are allocating\n100 bytes of memory, or, an array of 100 elements, for the object `ibuffer`. However,\nin the `test` block, we are using the `FixedBufferAllocator()`\nallocator object, which is limited to 10 bytes of space, because\nthe object `buffer`, which we provided to the allocator object,\nhave only 10 bytes of space.\n\nThat is why, the `alloc_error()` function raises an `OutOfMemory` error\non this case.\nBecause this function is trying to allocate more space than the allocator\nobject allows.\nSo, in essence, we are testing for a specific type of error,\nwhich is `OutOfMemory`. If the `alloc_error()` function returns any other type of error,\nthen, the `expectError()` function would make the entire test fail.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst expectError = std.testing.expectError;\nfn alloc_error(allocator: Allocator) !void {\n    var ibuffer = try allocator.alloc(u8, 100);\n    defer allocator.free(ibuffer);\n    ibuffer[0] = 2;\n}\n\ntest \"testing error\" {\n    var buffer: [10]u8 = undefined;\n    var fba = std.heap.FixedBufferAllocator.init(&buffer);\n    const allocator = fba.allocator();\n    try expectError(error.OutOfMemory, alloc_error(allocator));\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3d7d15bc8ea0.test.testing error...OKAll 1 \n   tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n## Testing simple equalities\n\nIn Zig, there are some different ways you can test for an equality.\nYou already saw that we can use `expect()` with the logical operator `==`\nto essentially reproduce an equality test. But we also have\nsome other helper functions that you should know about, especially\n`expectEqual()`, `expectEqualSlices()` and `expectEqualStrings()`.\n\n\nThe `expectEqual()` function, as the name suggests, is a classic\ntest equality function. It receives two objects as input. The first\nobject is the value that you expect to be in the second object.\nWhile second object is the object you have, or, the object that your application\nproduced as result. So, with `expectEqual()` you are essentially\ntesting if the values stored inside these two objects\nare equal or not.\n\nYou can see in the example below that, the test performed by\n`expectEqual()` failed. Because the objects `v1` and `v2` contain\ndifferent values in them.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"values are equal?\" {\n    const v1 = 15;\n    const v2 = 18;\n    try std.testing.expectEqual(v1, v2);\n}\n```\n:::\n\n\n\n```\n1/1 ve.test.values are equal?...\n    expected 15, found 18\n    FAIL (TestExpectedEqual)\nve.zig:5:5: test.values are equal? (test)\n    try std.testing.expectEqual(v1, v2);\n    ^\n0 passed; 0 skipped; 1 failed.\n```\n\n\nAlthough useful, the `expectEqual()` function does not work with arrays.\nFor testing if two arrays are equal, you should use the `expectEqualSlices()`\nfunction instead. This function have three arguments. First, you provide\nthe data type contained in both arrays that you are trying to compare.\nWhile the second and third arguments corresponds to the array objects that you want to compare.\n\nIn the example below, we are using this function to test if two array\nobjects (`array1` and `array2`) are equal or not. Since they\nare in fact equal, the unit test passed with no errors.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"arrays are equal?\" {\n    const array1 = [3]u32{1, 2, 3};\n    const array2 = [3]u32{1, 2, 3};\n    try std.testing.expectEqualSlices(\n        u32, &array1, &array2\n    );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3d7d7d8ccdbb.test.arrays are equal?...OKAl\n  ll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\nAt last, you might also want to use the `expectEqualStrings()` function.\nAs the name suggests, you can use this function to test if two strings\nare equal or not. Just provide the two string objects that you want to compare,\nas inputs to the function.\n\nIf the function finds any existing differences between the two strings,\nthen, the function will raise an error, and also, print an error message\nthat shows the exact difference between the two string objects provided,\nas the example below demonstrates:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"strings are equal?\" {\n    const str1 = \"hello, world!\";\n    const str2 = \"Hello, world!\";\n    try std.testing.expectEqualStrings(\n        str1, str2\n    );\n}\n```\n:::\n\n\n\n```\n1/1 t.test.strings are equal?...\n====== expected this output: =========\nhello, world!␃\n======== instead found this: =========\nHello, world!␃\n======================================\nFirst difference occurs on line 1:\nexpected:\nhello, world!\n^ ('\\x68')\nfound:\nHello, world!\n^ ('\\x48')\n```\n",
    -    "supporting": [
    -      "03-unittests_files"
    -    ],
    -    "filters": [
    -      "rmarkdown/pagebreak.lua"
    -    ],
    -    "includes": {},
    -    "engineDependencies": {
    -      "knitr": [
    -        "{\"type\":\"list\",\"attributes\":{},\"value\":[]}"
    -      ]
    -    },
    -    "preserve": null,
    -    "postProcess": false
    -  }
    -}
    \ No newline at end of file
    diff --git a/_freeze/Chapters/03-unittests/execute-results/html.json b/_freeze/Chapters/03-unittests/execute-results/html.json
    index 7e5990dc..a6dbf076 100644
    --- a/_freeze/Chapters/03-unittests/execute-results/html.json
    +++ b/_freeze/Chapters/03-unittests/execute-results/html.json
    @@ -2,10 +2,8 @@
       "hash": "555cc5c67a26414e89a3511dba578c1d",
       "result": {
         "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Unit tests {#sec-unittests}\n\nIn this chapter, I want to dive in on how unit tests are done in\nZig. We are going to talk about what is the testing workflow in Zig, and\nalso, about the `test` command from the `zig` compiler.\n\n\n## Introducing the `test` block\n\nIn Zig, unit tests are written inside a `test` declaration, or, how I prefer to call it, inside a `test` block.\nEvery `test` block is written by using the keyword `test`.\nYou can optionally use a string literal to write a label, which is responsible for identifying\nthe specific group of unit tests that you are writing inside this specific `test` block.\n\nIn the example below, we are testing if the sum of two objects (`a` and `b`)\nis equal to 4. The `expect()` function from the Zig Standard Library\nis a function that receives a logical test as input. If this logical test\nresults in `true`, then, the test passes. But if it results\nin `false`, then, the test fails.\n\nYou can write any Zig code you want inside a `test` block.\nPart of this code might be some necessary commands to setup your testing\nenvironment, or just initializing some objects that you need to use\nin your unit tests.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest \"testing simple sum\" {\n    const a: u8 = 2;\n    const b: u8 = 2;\n    try expect((a + b) == 4);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file81c21dbf264e.test.testing simple sum...OKA\n  All 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\nYou can have multiple `test` blocks written on the same Zig module.\nAlso, you can mix `test` blocks with your source code, with no problems\nor consequences. If you mix `test` blocks with your normal source code,\nwhen you execute the `build`, `build-exe`, `build-obj` or `build-lib` commands from the\n`zig` compiler that we exposed in @sec-compile-code, these `test` blocks are automatically\nignored by the compiler.\n\nIn other words, the `zig` compiler builds and execute your unit tests only\nwhen you ask it to. By default, the compiler always ignore `test`\nblocks written in your Zig modules. The compiler normally checks only if\nthere are any syntax errors in these `test` blocks.\n\nIf you take a look at the source code for most of the files present in the\nZig Standard Library[^zig-std-lib], you can see that the `test` blocks\nare written together with the normal source code of the library.\nYou can see this for example, at the [`array_list` module](https://github.com/ziglang/zig/blob/master/lib/std/array_list.zig)[^zig-array].\nSo, the standard that the Zig developers decided to adopt\nis to keep their unit tests together with the source code\nof the functionality that they are testing.\n\nEach programmer might have a different opinion on this.\nSome of them might prefer to keep unit tests separate from the actual\nsource code of their application. If that is your case, you can\nsimply create a separate `tests` folder in your project, and\nstart writing Zig modules that contains only unit tests (as you would normally do\non a Python project with `pytest`, for example), and everything will work fine.\nIt boils down to which is your preference here.\n\n[^zig-std-lib]: \n[^zig-array]: \n\n\n## How to run your tests\n\nIf the `zig` compiler ignores any `test` block by default, how can\nyou compile and run your unit tests? The answer is the `test` command from\nthe `zig` compiler. By running the `zig test` command, the compiler will\nfind every instance of a `test` block in your Zig modules, and, it will\ncompile and run the unit tests that you wrote.\n\n\n```bash\nzig test simple_sum.zig\n```\n\n```\n1/1 simple_sum.test.testing simple sum... OK\nAll 1 tests passed.\n```\n\n\n## Testing memory allocations\n\nOne of the advantages of Zig is that it offers great tools\nthat help us, programmers, to avoid (but also detect) memory problems, such as\nmemory leaks and double-frees. The `defer` keyword\nis especially helpful in this regard.\n\nWhen developing your source code, you, the programmer, are responsible for making\nsure that your code does not produce such problems. However,\nyou can also use a special type of an allocator object in Zig\nthat is capable of automatically detecting such problems for you.\nThis is the `std.testing.allocator` object.\nThis allocator object offers some basic memory safety detection\nfeatures, which are capable of detecting memory leaks.\n\nAs we described in @sec-heap, to allocate memory on the heap, you need\nto use an allocator object, and your functions that use these objects to allocate memory\non the heap, should receive an allocator object as one of its inputs.\nEvery memory on the heap that you allocate using these allocator objects,\nmust also be freed using this same allocator object.\n\nSo, if you want to test the memory allocations performed by your functions,\nand make sure that you don't have problems in these allocations, you can simply\nwrite unit tests for these functions, where you provide the\n`std.testing.allocator` object as input to these functions.\n\nLook at the example below, where I'm defining a function that clearly causes\na memory leak. Because we allocate memory, but, at the same time,\nwe do not free this allocated memory at any point. So, when the function\nreturns, we lose the reference to the `buffer` object, which contains\nthe allocated memory, and, as a result, we can no longer free this memory.\n\nNotice that, inside a `test` block I execute this function with\nthe `std.testing.allocator`. The allocator object was capable\nof looking deeper in our program, and detecting the memory leak. As a result,\nthis allocator object returns an error message of \"memory leaked\", and also,\na stack trace showing the exact point where the memory was leaked.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nfn some_memory_leak(allocator: Allocator) !void {\n    const buffer = try allocator.alloc(u32, 10);\n    _ = buffer;\n    // Return without freeing the\n    // allocated memory\n}\n\ntest \"memory leak\" {\n    const allocator = std.testing.allocator;\n    try some_memory_leak(allocator);\n}\n```\n:::\n\n\n\n\n```\nTest [1/1] leak_memory.test.memory leak...\n    [gpa] (err): memory address 0x7c1fddf39000 leaked:\n./ZigExamples/debugging/leak_memory.zig:4:39: 0x10395f2\n    const buffer = try allocator.alloc(u32, 10);\n                                      ^\n./ZigExamples/debugging/leak_memory.zig:12:25: 0x10398ea\n    try some_memory_leak(allocator);\n\n... more stack trace\n```\n\n\n## Testing errors\n\nOne common style of unit tests are those that look for\nspecific errors in your functions. In other words, you write\na unit test that tries to assert if a specific function call\nreturns any error, or a specific type of error.\n\nIn C++ you would normally write this style of unit tests using, for example,\nthe functions `REQUIRE_THROWS()` or `CHECK_THROWS()` from the [`Catch2` test framework](https://github.com/catchorg/Catch2/tree/devel)[^catch2].\nIn the case of a Python project, you would probably use the\n[`raises()` function from `pytest`](https://docs.pytest.org/en/7.1.x/reference/reference.html#pytest-raises)[^pytest].\nWhile in Rust, you would probably use `assert_eq!()` in conjunction with `Err()`.\n\n[^pytest]: \n[^catch2]: \n\n\nBut in Zig, we use the `expectError()` function, from the `std.testing` module.\nWith this function, you can test if a specific function call returns the exact\ntype of error that you expect it to return. To use this function, you first write\n`try expectError()`. Then, on the first argument, you provide the type of error that you\nare expecting from the function call. Then, on the second argument, you write\nthe function call that you expect to fail.\n\nThe code example below demonstrates such type of unit test in Zig.\nNotice that, inside the function `alloc_error()` we are allocating\n100 bytes of memory, or, an array of 100 elements, for the object `ibuffer`. However,\nin the `test` block, we are using the `FixedBufferAllocator()`\nallocator object, which is limited to 10 bytes of space, because\nthe object `buffer`, which we provided to the allocator object,\nhave only 10 bytes of space.\n\nThat is why, the `alloc_error()` function raises an `OutOfMemory` error\non this case.\nBecause this function is trying to allocate more space than the allocator\nobject allows.\nSo, in essence, we are testing for a specific type of error,\nwhich is `OutOfMemory`. If the `alloc_error()` function returns any other type of error,\nthen, the `expectError()` function would make the entire test fail.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst expectError = std.testing.expectError;\nfn alloc_error(allocator: Allocator) !void {\n    var ibuffer = try allocator.alloc(u8, 100);\n    defer allocator.free(ibuffer);\n    ibuffer[0] = 2;\n}\n\ntest \"testing error\" {\n    var buffer: [10]u8 = undefined;\n    var fba = std.heap.FixedBufferAllocator.init(&buffer);\n    const allocator = fba.allocator();\n    try expectError(error.OutOfMemory, alloc_error(allocator));\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file81c24fea00d1.test.testing error...OKAll 1 \n   tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## Testing simple equalities\n\nIn Zig, there are some different ways you can test for an equality.\nYou already saw that we can use `expect()` with the logical operator `==`\nto essentially reproduce an equality test. But we also have\nsome other helper functions that you should know about, especially\n`expectEqual()`, `expectEqualSlices()` and `expectEqualStrings()`.\n\n\nThe `expectEqual()` function, as the name suggests, is a classic\ntest equality function. It receives two objects as input. The first\nobject is the value that you expect to be in the second object.\nWhile second object is the object you have, or, the object that your application\nproduced as result. So, with `expectEqual()` you are essentially\ntesting if the values stored inside these two objects\nare equal or not.\n\nYou can see in the example below that, the test performed by\n`expectEqual()` failed. Because the objects `v1` and `v2` contain\ndifferent values in them.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"values are equal?\" {\n    const v1 = 15;\n    const v2 = 18;\n    try std.testing.expectEqual(v1, v2);\n}\n```\n:::\n\n\n\n\n```\n1/1 ve.test.values are equal?...\n    expected 15, found 18\n    FAIL (TestExpectedEqual)\nve.zig:5:5: test.values are equal? (test)\n    try std.testing.expectEqual(v1, v2);\n    ^\n0 passed; 0 skipped; 1 failed.\n```\n\n\nAlthough useful, the `expectEqual()` function does not work with arrays.\nFor testing if two arrays are equal, you should use the `expectEqualSlices()`\nfunction instead. This function have three arguments. First, you provide\nthe data type contained in both arrays that you are trying to compare.\nWhile the second and third arguments corresponds to the array objects that you want to compare.\n\nIn the example below, we are using this function to test if two array\nobjects (`array1` and `array2`) are equal or not. Since they\nare in fact equal, the unit test passed with no errors.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"arrays are equal?\" {\n    const array1 = [3]u32{1, 2, 3};\n    const array2 = [3]u32{1, 2, 3};\n    try std.testing.expectEqualSlices(\n        u32, &array1, &array2\n    );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file81c25513148.test.arrays are equal?...OKAll\n  l 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\nAt last, you might also want to use the `expectEqualStrings()` function.\nAs the name suggests, you can use this function to test if two strings\nare equal or not. Just provide the two string objects that you want to compare,\nas inputs to the function.\n\nIf the function finds any existing differences between the two strings,\nthen, the function will raise an error, and also, print an error message\nthat shows the exact difference between the two string objects provided,\nas the example below demonstrates:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"strings are equal?\" {\n    const str1 = \"hello, world!\";\n    const str2 = \"Hello, world!\";\n    try std.testing.expectEqualStrings(\n        str1, str2\n    );\n}\n```\n:::\n\n\n\n\n```\n1/1 t.test.strings are equal?...\n====== expected this output: =========\nhello, world!␃\n======== instead found this: =========\nHello, world!␃\n======================================\nFirst difference occurs on line 1:\nexpected:\nhello, world!\n^ ('\\x68')\nfound:\nHello, world!\n^ ('\\x48')\n```\n",
    -    "supporting": [
    -      "03-unittests_files"
    -    ],
    +    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n# Unit tests {#sec-unittests}\n\nIn this chapter, I want to dive in on how unit tests are done in\nZig. We are going to talk about what is the testing workflow in Zig, and\nalso, about the `test` command from the `zig` compiler.\n\n\n## Introducing the `test` block\n\nIn Zig, unit tests are written inside a `test` declaration, or, how I prefer to call it, inside a `test` block.\nEvery `test` block is written by using the keyword `test`.\nYou can optionally use a string literal to write a label, which is responsible for identifying\nthe specific group of unit tests that you are writing inside this specific `test` block.\n\nIn the example below, we are testing if the sum of two objects (`a` and `b`)\nis equal to 4. The `expect()` function from the Zig Standard Library\nis a function that receives a logical test as input. If this logical test\nresults in `true`, then, the test passes. But if it results\nin `false`, then, the test fails.\n\nYou can write any Zig code you want inside a `test` block.\nPart of this code might be some necessary commands to setup your testing\nenvironment, or just initializing some objects that you need to use\nin your unit tests.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst expect = std.testing.expect;\ntest \"testing simple sum\" {\n    const a: u8 = 2;\n    const b: u8 = 2;\n    try expect((a + b) == 4);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file1ed835512cf8.test.testing simple sum...OKA\n  All 1 tests passed.\n```\n\n\n:::\n:::\n\n\nYou can have multiple `test` blocks written on the same Zig module.\nAlso, you can mix `test` blocks with your source code, with no problems\nor consequences. If you mix `test` blocks with your normal source code,\nwhen you execute the `build`, `build-exe`, `build-obj` or `build-lib` commands from the\n`zig` compiler that we exposed in @sec-compile-code, these `test` blocks are automatically\nignored by the compiler.\n\nIn other words, the `zig` compiler builds and execute your unit tests only\nwhen you ask it to. By default, the compiler always ignore `test`\nblocks written in your Zig modules. The compiler normally checks only if\nthere are any syntax errors in these `test` blocks.\n\nIf you take a look at the source code for most of the files present in the\nZig Standard Library[^zig-std-lib], you can see that the `test` blocks\nare written together with the normal source code of the library.\nYou can see this for example, at the [`array_list` module](https://github.com/ziglang/zig/blob/master/lib/std/array_list.zig)[^zig-array].\nSo, the standard that the Zig developers decided to adopt\nis to keep their unit tests together with the source code\nof the functionality that they are testing.\n\nEach programmer might have a different opinion on this.\nSome of them might prefer to keep unit tests separate from the actual\nsource code of their application. If that is your case, you can\nsimply create a separate `tests` folder in your project, and\nstart writing Zig modules that contains only unit tests (as you would normally do\non a Python project with `pytest`, for example), and everything will work fine.\nIt boils down to which is your preference here.\n\n[^zig-std-lib]: \n[^zig-array]: \n\n\n## How to run your tests\n\nIf the `zig` compiler ignores any `test` block by default, how can\nyou compile and run your unit tests? The answer is the `test` command from\nthe `zig` compiler. By running the `zig test` command, the compiler will\nfind every instance of a `test` block in your Zig modules, and, it will\ncompile and run the unit tests that you wrote.\n\n\n```bash\nzig test simple_sum.zig\n```\n\n```\n1/1 simple_sum.test.testing simple sum... OK\nAll 1 tests passed.\n```\n\n\n## Testing memory allocations\n\nOne of the advantages of Zig is that it offers great tools\nthat help us, programmers, to avoid (but also detect) memory problems, such as\nmemory leaks and double-frees. The `defer` keyword\nis especially helpful in this regard.\n\nWhen developing your source code, you, the programmer, are responsible for making\nsure that your code does not produce such problems. However,\nyou can also use a special type of an allocator object in Zig\nthat is capable of automatically detecting such problems for you.\nThis is the `std.testing.allocator` object.\nThis allocator object offers some basic memory safety detection\nfeatures, which are capable of detecting memory leaks.\n\nAs we described in @sec-heap, to allocate memory on the heap, you need\nto use an allocator object, and your functions that use these objects to allocate memory\non the heap, should receive an allocator object as one of its inputs.\nEvery memory on the heap that you allocate using these allocator objects,\nmust also be freed using this same allocator object.\n\nSo, if you want to test the memory allocations performed by your functions,\nand make sure that you don't have problems in these allocations, you can simply\nwrite unit tests for these functions, where you provide the\n`std.testing.allocator` object as input to these functions.\n\nLook at the example below, where I'm defining a function that clearly causes\na memory leak. Because we allocate memory, but, at the same time,\nwe do not free this allocated memory at any point. So, when the function\nreturns, we lose the reference to the `buffer` object, which contains\nthe allocated memory, and, as a result, we can no longer free this memory.\n\nNotice that, inside a `test` block I execute this function with\nthe `std.testing.allocator`. The allocator object was capable\nof looking deeper in our program, and detecting the memory leak. As a result,\nthis allocator object returns an error message of \"memory leaked\", and also,\na stack trace showing the exact point where the memory was leaked.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nfn some_memory_leak(allocator: Allocator) !void {\n    const buffer = try allocator.alloc(u32, 10);\n    _ = buffer;\n    // Return without freeing the\n    // allocated memory\n}\n\ntest \"memory leak\" {\n    const allocator = std.testing.allocator;\n    try some_memory_leak(allocator);\n}\n```\n:::\n\n\n```\nTest [1/1] leak_memory.test.memory leak...\n    [gpa] (err): memory address 0x7c1fddf39000 leaked:\n./ZigExamples/debugging/leak_memory.zig:4:39: 0x10395f2\n    const buffer = try allocator.alloc(u32, 10);\n                                      ^\n./ZigExamples/debugging/leak_memory.zig:12:25: 0x10398ea\n    try some_memory_leak(allocator);\n\n... more stack trace\n```\n\n\n## Testing errors\n\nOne common style of unit tests are those that look for\nspecific errors in your functions. In other words, you write\na unit test that tries to assert if a specific function call\nreturns any error, or a specific type of error.\n\nIn C++ you would normally write this style of unit tests using, for example,\nthe functions `REQUIRE_THROWS()` or `CHECK_THROWS()` from the [`Catch2` test framework](https://github.com/catchorg/Catch2/tree/devel)[^catch2].\nIn the case of a Python project, you would probably use the\n[`raises()` function from `pytest`](https://docs.pytest.org/en/7.1.x/reference/reference.html#pytest-raises)[^pytest].\nWhile in Rust, you would probably use `assert_eq!()` in conjunction with `Err()`.\n\n[^pytest]: \n[^catch2]: \n\n\nBut in Zig, we use the `expectError()` function, from the `std.testing` module.\nWith this function, you can test if a specific function call returns the exact\ntype of error that you expect it to return. To use this function, you first write\n`try expectError()`. Then, on the first argument, you provide the type of error that you\nare expecting from the function call. Then, on the second argument, you write\nthe function call that you expect to fail.\n\nThe code example below demonstrates such type of unit test in Zig.\nNotice that, inside the function `alloc_error()` we are allocating\n100 bytes of memory, or, an array of 100 elements, for the object `ibuffer`. However,\nin the `test` block, we are using the `FixedBufferAllocator()`\nallocator object, which is limited to 10 bytes of space, because\nthe object `buffer`, which we provided to the allocator object,\nhave only 10 bytes of space.\n\nThat is why, the `alloc_error()` function raises an `OutOfMemory` error\non this case.\nBecause this function is trying to allocate more space than the allocator\nobject allows.\nSo, in essence, we are testing for a specific type of error,\nwhich is `OutOfMemory`. If the `alloc_error()` function returns any other type of error,\nthen, the `expectError()` function would make the entire test fail.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst expectError = std.testing.expectError;\nfn alloc_error(allocator: Allocator) !void {\n    var ibuffer = try allocator.alloc(u8, 100);\n    defer allocator.free(ibuffer);\n    ibuffer[0] = 2;\n}\n\ntest \"testing error\" {\n    var buffer: [10]u8 = undefined;\n    var fba = std.heap.FixedBufferAllocator.init(&buffer);\n    const allocator = fba.allocator();\n    try expectError(error.OutOfMemory, alloc_error(allocator));\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file1ed878d2d839.test.testing error...OKAll 1 \n   tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n## Testing simple equalities\n\nIn Zig, there are some different ways you can test for an equality.\nYou already saw that we can use `expect()` with the logical operator `==`\nto essentially reproduce an equality test. But we also have\nsome other helper functions that you should know about, especially\n`expectEqual()`, `expectEqualSlices()` and `expectEqualStrings()`.\n\n\nThe `expectEqual()` function, as the name suggests, is a classic\ntest equality function. It receives two objects as input. The first\nobject is the value that you expect to be in the second object.\nWhile second object is the object you have, or, the object that your application\nproduced as result. So, with `expectEqual()` you are essentially\ntesting if the values stored inside these two objects\nare equal or not.\n\nYou can see in the example below that, the test performed by\n`expectEqual()` failed. Because the objects `v1` and `v2` contain\ndifferent values in them.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"values are equal?\" {\n    const v1 = 15;\n    const v2 = 18;\n    try std.testing.expectEqual(v1, v2);\n}\n```\n:::\n\n\n```\n1/1 ve.test.values are equal?...\n    expected 15, found 18\n    FAIL (TestExpectedEqual)\nve.zig:5:5: test.values are equal? (test)\n    try std.testing.expectEqual(v1, v2);\n    ^\n0 passed; 0 skipped; 1 failed.\n```\n\n\nAlthough useful, the `expectEqual()` function does not work with arrays.\nFor testing if two arrays are equal, you should use the `expectEqualSlices()`\nfunction instead. This function have three arguments. First, you provide\nthe data type contained in both arrays that you are trying to compare.\nWhile the second and third arguments corresponds to the array objects that you want to compare.\n\nIn the example below, we are using this function to test if two array\nobjects (`array1` and `array2`) are equal or not. Since they\nare in fact equal, the unit test passed with no errors.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"arrays are equal?\" {\n    const array1 = [3]u32{1, 2, 3};\n    const array2 = [3]u32{1, 2, 3};\n    try std.testing.expectEqualSlices(\n        u32, &array1, &array2\n    );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file1ed83cbad6df.test.arrays are equal?...OKAl\n  ll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\nAt last, you might also want to use the `expectEqualStrings()` function.\nAs the name suggests, you can use this function to test if two strings\nare equal or not. Just provide the two string objects that you want to compare,\nas inputs to the function.\n\nIf the function finds any existing differences between the two strings,\nthen, the function will raise an error, and also, print an error message\nthat shows the exact difference between the two string objects provided,\nas the example below demonstrates:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\ntest \"strings are equal?\" {\n    const str1 = \"hello, world!\";\n    const str2 = \"Hello, world!\";\n    try std.testing.expectEqualStrings(\n        str1, str2\n    );\n}\n```\n:::\n\n\n```\n1/1 t.test.strings are equal?...\n====== expected this output: =========\nhello, world!␃\n======== instead found this: =========\nHello, world!␃\n======================================\nFirst difference occurs on line 1:\nexpected:\nhello, world!\n^ ('\\x68')\nfound:\nHello, world!\n^ ('\\x48')\n```\n",
    +    "supporting": [],
         "filters": [
           "rmarkdown/pagebreak.lua"
         ],
    diff --git a/_freeze/Chapters/04-http-server/execute-results/epub.json b/_freeze/Chapters/04-http-server/execute-results/epub.json
    deleted file mode 100644
    index ddf9953a..00000000
    --- a/_freeze/Chapters/04-http-server/execute-results/epub.json
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -{
    -  "hash": "f64c88659b4b19943ce530d1245b8add",
    -  "result": {
    -    "engine": "knitr",
    -    "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n# Project 2 - Building a HTTP Server from scratch\n\nIn this chapter, I want to implement a new\nsmall project with you. This time, we are going\nto implement a basic HTTP Server from scratch.\n\nThe Zig Standard Library already have a HTTP Server\nimplemented, which is available at `std.http.Server`.\nBut again, our objective here in this chapter, is to implement\nit **from scratch**. So we can't use this server object available\nfrom the Zig Standard Library.\n\n## What is a HTTP Server?\n\nFirst of all, what is a HTTP Server?\nA HTTP server, as any other type of server, is essentially\na program that runs indefinitely, on an infinite loop, waiting for incoming connections\nfrom clients. Once the server receives an incoming connection, it will\naccept this connection, and it will send messages back-and-forth to the client\nthrough this connection.\n\nBut the messages that are transmitted inside this connection are in a\nspecific format. They are HTTP messages\n(i.e., messages that use the HTTP Protocol specification).\nThe HTTP Protocol is the backbone of the modern web.\nThe world wide web as we know it today, would not exist without the\nHTTP Protocol.\n\nSo, Web servers (which is just a fancy name to\nHTTP Servers) are servers that exchange HTTP messages with clients.\nAnd these HTTP servers and the HTTP Protocol specification\nare essential to the operation of the world wide web today.\n\nThat is the whole picture of the process.\nAgain, we have two subjects involved here, a server (which is\na program that is running indefinitely, waiting to receive incoming connections),\nand a client (which is someone that wants to connect to the server,\nand exchange HTTP messages with it).\n\nYou may find the material about the [HTTP Protocol available at the Mozilla MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)[^mdn-http]\n, a great resource for you to also look at. It gives you a great overview on how\nHTTP works, and what role the server plays in this matter.\n\n[^mdn-http]: .\n\n\n## How a HTTP Server works? {#sec-how-http-works}\n\nImagine a HTTP Server as if it were the receptionist of a large hotel. In a hotel,\nyou have a reception, and inside that reception there is a receptionist\nwaiting for customers to arrive. A HTTP Server is essentially a receptionist\nthat is indefinitely waiting for new customers (or, in the context of HTTP, new clients)\nto arrive in the hotel.\n\nWhen a customer arrives at the hotel, that customer starts a conversation with the\nreceptionist. He tells the receptionist how many days he wants to stay at the hotel.\nThen, the receptionist search for an available apartment. If there is an available apartment\nat the moment, the customer pays the hotel fees, then, he gets the keys to the apartment,\nand then, he goes to the apartment to rest.\n\nAfter this entire process of dealing with the customer (searching for available apartments,\nreceiving payment, handing over the keys), the receptionist goes back to what he was\ndoing earlier, which is to wait. Wait for new customers to arrive.\n\nThat is, in a nutshell, what a HTTP Server do. It waits for clients to connect to the\nserver. When a client attempts to connect to the server, the server accepts this connection,\nand it starts to exchange messages with the client through this connection.\nThe first message that happens inside this connection is always a message from the client\nto the server. This message is called the *HTTP Request*.\n\nThis HTTP Request is a HTTP message that contains what\nthe client wants from the server. It is literally a request. The client\nthat connected to the server is asking this server to do something for him.\n\nThere are different \"types of request\" that a client can send to a HTTP Server.\nBut the most basic type of request, is when a client ask to the\nHTTP Server to serve (i.e., to send) some specific web page (which is a HTML file) to him.\nWhen you type `google.com` in your web browser, you are essentially sending a HTTP Request to Google's\nHTTP servers. This request is asking these servers to send the Google webpage to you.\n\nNonetheless, when the server receives this first message, the *HTTP Request*, it\nanalyzes this request, to understand: who the client is? What he wants the server to do?\nThis client has provided all the necessary information to perform the action that he\nasked? Etc.\n\nOnce the server understands what the client wants, he simply perform the action\nthat was requested, and, to finish the whole process, the server sends back\na HTTP message to the client, informing if the action performed was successful or not,\nand, at last, the server ends (or closes) the connection with the client.\n\nThis last HTTP message sent from the server to the client, is called the *HTTP Response*.\nBecause the server is responding to the action that was requested by the client.\nThe main objective of this response message is let the client know if the\naction requested was successful or not, before the server closes the connection.\n\n\n## How a HTTP server is normally implemented? {#sec-http-how-impl}\n\nLet's use the C language as an example. There are many materials\nteaching how to write a simple HTTP server in C code, like @jeffrey_http,\nor @nipun_http, or @eric_http.\nHaving this in mind, I will not show C code examples here, because you\ncan find them on the internet.\nBut I will describe the theory behind the necessary steps to create\nsuch HTTP server in C.\n\n\nIn essence, we normally implement a HTTP server in C by using a TCP socket,\nwhich involves the following steps:\n\n1. Create a TCP socket object.\n1. Bind a name (or more specifically, an address) to this socket object.\n1. Make this socket object to start listening and waiting for incoming connections.\n1. When a connection arrive, we accept this connection, and we exchange the HTTP messages (HTTP Request and HTTP Response).\n1. Then, we simply close this connection.\n\n\nA socket object is essentially a channel of communication.\nYou are creating a channel where people can send messages through.\nWhen you create a socket object, this object is not binded to any particular\naddress. This means that with this object you have a representation of a channel of communication\nin your hands. But this channel is not currently available, or, it is not currently accessible,\nbecause it does not have a known address where you can find it.\n\nThat is what the \"bind\" operation do. It binds a name (or more specifically, an address) to\nthis socket object, or, this channel of communication, so that it becomes available,\nor, accessible through this address. While the \"listen\" operation makes the socket object to\nlisten for incoming connections in this address. In other words, the \"listen\" operation\nmakes the socket wait for incoming connections.\n\nNow, when a client actually attempts to connect to the server through the socket address\nthat we have specified, in order to establish this connection with the client,\nthe socket object needs to accept this incoming connection. Thus, when we\naccept an incoming connection, the client and the server become\nconnected to each other, and they can start reading or writing messages into this\nestablished connection.\n\nAfter we receive the HTTP Request from the client, analyze it, and send the HTTP Response\nto the client, we can then close the connection, and end this communication.\n\n\n## Implementing the server - Part 1\n\n### Creating the socket object {#sec-create-socket}\n\nLet's begin with creating the socket object for our server.\nJust to make things shorter, I will create this socket object in\na separate Zig module. I will name it `config.zig`.\n\nIn Zig, we can create a TCP socket using\nthe `std.posix.socket()` function, from the Zig Standard Library.\nAs I mentioned earlier in @sec-http-how-impl, every socket object that we create\nrepresents a communication channel, and we need to bind this channel to a specific address.\nAn \"address\" is defined as an IP address, or, more specifically, an IPv4 address^[It can be also an IPv6 address. But normally, we use a IPv4 address for that.].\nEvery IPv4 address is composed by two components. The first component is the host,\nwhich is a sequence of 4 numbers separated by dot characters (`.`) that identifies the machine used.\nWhile the second component is a port number, which identifies the specific\ndoor, or, the specific port to use in the host machine.\n\nThe sequence of 4 numbers (i.e., the host) identifies the machine (i.e., the computer itself) where\nthis socket will live in. Every computer normally have multiple \"doors\" available inside of him, because\nthis allows the computer to receive and work with multiple connections at the same time.\nHe simply use a single door for each connection. So the port number, is\nessentially a number that identifies the specific door in the computer that will be responsible\nfor receiving the connection. That is, it identifies the \"door\" in the computer that the socket will use\nto receive incoming connections.\n\nTo make things simpler, I will use an IP address that identifies our current machine in this example.\nThis means that, our socket object will reside on the same computer that we are currently using\n(this is also known as the \"localhost\") to write this Zig source code.\n\nBy convention, the IP address that identifies the \"localhost\", which is the current machine we\nare using, is the IP `127.0.0.1`. So, that is the IP\naddress we are going to use in our server. I can declare it in Zig\nby using an array of 4 integers, like this:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst localhost = [4]u8{ 127, 0, 0, 1 };\n_ = localhost;\n```\n:::\n\n\n\nNow, we need to decide which port number to use. By convention, there are some\nport numbers that are reserved, meaning that, we cannot use them for our own\npurposes, like the port 22 (which is normally used for SSH connections).\nFor TCP connections, which is our case here,\na port number is a 16-bit unsigned integer (type `u16` in Zig),\nthus ranging from 0 to 65535 [@wikipedia_port].\nSo, we can choose\na number from 0 to 65535 for our port number. In the\nexample of this book, I will use the port number 3490\n(just a random number).\n\n\nNow that we have these two informations at hand, I can\nfinally create our socket object, using the `std.posix.socket()` function.\nFirst, we use the host and the port number to create an `Address` object,\nwith the `std.net.Address.initIp4()` function, like in the example below.\nAfter that, I use this address object inside the `socket()` function\nto create our socket object.\n\nThe `Socket` struct defined below summarizes all the logic behind\nthis process. In this struct, we have two data members, which are:\n1)  the address object; 2) and a stream object, which is\nthe object we will use to read and write the messages into any connection we establish.\n\nNotice that, inside the constructor method of this struct,\nwhen we create the socket object, we are using the `IPROTO.TCP` property as an input to\ntell the function to create a socket for TCP connections.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\nconst net = @import(\"std\").net;\n\npub const Socket = struct {\n    _address: std.net.Address,\n    _stream: std.net.Stream,\n\n    pub fn init() !Socket {\n        const host = [4]u8{ 127, 0, 0, 1 };\n        const port = 3490;\n        const addr = net.Address.initIp4(host, port);\n        const socket = try std.posix.socket(\n            addr.any.family,\n            std.posix.SOCK.STREAM,\n            std.posix.IPPROTO.TCP\n        );\n        const stream = net.Stream{ .handle = socket };\n        return Socket{ ._address = addr, ._stream = stream };\n    }\n};\n```\n:::\n\n\n\n\n### Listening and receiving connections\n\nRemember that we stored the `Socket` struct\ndeclaration that we built in @sec-create-socket inside a Zig module named `config.zig`.\nThis is why I imported this module into our main module (`main.zig`) in the example below, as the `SocketConf` object,\nto access the `Socket` struct.\n\nOnce we created our socket object, we can focus now on making this socket object\nlisten and receive new incoming connections. We do that, by calling the `listen()`\nmethod from the `Address` object that is contained inside the socket object, and then,\nwe call the `accept()` method over the result.\n\nThe `listen()` method from the `Address` object produces a server object,\nwhich is an object that will stay open and running indefinitely, waiting\nto receive an incoming connection. Therefore, if you try to run the code\nexample below, by calling the `run` command from the `zig` compiler,\nyou will notice that the programs keeps running indefinitely,\nwithout a clear end.\n\nThis happens, because the program is waiting for something to happen.\nIt's waiting for someone to try to connect to the address (`http://127.0.0.1:3490`) where\nthe server is running and listening for incoming connections. This is what\nthe `listen()` method do, it makes the socket to be active waiting for someone\nto connect.\n\nOn the other side, the `accept()` method is the function that establishes the connection\nwhen someone tries to connect to the socket. This means that, the `accept()` method\nreturns a new connection object as a result. And you can use this connection object\nto read or write messages from or to the client.\nFor now, we are not doing anything with this connection object.\nBut we are going to use it in the next section.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    const socket = try SocketConf.Socket.init();\n    try stdout.print(\"Server Addr: {any}\\n\", .{socket._address});\n    var server = try socket._address.listen(.{});\n    const connection = try server.accept();\n    _ = connection;\n}\n```\n:::\n\n\n\nThis code example allows one single connection. In other words, the\nserver will wait for one incoming connection, and as soon as the\nserver is done with this first connection that it establishes, the\nprogram ends, and the server stops.\n\nThis is not the norm in the real world. Most people that write\na HTTP server like this, usually put the `accept()` method\ninside a `while` (infinite) loop, where if a connection\nis created with `accept()`, a new thread of execution is created to deal with\nthis new connection and the client. That is, real-world examples of HTTP Servers\nnormally rely on parallel computing to work.\n\nWith this design, the server simply accepts the connection,\nand the whole process of dealing with the client, and receiving\nthe HTTP Request, and sending the HTTP Response, all of this\nis done in the background, on a separate execution thread.\n\nSo, as soon as the server accepts the connection, and creates\nthe separate thread, the server goes back to what he was doing earlier,\nwhich is to wait indefinitely for a new connection to accept.\nHaving this in mind, the code example exposed above, is a\nserver that serves only a single client. Because the program\nterminates as soon as the connection is accepted.\n\n\n\n### Reading the message from the client {#sec-read-http-message}\n\nNow that we have a connection established, i.e., the connection\nobject that we created through the `accept()` function, we can now\nuse this connection object to read any messages that the client\nsend to our server. But we can also use it to send messages back\nto the client.\n\nThe basic idea is, if we **write** any data into this connection object,\nthen, we are sending data to the client, and if we **read** the data present in\nthis connection object, then, we are reading any data that the\nclient sent to us, through this connection object. So, just\nhave this logic in mind. \"Read\" is for reading messages from the client,\nand \"write\" is to send a message to the client.\n\nRemember from @sec-how-http-works that, the first thing that we need to do is to read the HTTP Request\nsent by the client to our server. Because it is the first message that happens\ninside the established connection, and, as a consequence, it is the first\nthing that we need to deal with.\n\nThat is why, I'm going to create a new Zig module in this small project, named `request.zig`\nto keep all functions related to the HTTP Request\ntogether. Then, I will create a new function named `read_request()` that will\nuse our connection object to read the message sent by the client,\nwhich is the HTTP Request.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Connection = std.net.Server.Connection;\npub fn read_request(conn: Connection,\n                    buffer: []u8) !void {\n    const reader = conn.stream.reader();\n    _ = try reader.read(buffer);\n}\n```\n:::\n\n\n\n\nThis function accepts a slice object which behaves as a buffer.\nThe `read_request()` function reads the message sent into\nthe connection object, and saves this message into this buffer object that\nwe have provided as input.\n\nNotice that I'm using the connection object that we created to read\nthe message from the client. I first access the `reader` object that lives inside the\nconnection object. Then, I call the `read()` method of this `reader` object\nto effectively read and save the data sent by the client into the buffer object\nthat we created earlier. I'm discarding the return value\nof the `read()` method, by assigning it to the underscore character (`_`),\nbecause this return value is not useful for us right now.\n\n\n\n## Looking at the current state of the program\n\n\nI think now is a good time to see how our program is currently working. Shall we?\nSo, the first thing I will do is to update the `main.zig` module in our small Zig project,\nso that the `main()` function call this new `read_request()` function that we have just created.\nI will also add a print statement at the end of the `main()` function,\njust so that you can see what the HTTP Request that we have just loaded into the buffer object\nlooks like.\n\nAlso, I'm creating the buffer object in the `main()` function, which will be\nresponsible for storing the message sent by the client, and, I'm also\nusing a `for` loop to initialize all fields of this buffer object to the number zero.\nThis is important to make sure that we don't have uninitialized memory in\nthis object. Because uninitialized memory may cause undefined behaviour in our program.\n\nSince the `read_request()` function should receive as input the buffer object as a slice object (`[]u8`),\nI am using the syntax `array[0..array.len]` to get access to a slice of this `buffer` object.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst Request = @import(\"request.zig\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    const socket = try SocketConf.Socket.init();\n    try stdout.print(\"Server Addr: {any}\\n\", .{socket._address});\n    var server = try socket._address.listen(.{});\n    const connection = try server.accept();\n    var buffer: [1000]u8 = undefined;\n    for (0..buffer.len) |i| {\n        buffer[i] = 0;\n    }\n    _ = try Request.read_request(\n        connection, buffer[0..buffer.len]\n    );\n    try stdout.print(\"{s}\\n\", .{buffer});\n}\n```\n:::\n\n\n\nNow, I'm going to execute this program, with the `run` command from the\n`zig` compiler. But remember, as we sad earlier, as soon as I execute this program, it will\nhang indefinitely, because the program is waiting for a client trying to\nconnect to the server.\n\nMore specifically, the program will pause at the line\nwith the `accept()` call. As soon as a client try to connect to the\nserver, then, the execution will \"unpause\", and the `accept()` function\nwill finally be executed to create the\nconnection object that we need, and the remaining of the program\nwill run.\n\nYou can see that in @fig-print-zigrun1. The message `Server Addr: 127.0.0.1:3490`\nis printed to the console, and the program is now waiting for an incoming connection.\n\n![A screenshot of running the program](./../Figures/print-zigrun1.png){#fig-print-zigrun1}\n\n\nWe can finally try to connect to this server, and there are several ways we can do this.\nFor example, we could use the following Python script:\n\n```python\nimport requests\nrequests.get(\"http://127.0.0.1:3490\")\n```\n\nOr, we could also open any web browser of our preference, and type\nthe URL `localhost:3490`. OBS: `localhost` is the same thing as the\nIP `127.0.0.1`. When you press enter, and your web browser go\nto this address, first, the browser will probably print a message\nsaying that \"this page isn't working\", and, then, it will\nprobably change to a new message saying that \"the site can't be\nreached\".\n\nYou get these \"error messages\" in the web browser, because\nit got no response back from the server. In other words, when the web\nbrowser connected to our server, it did send the HTTP Request through the established connection.\nThen, the web browser was expecting to receive a HTTP Response back, but\nit got no response from the server (we didn't implemented the HTTP Response logic yet).\n\nBut that is okay. We have achieved the result that we wanted for now,\nwhich is to connect to the server, and see the HTTP Request\nthat was sent by the web browser (or by the Python script)\nto the server.\n\nIf you comeback to the console that you left open\nwhen you have executed the program, you will see that the\nprogram finished its execution, and, a new message is\nprinted in the console, which is the actual HTTP Request\nmessage that was sent by the web browser to the server.\nYou can see this message in @fig-print-zigrun2.\n\n![A screenshot of the HTTP Request sent by the web browser](./../Figures/print-zigrun2.png){#fig-print-zigrun2}\n\n\n\n\n## Learning about Enums in Zig {#sec-enum}\n\nEnums structures are available in Zig through the `enum` keyword.\nAn enum (short for \"enumeration\") is a special structure that represents a group of constant values.\nSo, if you have a variable which can assume a short and known\nset of values, you might want to associate this variable to an enum structure,\nto make sure that this variable only assumes a value from this set.\n\nA classic example for enums are primary colors. If for some reason, your program\nneeds to represent one of the primary colors, you can create an enum\nthat represents one of these colors.\nIn the example below, we are creating the enum `PrimaryColorRGB`, which\nrepresents a primary color from the RGB color system. By using this enum,\nI am guaranteed that the `acolor` object for example, will contain\none of these three values: `RED`, `GREEN` or `BLUE`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst PrimaryColorRGB = enum {\n    RED, GREEN, BLUE\n};\nconst acolor = PrimaryColorRGB.RED;\n_ = acolor;\n```\n:::\n\n\n\nIf for some reason, my code tries to save in `acolor`,\na value that is not in this set, I will get an error message\nwarning me that a value such as \"MAGENTA\" do not exist\ninside the `PrimaryColorRGB` enum.\nThen I can easily fix my mistake.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst acolor = PrimaryColorRGB.MAGENTA;\n```\n:::\n\n\n\n```\ne1.zig:5:36: error: enum 'PrimaryColorRGB' has\n        no member named 'MAGENTA':\n    const acolor = PrimaryColorRGB.MAGENTA;\n                                   ^~~~~~~\n```\n\nBehind the hood, enums in Zig work the same way that enums\nwork in C. Each enum value is essentially represented as an integer.\nThe first value in the set is represented as zero,\nthen, the second value is one, ... etc.\n\nOne thing that we are going to learn in the next section is that\nenums can have methods in them. Wait... What? This is amazing!\nYes, enums in Zig are similar to structs, and they can have\nprivate and public methods inside them.\n\n\n\n\n\n\n\n## Implementing the server - Part 2\n\nNow, on this section, I want to focus on parsing\nthe HTTP Request that we received from the client.\nHowever, to effectively parse a HTTP Request message, we first need to understand its\nstructure.\nIn summary, a HTTP Request is a text message that is divided into 3 different\nsections (or parts):\n\n- The top-level header indicating the method of the HTTP Request, the URI, and the HTTP version used in the message.\n- A list of HTTP Headers.\n- The body of the HTTP Request.\n\n### The top-level header\n\nThe first line of text in a HTTP Request always come with the three most essential\ninformation about the request. These three key attributes of the HTTP Request\nare separated by a simple space in this first line of the request.\nThe first information is the HTTP method that is being\nused in the request, second, we have the URI to which this HTTP Request is being sent to,\nand third, we have the version of the HTTP protocol that is being used in this HTTP Request.\n\nIn the snippet below, you can find an example of this first line in a HTTP Request.\nFirst, we have the HTTP method of this request (`GET`). Many programmers\nrefer to the URI component (`/users/list`) as the \"API endpoint\" to which the HTTP Request\nis being sent to. In the context of this specific request, since it's a GET request,\nyou could also say that the URI component is the path to the resource we want to access,\nor, the path to the document (or the file) that we want to retrieve from the server.\n\n```\nGET /users/list HTTP/1.1\n```\n\nAlso, notice that this HTTP Request is using the version 1.1 of the HTTP protocol,\nwhich is the most popular version of the protocol used in the web.\n\n\n\n### The list of HTTP headers\n\nMost HTTP Requests also include a section of HTTP Headers,\nwhich is just a list of attributes or key-value pairs associated with this\nparticular request. This section always comes right after the \"top-level header\" of the request.\n\nFor our purpose in this chapter, which is to build a simple HTTP Server,\nwe are going to ignore this section of the HTTP Request, for simplicity.\nBut most HTTP servers that exist in the wild parses and use these\nHTTP headers to change the way that the server responds to the request\nsent by the client.\n\nFor example, many requests we encounter in the real-world comes with\na HTTP header called `Accept`. In this header, we find a list of [MIME types](https://en.wikipedia.org/wiki/Media_type)[^mime].\nThis list indicates the file formats that the client can read, or parse, or interpret.\nIn other words, you also interpret this header as the client saying the following phrase\nto the server: \"Hey! Look, I can read only HTML documents, so please, send me back\na document that is in a HTML format.\".\n\n[^mime]: .\n\nIf the HTTP server can read and use this `Accept` header, then, the server can identify\nwhich is the best file format for the document to be sent to the client. Maybe the HTTP server have\nthe same document in multiple formats, for example, in JSON, in XML, in HTML and in PDF,\nbut the client can only understand documents in the HTML format. That is the purpose\nof this `Accept` header.\n\n\n### The body\n\nThe body comes after the list of HTTP headers, and it's an optional section of the HTTP Request, meaning that, not\nall HTTP Requests will come with a body in them. For example, every HTTP Request that uses the\nGET method usually does not come with a body.\n\nBecause a GET request is used to request data, instead of sending it to the server.\nSo, the body section is more related to the POST method, which is a method that involves\nsending data to the server, to be processed and stored.\n\nSince we are going to support only the GET method in this project, it means that\nwe also do not need to care about the body of the request.\n\n\n\n### Creating the HTTP Method enum\n\nEvery HTTP Request comes with a explicit method. The method used in a HTTP Request\nis identified by one these words:\n\n- GET;\n- POST;\n- OPTIONS;\n- PATCH;\n- DELETE;\n- and some other methods.\n\nEach HTTP method is used for a specific type of task. The POST method for example is normally\nused to post some data into the destination. In other words, it's used\nto send some data to the HTTP server, so that it can be processed and stored by the server.\n\nAs another example, the GET method is normally used to get content from the server.\nIn other words, we use this method whenever we want the server to send some\ncontent back to us. It can be any type of content. It can be a web page,\na document file, or some data in a JSON format.\n\nWhen a client sends a POST HTTP Request, the HTTP Response sent by the server normally have the sole purpose of\nletting the client know if the server processed and stored the data successfully.\nIn contrast, when the server receives a GET HTTP Request, then, the server sends the content\nthat the client asked for in the HTTP Response itself. This demonstrates that the method associated\nwith the HTTP Request changes a lot on the dynamics and the roles that each party\nplays in the whole process.\n\nSince the HTTP method of the HTTP Request is identified by this very small and specific\nset of words, it would be interesting to create an enum structure to represent a HTTP method.\nThis way, we can easily check if the HTTP Request we receive from the client is a\nHTTP method that we currently support in our small HTTP server project.\n\nThe `Method` structure below represents this enumeration.\nNotice that, for now, only the GET HTTP method is included in this\nenumeration. Because, for the purpose of this chapter, I want to\nimplement only the GET HTTP method. That is why I am not\nincluding the other HTTP methods in this enumeration.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Method = enum {\n    GET\n};\n```\n:::\n\n\n\n\nNow, I think we should add two methods to this enum structure. One method is `is_supported()`,\nwhich will be a function that returns a boolean value, indicating if the input HTTP method is supported\nor not by our HTTP Server. The other is `init()`, which is a constructor function that takes a string as input,\nand tries to convert it into a `Method` value.\n\n\nBut in order to build these functions, I will use a functionality from the Zig Standard Library, called\n`StaticStringMap()`. This function allows us to create a simple map from strings to enum values.\nIn other words, we can use this map structure to map a string to the respective enum value.\nTo some extent, this specific structure from the standard library works almost like a \"hashtable\" structure,\nand it's optimized for small sets of words, or, small sets of keys, which is our case here.\nWe are going to talk more about hashtables in Zig in @sec-maps-hashtables.\n\nTo use this \"static string map\" structure, you have to import it from the `std.static_string_map` module\nof the Zig Standard Library. Just to make things shorter and easier to type, I am going to import this\nfunction through a different and shorter name (`Map`).\n\nWith `Map()` imported, we can just apply this function over the enum structure\nthat we are going to use in the resulting map. In our case here, it's the `Method` enum structure\nthat we declared at the last code example. Then, I call the `initComptime()` method with the\nmap, i.e., the list of key-value pairs that we are going to use.\n\nYou can see in the example below that I wrote this map using multiple anonymous struct literals.\nInside the first (or \"top-level\") struct literal, we have a list (or a sequence) of struct literals.\nEach struct literal in this list represents a separate key-value pair. The first element (or the key)\nin each key-value pair should always be a string value. While the second element should\nbe a value from the enum structure that you have used inside the `Map()` function.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Map = std.static_string_map.StaticStringMap;\nconst MethodMap = Map(Method).initComptime(.{\n    .{ \"GET\", Method.GET },\n});\n```\n:::\n\n\n\nTherefore, the `MethodMap` object is basically a `std::map` object from C++, or,\na `dict` object from Python. You can retrieve (or get) the enum value that\ncorresponds to a particular key, by using the `get()` method from the map\nobject. This method returns an optional value, so, the `get()` method might\nresult in a null value.\n\nWe can use this in our advantage to detect if a particular HTTP method is\nsupported or not in our HTTP server. Because, if the `get()` method returns null,\nit means that it did not found the method that we provided inside the `MethodMap` object, and,\nas a consequence, this method is not supported by our HTTP server.\n\nThe `init()` method below, takes a string value as input, and then, it simply passes this string value\nto the `get()` method of our `MethodMap` object. As consequence, we should get the enum value that corresponds\nto this input string.\n\nNotice in the example below that, the `init()` method returns either an error\n(which might happen if the `?` method returns `unreacheable`, checkout @sec-null-handling for more details)\nor a `Method` object as result. Since `GET` is currently the only value in our `Method` enum\nstructure, it means that, the `init()` method will most likely return the value `Method.GET` as result.\n\nAlso notice that, in the `is_supported()` method, we are using the optional value returned\nby the `get()` method from our `MethodMap` object. The if statement unwraps the optional value\nreturned by this method, and returns `true` in case this optional value is a not-null value.\nOtherwise, it simply returns `false`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Method = enum {\n    GET,\n    pub fn init(text: []const u8) !Method {\n        return MethodMap.get(text).?;\n    }\n    pub fn is_supported(m: []const u8) bool {\n        const method = MethodMap.get(m);\n        if (method) |_| {\n            return true;\n        }\n        return false;\n    }\n};\n```\n:::\n\n\n\n\n\n\n\n\n\n### Writing the parse request function\n\nNow that we created the enum that represents our HTTP method,\nwe should start to write the function responsible for\nactually parsing the HTTP Request.\n\nThe first thing we can do, is to write a struct to represent the HTTP Request.\nTake the `Request` struct below as an example. It contains the three\nessential information from the \"top-level\" header (i.e., the first line)\nin the HTTP Request.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Request = struct {\n    method: Method,\n    version: []const u8,\n    uri: []const u8,\n    pub fn init(method: Method,\n                uri: []const u8,\n                version: []const u8) Request {\n        return Request{\n            .method = method,\n            .uri = uri,\n            .version = version,\n        };\n    }\n};\n```\n:::\n\n\n\n\nThe `parse_request()` function should receive a string as input. This input string\ncontains the entire HTTP Request message, and the parsing function should\nread and understand the individual parts of this message.\n\nNow, remember that for the purpose of this chapter, we care only about the first\nline in this message, which contains the \"top-level header\", or, the three essential attributes about the HTTP Request,\nwhich are the HTTP method used, the URI and the HTTP version.\n\nNotice that I use the function `indexOfScalar()` in `parse_request()`. This function from the\nZig Standard Library returns the first index where the scalar value that we provide\nhappens in a string. In this case, I'm looking at the first occurrence of the new line character (`\\n`).\nBecause once again, we care only about the first line in the HTTP Request message.\nThis is the line where we have the three information that we want to parse\n(version of HTTP, the HTTP method and the URI).\n\nTherefore, we are using this `indexOfScalar()` function\nto limit our parsing process to the first line in the message.\nIt's also worth mentioning that, the `indexOfScalar()` function returns an optional value.\nThat is why I use the `orelse` keyword to provide an alternative value, in case\nthe value returned by the function is a null value.\n\nSince each of these three attributes are separated by a simple space, we\ncould use the function `splitScalar()` from the Zig Standard Library to split\nthe input string into sections by looking for every position that appears\na simple space. In other words, this `splitScalar()` function is equivalent\nto the `split()` method in Python, or, the `std::getline()` function from C++,\nor the `strtok()` function in C.\n\nWhen you use this `splitScalar()` function, you get an iterator as the result.\nThis iterator have a `next()` method that you can use to advance the iterator\nto the next position, or, to the next section of the splitted string.\nNote that, when you use `next()`, the method not only advances the iterator,\nbut it also returns a slice to the current section of the splitted\nstring as result.\n\nNow, if you want to get a slice to the current section of the splitted\nstring, but not advance the iterator to the next position, you can use\nthe `peek()` method. Both `next()` and `peek()` methods return an optional value, that is\nwhy I use the `?` method to unwrap these optional values.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn parse_request(text: []u8) Request {\n    const line_index = std.mem.indexOfScalar(\n        u8, text, '\\n'\n    ) orelse text.len;\n    var iterator = std.mem.splitScalar(\n        u8, text[0..line_index], ' '\n    );\n    const method = try Method.init(iterator.next().?);\n    const uri = iterator.next().?;\n    const version = iterator.next().?;\n    const request = Request.init(method, uri, version);\n    return request;\n}\n```\n:::\n\n\n\n\nAs I described in @sec-zig-strings, strings in Zig are simply arrays of bytes in the language.\nSo, you will find lots of excellent utility functions to work directly with strings\ninside this `mem` module from the Zig Standard Library.\nWe have described some of these useful utility functions already\nin @sec-strings-useful-funs.\n\n\n\n### Using the parse request function\n\nNow that we wrote the function responsible for parsing the HTTP Request,\nwe can add the function call to `parse_request()` in\nthe `main()` function of our program.\n\nAfter that, is a good idea to test once again the state of our program.\nI execute this program again with the `run` command from the `zig` compiler,\nthen, I use my web browser to connect once again to the server through the URL `localhost:3490`, and finally,\nthe end result of our `Request` object is printed to the console.\n\nA quick observation, since I have used the `any` format specifier in the\nprint statement, the data members `version` and `uri` of the `Request`\nstruct were printed as raw integer values. String data being printed\nas integer values is common in Zig, and remember, these integer values are just the decimal representation of\nthe bytes that form the string in question.\n\nIn the result below, the sequence of decimal values 72, 84, 84, 80, 47, 49, 46, 49, and 13,\nare the bytes that form the text \"HTTP/1.1\". And the integer 47, is the decimal value of\nthe character `/`, which represents our URI in this request.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst Request = @import(\"request.zig\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n    const socket = try SocketConf.Socket.init();\n    var server = try socket._address.listen(.{});\n    const connection = try server.accept();\n\n    var buffer: [1000]u8 = undefined;\n    for (0..buffer.len) |i| {\n        buffer[i] = 0;\n    }\n    try Request.read_request(\n        connection, buffer[0..buffer.len]\n    );\n    const request = Request.parse_request(\n        buffer[0..buffer.len]\n    );\n    try stdout.print(\"{any}\\n\", .{request});\n}\n```\n:::\n\n\n\n```\nrequest.Request{\n    .method = request.Method.GET,\n    .version = {72, 84, 84, 80, 47, 49, 46, 49, 13},\n    .uri = {47}\n}\n```\n\n\n\n### Sending the HTTP Response to the client\n\nIn this last part, we are going to write the logic responsible for\nsending the HTTP Response from the server to the client. To make things\nsimple, the server in this project will send just a simple web page\ncontaining the text \"Hello world\".\n\nFirst, I create a new Zig module in the project, named `response.zig`.\nIn this module, I will declare just two functions. Each function\ncorresponds to a specific status code in the HTTP Response.\nThe `send_200()` function will send a HTTP Response with status code 200\n(which means \"Success\") to the client. While the `send_404()` function sends a response\nwith status code 404 (which means \"Not found\").\n\nThis is definitely not the most ergonomic and adequate way of handling the\nHTTP Response, but it works for our case here. We are just building toy projects\nin this book after all, therefore, the source code that we write do not need to be perfect.\nIt just needs to work!\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Connection = std.net.Server.Connection;\npub fn send_200(conn: Connection) !void {\n    const message = (\n        \"HTTP/1.1 200 OK\\nContent-Length: 48\"\n        ++ \"\\nContent-Type: text/html\\n\"\n        ++ \"Connection: Closed\\n\\n\"\n        ++ \"

    Hello, World!

    \"\n );\n _ = try conn.stream.write(message);\n}\n\npub fn send_404(conn: Connection) !void {\n const message = (\n \"HTTP/1.1 404 Not Found\\nContent-Length: 50\"\n ++ \"\\nContent-Type: text/html\\n\"\n ++ \"Connection: Closed\\n\\n\"\n ++ \"

    File not found!

    \"\n );\n _ = try conn.stream.write(message);\n}\n```\n:::\n\n\n\nNotice that both functions receives the connection object as input, and\nuse the `write()` method to write the HTTP Response message directly\ninto this communication channel. As result, the party in the other\nside of the connection (i.e., the client), will receive such message.\n\nMost real-world HTTP Servers will have a single function (or a single struct) to effectively handle\nthe response. It gets the HTTP Request already parsed as input, and then, it tries to build\nthe HTTP Response bit by bit, before the function sends it over the connection.\n\nWe would also have a specialized struct to represent a HTTP Response, and\na lot of methods that would be used to build each part or component of the response object.\nTake the `Response` struct created by the Javascript runtime Bun as an example.\nYou can find this struct in the [`response.zig` module](https://github.com/oven-sh/bun/blob/main/src/bun.js/webcore/response.zig)[^bun-resp]\nin their GitHub project.\n\n[^bun-resp]: .\n\n\n## The end result\n\nWe can now, update once again our `main()` function to incorporate our new\nfunctions from the `response.zig` module. First, I need to import this module\ninto our `main.zig` module, then, I add the function calls to `send_200()`\nand `send_404()`.\n\nNotice that I'm using if statements to decide which \"response function\" to call,\nbased especially on the URI present in the HTTP Request. If the user asked for\na content (or a document) that is not present in our server, we should respond\nwith a 404 status code. But since we have just a simple HTTP server, with no\nreal documents to send, we can just check if the URI is the root path (`/`)\nor not to decide which function to call.\n\nAlso, notice that I'm using the function `std.mem.eql()` from the Zig Standard Library\nto check if the string from `uri` is equal or not the string `\"/\"`. We have\ndescribed this function already in @sec-strings-useful-funs, so, comeback to\nthat section if you are not familiar yet with this function.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst Request = @import(\"request.zig\");\nconst Response = @import(\"response.zig\");\nconst Method = Request.Method;\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n try stdout.print(\"Server Addr: {any}\\n\", .{socket._address});\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n\n var buffer: [1000]u8 = undefined;\n for (0..buffer.len) |i| {\n buffer[i] = 0;\n }\n try Request.read_request(connection, buffer[0..buffer.len]);\n const request = Request.parse_request(\n buffer[0..buffer.len]\n );\n if (request.method == Method.GET) {\n if (std.mem.eql(u8, request.uri, \"/\")) {\n try Response.send_200(connection);\n } else {\n try Response.send_404(connection);\n }\n }\n}\n```\n:::\n\n\n\n\nNow that we adjusted our `main()` function, I can now execute our program, and\nsee the effects of these last changes. First, I execute the program once again, with the\n`run` command of the `zig` compiler. The program will hang, waiting for a client to connect.\n\nThen, I open my web browser, and try to connect to the server again, using the URL `localhost:3490`.\nThis time, instead of getting some sort of an error message from the browser, you will get the message\n\"Hello World\" printed into your web browser. Because this time, the server sended the HTTP Response\nsuccessfully to the web browser, as demonstrated by @fig-print-zigrun3.\n\n\n![The Hello World message sent in the HTTP Response](./../Figures/print-zigrun3.png){#fig-print-zigrun3}\n", - "supporting": [ - "04-http-server_files" - ], - "filters": [ - "rmarkdown/pagebreak.lua" - ], - "includes": {}, - "engineDependencies": { - "knitr": [ - "{\"type\":\"list\",\"attributes\":{},\"value\":[]}" - ] - }, - "preserve": null, - "postProcess": false - } -} \ No newline at end of file diff --git a/_freeze/Chapters/04-http-server/execute-results/html.json b/_freeze/Chapters/04-http-server/execute-results/html.json index b09291c7..577dfb71 100644 --- a/_freeze/Chapters/04-http-server/execute-results/html.json +++ b/_freeze/Chapters/04-http-server/execute-results/html.json @@ -2,10 +2,8 @@ "hash": "f64c88659b4b19943ce530d1245b8add", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 2 - Building a HTTP Server from scratch\n\nIn this chapter, I want to implement a new\nsmall project with you. This time, we are going\nto implement a basic HTTP Server from scratch.\n\nThe Zig Standard Library already have a HTTP Server\nimplemented, which is available at `std.http.Server`.\nBut again, our objective here in this chapter, is to implement\nit **from scratch**. So we can't use this server object available\nfrom the Zig Standard Library.\n\n## What is a HTTP Server?\n\nFirst of all, what is a HTTP Server?\nA HTTP server, as any other type of server, is essentially\na program that runs indefinitely, on an infinite loop, waiting for incoming connections\nfrom clients. Once the server receives an incoming connection, it will\naccept this connection, and it will send messages back-and-forth to the client\nthrough this connection.\n\nBut the messages that are transmitted inside this connection are in a\nspecific format. They are HTTP messages\n(i.e., messages that use the HTTP Protocol specification).\nThe HTTP Protocol is the backbone of the modern web.\nThe world wide web as we know it today, would not exist without the\nHTTP Protocol.\n\nSo, Web servers (which is just a fancy name to\nHTTP Servers) are servers that exchange HTTP messages with clients.\nAnd these HTTP servers and the HTTP Protocol specification\nare essential to the operation of the world wide web today.\n\nThat is the whole picture of the process.\nAgain, we have two subjects involved here, a server (which is\na program that is running indefinitely, waiting to receive incoming connections),\nand a client (which is someone that wants to connect to the server,\nand exchange HTTP messages with it).\n\nYou may find the material about the [HTTP Protocol available at the Mozilla MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)[^mdn-http]\n, a great resource for you to also look at. It gives you a great overview on how\nHTTP works, and what role the server plays in this matter.\n\n[^mdn-http]: .\n\n\n## How a HTTP Server works? {#sec-how-http-works}\n\nImagine a HTTP Server as if it were the receptionist of a large hotel. In a hotel,\nyou have a reception, and inside that reception there is a receptionist\nwaiting for customers to arrive. A HTTP Server is essentially a receptionist\nthat is indefinitely waiting for new customers (or, in the context of HTTP, new clients)\nto arrive in the hotel.\n\nWhen a customer arrives at the hotel, that customer starts a conversation with the\nreceptionist. He tells the receptionist how many days he wants to stay at the hotel.\nThen, the receptionist search for an available apartment. If there is an available apartment\nat the moment, the customer pays the hotel fees, then, he gets the keys to the apartment,\nand then, he goes to the apartment to rest.\n\nAfter this entire process of dealing with the customer (searching for available apartments,\nreceiving payment, handing over the keys), the receptionist goes back to what he was\ndoing earlier, which is to wait. Wait for new customers to arrive.\n\nThat is, in a nutshell, what a HTTP Server do. It waits for clients to connect to the\nserver. When a client attempts to connect to the server, the server accepts this connection,\nand it starts to exchange messages with the client through this connection.\nThe first message that happens inside this connection is always a message from the client\nto the server. This message is called the *HTTP Request*.\n\nThis HTTP Request is a HTTP message that contains what\nthe client wants from the server. It is literally a request. The client\nthat connected to the server is asking this server to do something for him.\n\nThere are different \"types of request\" that a client can send to a HTTP Server.\nBut the most basic type of request, is when a client ask to the\nHTTP Server to serve (i.e., to send) some specific web page (which is a HTML file) to him.\nWhen you type `google.com` in your web browser, you are essentially sending a HTTP Request to Google's\nHTTP servers. This request is asking these servers to send the Google webpage to you.\n\nNonetheless, when the server receives this first message, the *HTTP Request*, it\nanalyzes this request, to understand: who the client is? What he wants the server to do?\nThis client has provided all the necessary information to perform the action that he\nasked? Etc.\n\nOnce the server understands what the client wants, he simply perform the action\nthat was requested, and, to finish the whole process, the server sends back\na HTTP message to the client, informing if the action performed was successful or not,\nand, at last, the server ends (or closes) the connection with the client.\n\nThis last HTTP message sent from the server to the client, is called the *HTTP Response*.\nBecause the server is responding to the action that was requested by the client.\nThe main objective of this response message is let the client know if the\naction requested was successful or not, before the server closes the connection.\n\n\n## How a HTTP server is normally implemented? {#sec-http-how-impl}\n\nLet's use the C language as an example. There are many materials\nteaching how to write a simple HTTP server in C code, like @jeffrey_http,\nor @nipun_http, or @eric_http.\nHaving this in mind, I will not show C code examples here, because you\ncan find them on the internet.\nBut I will describe the theory behind the necessary steps to create\nsuch HTTP server in C.\n\n\nIn essence, we normally implement a HTTP server in C by using a TCP socket,\nwhich involves the following steps:\n\n1. Create a TCP socket object.\n1. Bind a name (or more specifically, an address) to this socket object.\n1. Make this socket object to start listening and waiting for incoming connections.\n1. When a connection arrive, we accept this connection, and we exchange the HTTP messages (HTTP Request and HTTP Response).\n1. Then, we simply close this connection.\n\n\nA socket object is essentially a channel of communication.\nYou are creating a channel where people can send messages through.\nWhen you create a socket object, this object is not binded to any particular\naddress. This means that with this object you have a representation of a channel of communication\nin your hands. But this channel is not currently available, or, it is not currently accessible,\nbecause it does not have a known address where you can find it.\n\nThat is what the \"bind\" operation do. It binds a name (or more specifically, an address) to\nthis socket object, or, this channel of communication, so that it becomes available,\nor, accessible through this address. While the \"listen\" operation makes the socket object to\nlisten for incoming connections in this address. In other words, the \"listen\" operation\nmakes the socket wait for incoming connections.\n\nNow, when a client actually attempts to connect to the server through the socket address\nthat we have specified, in order to establish this connection with the client,\nthe socket object needs to accept this incoming connection. Thus, when we\naccept an incoming connection, the client and the server become\nconnected to each other, and they can start reading or writing messages into this\nestablished connection.\n\nAfter we receive the HTTP Request from the client, analyze it, and send the HTTP Response\nto the client, we can then close the connection, and end this communication.\n\n\n## Implementing the server - Part 1\n\n### Creating the socket object {#sec-create-socket}\n\nLet's begin with creating the socket object for our server.\nJust to make things shorter, I will create this socket object in\na separate Zig module. I will name it `config.zig`.\n\nIn Zig, we can create a TCP socket using\nthe `std.posix.socket()` function, from the Zig Standard Library.\nAs I mentioned earlier in @sec-http-how-impl, every socket object that we create\nrepresents a communication channel, and we need to bind this channel to a specific address.\nAn \"address\" is defined as an IP address, or, more specifically, an IPv4 address^[It can be also an IPv6 address. But normally, we use a IPv4 address for that.].\nEvery IPv4 address is composed by two components. The first component is the host,\nwhich is a sequence of 4 numbers separated by dot characters (`.`) that identifies the machine used.\nWhile the second component is a port number, which identifies the specific\ndoor, or, the specific port to use in the host machine.\n\nThe sequence of 4 numbers (i.e., the host) identifies the machine (i.e., the computer itself) where\nthis socket will live in. Every computer normally have multiple \"doors\" available inside of him, because\nthis allows the computer to receive and work with multiple connections at the same time.\nHe simply use a single door for each connection. So the port number, is\nessentially a number that identifies the specific door in the computer that will be responsible\nfor receiving the connection. That is, it identifies the \"door\" in the computer that the socket will use\nto receive incoming connections.\n\nTo make things simpler, I will use an IP address that identifies our current machine in this example.\nThis means that, our socket object will reside on the same computer that we are currently using\n(this is also known as the \"localhost\") to write this Zig source code.\n\nBy convention, the IP address that identifies the \"localhost\", which is the current machine we\nare using, is the IP `127.0.0.1`. So, that is the IP\naddress we are going to use in our server. I can declare it in Zig\nby using an array of 4 integers, like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst localhost = [4]u8{ 127, 0, 0, 1 };\n_ = localhost;\n```\n:::\n\n\n\n\nNow, we need to decide which port number to use. By convention, there are some\nport numbers that are reserved, meaning that, we cannot use them for our own\npurposes, like the port 22 (which is normally used for SSH connections).\nFor TCP connections, which is our case here,\na port number is a 16-bit unsigned integer (type `u16` in Zig),\nthus ranging from 0 to 65535 [@wikipedia_port].\nSo, we can choose\na number from 0 to 65535 for our port number. In the\nexample of this book, I will use the port number 3490\n(just a random number).\n\n\nNow that we have these two informations at hand, I can\nfinally create our socket object, using the `std.posix.socket()` function.\nFirst, we use the host and the port number to create an `Address` object,\nwith the `std.net.Address.initIp4()` function, like in the example below.\nAfter that, I use this address object inside the `socket()` function\nto create our socket object.\n\nThe `Socket` struct defined below summarizes all the logic behind\nthis process. In this struct, we have two data members, which are:\n1) the address object; 2) and a stream object, which is\nthe object we will use to read and write the messages into any connection we establish.\n\nNotice that, inside the constructor method of this struct,\nwhen we create the socket object, we are using the `IPROTO.TCP` property as an input to\ntell the function to create a socket for TCP connections.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\nconst net = @import(\"std\").net;\n\npub const Socket = struct {\n _address: std.net.Address,\n _stream: std.net.Stream,\n\n pub fn init() !Socket {\n const host = [4]u8{ 127, 0, 0, 1 };\n const port = 3490;\n const addr = net.Address.initIp4(host, port);\n const socket = try std.posix.socket(\n addr.any.family,\n std.posix.SOCK.STREAM,\n std.posix.IPPROTO.TCP\n );\n const stream = net.Stream{ .handle = socket };\n return Socket{ ._address = addr, ._stream = stream };\n }\n};\n```\n:::\n\n\n\n\n\n### Listening and receiving connections\n\nRemember that we stored the `Socket` struct\ndeclaration that we built in @sec-create-socket inside a Zig module named `config.zig`.\nThis is why I imported this module into our main module (`main.zig`) in the example below, as the `SocketConf` object,\nto access the `Socket` struct.\n\nOnce we created our socket object, we can focus now on making this socket object\nlisten and receive new incoming connections. We do that, by calling the `listen()`\nmethod from the `Address` object that is contained inside the socket object, and then,\nwe call the `accept()` method over the result.\n\nThe `listen()` method from the `Address` object produces a server object,\nwhich is an object that will stay open and running indefinitely, waiting\nto receive an incoming connection. Therefore, if you try to run the code\nexample below, by calling the `run` command from the `zig` compiler,\nyou will notice that the programs keeps running indefinitely,\nwithout a clear end.\n\nThis happens, because the program is waiting for something to happen.\nIt's waiting for someone to try to connect to the address (`http://127.0.0.1:3490`) where\nthe server is running and listening for incoming connections. This is what\nthe `listen()` method do, it makes the socket to be active waiting for someone\nto connect.\n\nOn the other side, the `accept()` method is the function that establishes the connection\nwhen someone tries to connect to the socket. This means that, the `accept()` method\nreturns a new connection object as a result. And you can use this connection object\nto read or write messages from or to the client.\nFor now, we are not doing anything with this connection object.\nBut we are going to use it in the next section.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n try stdout.print(\"Server Addr: {any}\\n\", .{socket._address});\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n _ = connection;\n}\n```\n:::\n\n\n\n\nThis code example allows one single connection. In other words, the\nserver will wait for one incoming connection, and as soon as the\nserver is done with this first connection that it establishes, the\nprogram ends, and the server stops.\n\nThis is not the norm in the real world. Most people that write\na HTTP server like this, usually put the `accept()` method\ninside a `while` (infinite) loop, where if a connection\nis created with `accept()`, a new thread of execution is created to deal with\nthis new connection and the client. That is, real-world examples of HTTP Servers\nnormally rely on parallel computing to work.\n\nWith this design, the server simply accepts the connection,\nand the whole process of dealing with the client, and receiving\nthe HTTP Request, and sending the HTTP Response, all of this\nis done in the background, on a separate execution thread.\n\nSo, as soon as the server accepts the connection, and creates\nthe separate thread, the server goes back to what he was doing earlier,\nwhich is to wait indefinitely for a new connection to accept.\nHaving this in mind, the code example exposed above, is a\nserver that serves only a single client. Because the program\nterminates as soon as the connection is accepted.\n\n\n\n### Reading the message from the client {#sec-read-http-message}\n\nNow that we have a connection established, i.e., the connection\nobject that we created through the `accept()` function, we can now\nuse this connection object to read any messages that the client\nsend to our server. But we can also use it to send messages back\nto the client.\n\nThe basic idea is, if we **write** any data into this connection object,\nthen, we are sending data to the client, and if we **read** the data present in\nthis connection object, then, we are reading any data that the\nclient sent to us, through this connection object. So, just\nhave this logic in mind. \"Read\" is for reading messages from the client,\nand \"write\" is to send a message to the client.\n\nRemember from @sec-how-http-works that, the first thing that we need to do is to read the HTTP Request\nsent by the client to our server. Because it is the first message that happens\ninside the established connection, and, as a consequence, it is the first\nthing that we need to deal with.\n\nThat is why, I'm going to create a new Zig module in this small project, named `request.zig`\nto keep all functions related to the HTTP Request\ntogether. Then, I will create a new function named `read_request()` that will\nuse our connection object to read the message sent by the client,\nwhich is the HTTP Request.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Connection = std.net.Server.Connection;\npub fn read_request(conn: Connection,\n buffer: []u8) !void {\n const reader = conn.stream.reader();\n _ = try reader.read(buffer);\n}\n```\n:::\n\n\n\n\n\nThis function accepts a slice object which behaves as a buffer.\nThe `read_request()` function reads the message sent into\nthe connection object, and saves this message into this buffer object that\nwe have provided as input.\n\nNotice that I'm using the connection object that we created to read\nthe message from the client. I first access the `reader` object that lives inside the\nconnection object. Then, I call the `read()` method of this `reader` object\nto effectively read and save the data sent by the client into the buffer object\nthat we created earlier. I'm discarding the return value\nof the `read()` method, by assigning it to the underscore character (`_`),\nbecause this return value is not useful for us right now.\n\n\n\n## Looking at the current state of the program\n\n\nI think now is a good time to see how our program is currently working. Shall we?\nSo, the first thing I will do is to update the `main.zig` module in our small Zig project,\nso that the `main()` function call this new `read_request()` function that we have just created.\nI will also add a print statement at the end of the `main()` function,\njust so that you can see what the HTTP Request that we have just loaded into the buffer object\nlooks like.\n\nAlso, I'm creating the buffer object in the `main()` function, which will be\nresponsible for storing the message sent by the client, and, I'm also\nusing a `for` loop to initialize all fields of this buffer object to the number zero.\nThis is important to make sure that we don't have uninitialized memory in\nthis object. Because uninitialized memory may cause undefined behaviour in our program.\n\nSince the `read_request()` function should receive as input the buffer object as a slice object (`[]u8`),\nI am using the syntax `array[0..array.len]` to get access to a slice of this `buffer` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst Request = @import(\"request.zig\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n try stdout.print(\"Server Addr: {any}\\n\", .{socket._address});\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n var buffer: [1000]u8 = undefined;\n for (0..buffer.len) |i| {\n buffer[i] = 0;\n }\n _ = try Request.read_request(\n connection, buffer[0..buffer.len]\n );\n try stdout.print(\"{s}\\n\", .{buffer});\n}\n```\n:::\n\n\n\n\nNow, I'm going to execute this program, with the `run` command from the\n`zig` compiler. But remember, as we sad earlier, as soon as I execute this program, it will\nhang indefinitely, because the program is waiting for a client trying to\nconnect to the server.\n\nMore specifically, the program will pause at the line\nwith the `accept()` call. As soon as a client try to connect to the\nserver, then, the execution will \"unpause\", and the `accept()` function\nwill finally be executed to create the\nconnection object that we need, and the remaining of the program\nwill run.\n\nYou can see that in @fig-print-zigrun1. The message `Server Addr: 127.0.0.1:3490`\nis printed to the console, and the program is now waiting for an incoming connection.\n\n![A screenshot of running the program](./../Figures/print-zigrun1.png){#fig-print-zigrun1}\n\n\nWe can finally try to connect to this server, and there are several ways we can do this.\nFor example, we could use the following Python script:\n\n```python\nimport requests\nrequests.get(\"http://127.0.0.1:3490\")\n```\n\nOr, we could also open any web browser of our preference, and type\nthe URL `localhost:3490`. OBS: `localhost` is the same thing as the\nIP `127.0.0.1`. When you press enter, and your web browser go\nto this address, first, the browser will probably print a message\nsaying that \"this page isn't working\", and, then, it will\nprobably change to a new message saying that \"the site can't be\nreached\".\n\nYou get these \"error messages\" in the web browser, because\nit got no response back from the server. In other words, when the web\nbrowser connected to our server, it did send the HTTP Request through the established connection.\nThen, the web browser was expecting to receive a HTTP Response back, but\nit got no response from the server (we didn't implemented the HTTP Response logic yet).\n\nBut that is okay. We have achieved the result that we wanted for now,\nwhich is to connect to the server, and see the HTTP Request\nthat was sent by the web browser (or by the Python script)\nto the server.\n\nIf you comeback to the console that you left open\nwhen you have executed the program, you will see that the\nprogram finished its execution, and, a new message is\nprinted in the console, which is the actual HTTP Request\nmessage that was sent by the web browser to the server.\nYou can see this message in @fig-print-zigrun2.\n\n![A screenshot of the HTTP Request sent by the web browser](./../Figures/print-zigrun2.png){#fig-print-zigrun2}\n\n\n\n\n## Learning about Enums in Zig {#sec-enum}\n\nEnums structures are available in Zig through the `enum` keyword.\nAn enum (short for \"enumeration\") is a special structure that represents a group of constant values.\nSo, if you have a variable which can assume a short and known\nset of values, you might want to associate this variable to an enum structure,\nto make sure that this variable only assumes a value from this set.\n\nA classic example for enums are primary colors. If for some reason, your program\nneeds to represent one of the primary colors, you can create an enum\nthat represents one of these colors.\nIn the example below, we are creating the enum `PrimaryColorRGB`, which\nrepresents a primary color from the RGB color system. By using this enum,\nI am guaranteed that the `acolor` object for example, will contain\none of these three values: `RED`, `GREEN` or `BLUE`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst PrimaryColorRGB = enum {\n RED, GREEN, BLUE\n};\nconst acolor = PrimaryColorRGB.RED;\n_ = acolor;\n```\n:::\n\n\n\n\nIf for some reason, my code tries to save in `acolor`,\na value that is not in this set, I will get an error message\nwarning me that a value such as \"MAGENTA\" do not exist\ninside the `PrimaryColorRGB` enum.\nThen I can easily fix my mistake.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst acolor = PrimaryColorRGB.MAGENTA;\n```\n:::\n\n\n\n\n```\ne1.zig:5:36: error: enum 'PrimaryColorRGB' has\n no member named 'MAGENTA':\n const acolor = PrimaryColorRGB.MAGENTA;\n ^~~~~~~\n```\n\nBehind the hood, enums in Zig work the same way that enums\nwork in C. Each enum value is essentially represented as an integer.\nThe first value in the set is represented as zero,\nthen, the second value is one, ... etc.\n\nOne thing that we are going to learn in the next section is that\nenums can have methods in them. Wait... What? This is amazing!\nYes, enums in Zig are similar to structs, and they can have\nprivate and public methods inside them.\n\n\n\n\n\n\n\n## Implementing the server - Part 2\n\nNow, on this section, I want to focus on parsing\nthe HTTP Request that we received from the client.\nHowever, to effectively parse a HTTP Request message, we first need to understand its\nstructure.\nIn summary, a HTTP Request is a text message that is divided into 3 different\nsections (or parts):\n\n- The top-level header indicating the method of the HTTP Request, the URI, and the HTTP version used in the message.\n- A list of HTTP Headers.\n- The body of the HTTP Request.\n\n### The top-level header\n\nThe first line of text in a HTTP Request always come with the three most essential\ninformation about the request. These three key attributes of the HTTP Request\nare separated by a simple space in this first line of the request.\nThe first information is the HTTP method that is being\nused in the request, second, we have the URI to which this HTTP Request is being sent to,\nand third, we have the version of the HTTP protocol that is being used in this HTTP Request.\n\nIn the snippet below, you can find an example of this first line in a HTTP Request.\nFirst, we have the HTTP method of this request (`GET`). Many programmers\nrefer to the URI component (`/users/list`) as the \"API endpoint\" to which the HTTP Request\nis being sent to. In the context of this specific request, since it's a GET request,\nyou could also say that the URI component is the path to the resource we want to access,\nor, the path to the document (or the file) that we want to retrieve from the server.\n\n```\nGET /users/list HTTP/1.1\n```\n\nAlso, notice that this HTTP Request is using the version 1.1 of the HTTP protocol,\nwhich is the most popular version of the protocol used in the web.\n\n\n\n### The list of HTTP headers\n\nMost HTTP Requests also include a section of HTTP Headers,\nwhich is just a list of attributes or key-value pairs associated with this\nparticular request. This section always comes right after the \"top-level header\" of the request.\n\nFor our purpose in this chapter, which is to build a simple HTTP Server,\nwe are going to ignore this section of the HTTP Request, for simplicity.\nBut most HTTP servers that exist in the wild parses and use these\nHTTP headers to change the way that the server responds to the request\nsent by the client.\n\nFor example, many requests we encounter in the real-world comes with\na HTTP header called `Accept`. In this header, we find a list of [MIME types](https://en.wikipedia.org/wiki/Media_type)[^mime].\nThis list indicates the file formats that the client can read, or parse, or interpret.\nIn other words, you also interpret this header as the client saying the following phrase\nto the server: \"Hey! Look, I can read only HTML documents, so please, send me back\na document that is in a HTML format.\".\n\n[^mime]: .\n\nIf the HTTP server can read and use this `Accept` header, then, the server can identify\nwhich is the best file format for the document to be sent to the client. Maybe the HTTP server have\nthe same document in multiple formats, for example, in JSON, in XML, in HTML and in PDF,\nbut the client can only understand documents in the HTML format. That is the purpose\nof this `Accept` header.\n\n\n### The body\n\nThe body comes after the list of HTTP headers, and it's an optional section of the HTTP Request, meaning that, not\nall HTTP Requests will come with a body in them. For example, every HTTP Request that uses the\nGET method usually does not come with a body.\n\nBecause a GET request is used to request data, instead of sending it to the server.\nSo, the body section is more related to the POST method, which is a method that involves\nsending data to the server, to be processed and stored.\n\nSince we are going to support only the GET method in this project, it means that\nwe also do not need to care about the body of the request.\n\n\n\n### Creating the HTTP Method enum\n\nEvery HTTP Request comes with a explicit method. The method used in a HTTP Request\nis identified by one these words:\n\n- GET;\n- POST;\n- OPTIONS;\n- PATCH;\n- DELETE;\n- and some other methods.\n\nEach HTTP method is used for a specific type of task. The POST method for example is normally\nused to post some data into the destination. In other words, it's used\nto send some data to the HTTP server, so that it can be processed and stored by the server.\n\nAs another example, the GET method is normally used to get content from the server.\nIn other words, we use this method whenever we want the server to send some\ncontent back to us. It can be any type of content. It can be a web page,\na document file, or some data in a JSON format.\n\nWhen a client sends a POST HTTP Request, the HTTP Response sent by the server normally have the sole purpose of\nletting the client know if the server processed and stored the data successfully.\nIn contrast, when the server receives a GET HTTP Request, then, the server sends the content\nthat the client asked for in the HTTP Response itself. This demonstrates that the method associated\nwith the HTTP Request changes a lot on the dynamics and the roles that each party\nplays in the whole process.\n\nSince the HTTP method of the HTTP Request is identified by this very small and specific\nset of words, it would be interesting to create an enum structure to represent a HTTP method.\nThis way, we can easily check if the HTTP Request we receive from the client is a\nHTTP method that we currently support in our small HTTP server project.\n\nThe `Method` structure below represents this enumeration.\nNotice that, for now, only the GET HTTP method is included in this\nenumeration. Because, for the purpose of this chapter, I want to\nimplement only the GET HTTP method. That is why I am not\nincluding the other HTTP methods in this enumeration.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Method = enum {\n GET\n};\n```\n:::\n\n\n\n\n\nNow, I think we should add two methods to this enum structure. One method is `is_supported()`,\nwhich will be a function that returns a boolean value, indicating if the input HTTP method is supported\nor not by our HTTP Server. The other is `init()`, which is a constructor function that takes a string as input,\nand tries to convert it into a `Method` value.\n\n\nBut in order to build these functions, I will use a functionality from the Zig Standard Library, called\n`StaticStringMap()`. This function allows us to create a simple map from strings to enum values.\nIn other words, we can use this map structure to map a string to the respective enum value.\nTo some extent, this specific structure from the standard library works almost like a \"hashtable\" structure,\nand it's optimized for small sets of words, or, small sets of keys, which is our case here.\nWe are going to talk more about hashtables in Zig in @sec-maps-hashtables.\n\nTo use this \"static string map\" structure, you have to import it from the `std.static_string_map` module\nof the Zig Standard Library. Just to make things shorter and easier to type, I am going to import this\nfunction through a different and shorter name (`Map`).\n\nWith `Map()` imported, we can just apply this function over the enum structure\nthat we are going to use in the resulting map. In our case here, it's the `Method` enum structure\nthat we declared at the last code example. Then, I call the `initComptime()` method with the\nmap, i.e., the list of key-value pairs that we are going to use.\n\nYou can see in the example below that I wrote this map using multiple anonymous struct literals.\nInside the first (or \"top-level\") struct literal, we have a list (or a sequence) of struct literals.\nEach struct literal in this list represents a separate key-value pair. The first element (or the key)\nin each key-value pair should always be a string value. While the second element should\nbe a value from the enum structure that you have used inside the `Map()` function.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Map = std.static_string_map.StaticStringMap;\nconst MethodMap = Map(Method).initComptime(.{\n .{ \"GET\", Method.GET },\n});\n```\n:::\n\n\n\n\nTherefore, the `MethodMap` object is basically a `std::map` object from C++, or,\na `dict` object from Python. You can retrieve (or get) the enum value that\ncorresponds to a particular key, by using the `get()` method from the map\nobject. This method returns an optional value, so, the `get()` method might\nresult in a null value.\n\nWe can use this in our advantage to detect if a particular HTTP method is\nsupported or not in our HTTP server. Because, if the `get()` method returns null,\nit means that it did not found the method that we provided inside the `MethodMap` object, and,\nas a consequence, this method is not supported by our HTTP server.\n\nThe `init()` method below, takes a string value as input, and then, it simply passes this string value\nto the `get()` method of our `MethodMap` object. As consequence, we should get the enum value that corresponds\nto this input string.\n\nNotice in the example below that, the `init()` method returns either an error\n(which might happen if the `?` method returns `unreacheable`, checkout @sec-null-handling for more details)\nor a `Method` object as result. Since `GET` is currently the only value in our `Method` enum\nstructure, it means that, the `init()` method will most likely return the value `Method.GET` as result.\n\nAlso notice that, in the `is_supported()` method, we are using the optional value returned\nby the `get()` method from our `MethodMap` object. The if statement unwraps the optional value\nreturned by this method, and returns `true` in case this optional value is a not-null value.\nOtherwise, it simply returns `false`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Method = enum {\n GET,\n pub fn init(text: []const u8) !Method {\n return MethodMap.get(text).?;\n }\n pub fn is_supported(m: []const u8) bool {\n const method = MethodMap.get(m);\n if (method) |_| {\n return true;\n }\n return false;\n }\n};\n```\n:::\n\n\n\n\n\n\n\n\n\n\n### Writing the parse request function\n\nNow that we created the enum that represents our HTTP method,\nwe should start to write the function responsible for\nactually parsing the HTTP Request.\n\nThe first thing we can do, is to write a struct to represent the HTTP Request.\nTake the `Request` struct below as an example. It contains the three\nessential information from the \"top-level\" header (i.e., the first line)\nin the HTTP Request.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Request = struct {\n method: Method,\n version: []const u8,\n uri: []const u8,\n pub fn init(method: Method,\n uri: []const u8,\n version: []const u8) Request {\n return Request{\n .method = method,\n .uri = uri,\n .version = version,\n };\n }\n};\n```\n:::\n\n\n\n\n\nThe `parse_request()` function should receive a string as input. This input string\ncontains the entire HTTP Request message, and the parsing function should\nread and understand the individual parts of this message.\n\nNow, remember that for the purpose of this chapter, we care only about the first\nline in this message, which contains the \"top-level header\", or, the three essential attributes about the HTTP Request,\nwhich are the HTTP method used, the URI and the HTTP version.\n\nNotice that I use the function `indexOfScalar()` in `parse_request()`. This function from the\nZig Standard Library returns the first index where the scalar value that we provide\nhappens in a string. In this case, I'm looking at the first occurrence of the new line character (`\\n`).\nBecause once again, we care only about the first line in the HTTP Request message.\nThis is the line where we have the three information that we want to parse\n(version of HTTP, the HTTP method and the URI).\n\nTherefore, we are using this `indexOfScalar()` function\nto limit our parsing process to the first line in the message.\nIt's also worth mentioning that, the `indexOfScalar()` function returns an optional value.\nThat is why I use the `orelse` keyword to provide an alternative value, in case\nthe value returned by the function is a null value.\n\nSince each of these three attributes are separated by a simple space, we\ncould use the function `splitScalar()` from the Zig Standard Library to split\nthe input string into sections by looking for every position that appears\na simple space. In other words, this `splitScalar()` function is equivalent\nto the `split()` method in Python, or, the `std::getline()` function from C++,\nor the `strtok()` function in C.\n\nWhen you use this `splitScalar()` function, you get an iterator as the result.\nThis iterator have a `next()` method that you can use to advance the iterator\nto the next position, or, to the next section of the splitted string.\nNote that, when you use `next()`, the method not only advances the iterator,\nbut it also returns a slice to the current section of the splitted\nstring as result.\n\nNow, if you want to get a slice to the current section of the splitted\nstring, but not advance the iterator to the next position, you can use\nthe `peek()` method. Both `next()` and `peek()` methods return an optional value, that is\nwhy I use the `?` method to unwrap these optional values.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn parse_request(text: []u8) Request {\n const line_index = std.mem.indexOfScalar(\n u8, text, '\\n'\n ) orelse text.len;\n var iterator = std.mem.splitScalar(\n u8, text[0..line_index], ' '\n );\n const method = try Method.init(iterator.next().?);\n const uri = iterator.next().?;\n const version = iterator.next().?;\n const request = Request.init(method, uri, version);\n return request;\n}\n```\n:::\n\n\n\n\n\nAs I described in @sec-zig-strings, strings in Zig are simply arrays of bytes in the language.\nSo, you will find lots of excellent utility functions to work directly with strings\ninside this `mem` module from the Zig Standard Library.\nWe have described some of these useful utility functions already\nin @sec-strings-useful-funs.\n\n\n\n### Using the parse request function\n\nNow that we wrote the function responsible for parsing the HTTP Request,\nwe can add the function call to `parse_request()` in\nthe `main()` function of our program.\n\nAfter that, is a good idea to test once again the state of our program.\nI execute this program again with the `run` command from the `zig` compiler,\nthen, I use my web browser to connect once again to the server through the URL `localhost:3490`, and finally,\nthe end result of our `Request` object is printed to the console.\n\nA quick observation, since I have used the `any` format specifier in the\nprint statement, the data members `version` and `uri` of the `Request`\nstruct were printed as raw integer values. String data being printed\nas integer values is common in Zig, and remember, these integer values are just the decimal representation of\nthe bytes that form the string in question.\n\nIn the result below, the sequence of decimal values 72, 84, 84, 80, 47, 49, 46, 49, and 13,\nare the bytes that form the text \"HTTP/1.1\". And the integer 47, is the decimal value of\nthe character `/`, which represents our URI in this request.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst Request = @import(\"request.zig\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n\n var buffer: [1000]u8 = undefined;\n for (0..buffer.len) |i| {\n buffer[i] = 0;\n }\n try Request.read_request(\n connection, buffer[0..buffer.len]\n );\n const request = Request.parse_request(\n buffer[0..buffer.len]\n );\n try stdout.print(\"{any}\\n\", .{request});\n}\n```\n:::\n\n\n\n\n```\nrequest.Request{\n .method = request.Method.GET,\n .version = {72, 84, 84, 80, 47, 49, 46, 49, 13},\n .uri = {47}\n}\n```\n\n\n\n### Sending the HTTP Response to the client\n\nIn this last part, we are going to write the logic responsible for\nsending the HTTP Response from the server to the client. To make things\nsimple, the server in this project will send just a simple web page\ncontaining the text \"Hello world\".\n\nFirst, I create a new Zig module in the project, named `response.zig`.\nIn this module, I will declare just two functions. Each function\ncorresponds to a specific status code in the HTTP Response.\nThe `send_200()` function will send a HTTP Response with status code 200\n(which means \"Success\") to the client. While the `send_404()` function sends a response\nwith status code 404 (which means \"Not found\").\n\nThis is definitely not the most ergonomic and adequate way of handling the\nHTTP Response, but it works for our case here. We are just building toy projects\nin this book after all, therefore, the source code that we write do not need to be perfect.\nIt just needs to work!\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Connection = std.net.Server.Connection;\npub fn send_200(conn: Connection) !void {\n const message = (\n \"HTTP/1.1 200 OK\\nContent-Length: 48\"\n ++ \"\\nContent-Type: text/html\\n\"\n ++ \"Connection: Closed\\n\\n\"\n ++ \"

    Hello, World!

    \"\n );\n _ = try conn.stream.write(message);\n}\n\npub fn send_404(conn: Connection) !void {\n const message = (\n \"HTTP/1.1 404 Not Found\\nContent-Length: 50\"\n ++ \"\\nContent-Type: text/html\\n\"\n ++ \"Connection: Closed\\n\\n\"\n ++ \"

    File not found!

    \"\n );\n _ = try conn.stream.write(message);\n}\n```\n:::\n\n\n\n\nNotice that both functions receives the connection object as input, and\nuse the `write()` method to write the HTTP Response message directly\ninto this communication channel. As result, the party in the other\nside of the connection (i.e., the client), will receive such message.\n\nMost real-world HTTP Servers will have a single function (or a single struct) to effectively handle\nthe response. It gets the HTTP Request already parsed as input, and then, it tries to build\nthe HTTP Response bit by bit, before the function sends it over the connection.\n\nWe would also have a specialized struct to represent a HTTP Response, and\na lot of methods that would be used to build each part or component of the response object.\nTake the `Response` struct created by the Javascript runtime Bun as an example.\nYou can find this struct in the [`response.zig` module](https://github.com/oven-sh/bun/blob/main/src/bun.js/webcore/response.zig)[^bun-resp]\nin their GitHub project.\n\n[^bun-resp]: .\n\n\n## The end result\n\nWe can now, update once again our `main()` function to incorporate our new\nfunctions from the `response.zig` module. First, I need to import this module\ninto our `main.zig` module, then, I add the function calls to `send_200()`\nand `send_404()`.\n\nNotice that I'm using if statements to decide which \"response function\" to call,\nbased especially on the URI present in the HTTP Request. If the user asked for\na content (or a document) that is not present in our server, we should respond\nwith a 404 status code. But since we have just a simple HTTP server, with no\nreal documents to send, we can just check if the URI is the root path (`/`)\nor not to decide which function to call.\n\nAlso, notice that I'm using the function `std.mem.eql()` from the Zig Standard Library\nto check if the string from `uri` is equal or not the string `\"/\"`. We have\ndescribed this function already in @sec-strings-useful-funs, so, comeback to\nthat section if you are not familiar yet with this function.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst Request = @import(\"request.zig\");\nconst Response = @import(\"response.zig\");\nconst Method = Request.Method;\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n try stdout.print(\"Server Addr: {any}\\n\", .{socket._address});\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n\n var buffer: [1000]u8 = undefined;\n for (0..buffer.len) |i| {\n buffer[i] = 0;\n }\n try Request.read_request(connection, buffer[0..buffer.len]);\n const request = Request.parse_request(\n buffer[0..buffer.len]\n );\n if (request.method == Method.GET) {\n if (std.mem.eql(u8, request.uri, \"/\")) {\n try Response.send_200(connection);\n } else {\n try Response.send_404(connection);\n }\n }\n}\n```\n:::\n\n\n\n\n\nNow that we adjusted our `main()` function, I can now execute our program, and\nsee the effects of these last changes. First, I execute the program once again, with the\n`run` command of the `zig` compiler. The program will hang, waiting for a client to connect.\n\nThen, I open my web browser, and try to connect to the server again, using the URL `localhost:3490`.\nThis time, instead of getting some sort of an error message from the browser, you will get the message\n\"Hello World\" printed into your web browser. Because this time, the server sended the HTTP Response\nsuccessfully to the web browser, as demonstrated by @fig-print-zigrun3.\n\n\n![The Hello World message sent in the HTTP Response](./../Figures/print-zigrun3.png){#fig-print-zigrun3}\n", - "supporting": [ - "04-http-server_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n# Project 2 - Building a HTTP Server from scratch\n\nIn this chapter, I want to implement a new\nsmall project with you. This time, we are going\nto implement a basic HTTP Server from scratch.\n\nThe Zig Standard Library already have a HTTP Server\nimplemented, which is available at `std.http.Server`.\nBut again, our objective here in this chapter, is to implement\nit **from scratch**. So we can't use this server object available\nfrom the Zig Standard Library.\n\n## What is a HTTP Server?\n\nFirst of all, what is a HTTP Server?\nA HTTP server, as any other type of server, is essentially\na program that runs indefinitely, on an infinite loop, waiting for incoming connections\nfrom clients. Once the server receives an incoming connection, it will\naccept this connection, and it will send messages back-and-forth to the client\nthrough this connection.\n\nBut the messages that are transmitted inside this connection are in a\nspecific format. They are HTTP messages\n(i.e., messages that use the HTTP Protocol specification).\nThe HTTP Protocol is the backbone of the modern web.\nThe world wide web as we know it today, would not exist without the\nHTTP Protocol.\n\nSo, Web servers (which is just a fancy name to\nHTTP Servers) are servers that exchange HTTP messages with clients.\nAnd these HTTP servers and the HTTP Protocol specification\nare essential to the operation of the world wide web today.\n\nThat is the whole picture of the process.\nAgain, we have two subjects involved here, a server (which is\na program that is running indefinitely, waiting to receive incoming connections),\nand a client (which is someone that wants to connect to the server,\nand exchange HTTP messages with it).\n\nYou may find the material about the [HTTP Protocol available at the Mozilla MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)[^mdn-http]\n, a great resource for you to also look at. It gives you a great overview on how\nHTTP works, and what role the server plays in this matter.\n\n[^mdn-http]: .\n\n\n## How a HTTP Server works? {#sec-how-http-works}\n\nImagine a HTTP Server as if it were the receptionist of a large hotel. In a hotel,\nyou have a reception, and inside that reception there is a receptionist\nwaiting for customers to arrive. A HTTP Server is essentially a receptionist\nthat is indefinitely waiting for new customers (or, in the context of HTTP, new clients)\nto arrive in the hotel.\n\nWhen a customer arrives at the hotel, that customer starts a conversation with the\nreceptionist. He tells the receptionist how many days he wants to stay at the hotel.\nThen, the receptionist search for an available apartment. If there is an available apartment\nat the moment, the customer pays the hotel fees, then, he gets the keys to the apartment,\nand then, he goes to the apartment to rest.\n\nAfter this entire process of dealing with the customer (searching for available apartments,\nreceiving payment, handing over the keys), the receptionist goes back to what he was\ndoing earlier, which is to wait. Wait for new customers to arrive.\n\nThat is, in a nutshell, what a HTTP Server do. It waits for clients to connect to the\nserver. When a client attempts to connect to the server, the server accepts this connection,\nand it starts to exchange messages with the client through this connection.\nThe first message that happens inside this connection is always a message from the client\nto the server. This message is called the *HTTP Request*.\n\nThis HTTP Request is a HTTP message that contains what\nthe client wants from the server. It is literally a request. The client\nthat connected to the server is asking this server to do something for him.\n\nThere are different \"types of request\" that a client can send to a HTTP Server.\nBut the most basic type of request, is when a client ask to the\nHTTP Server to serve (i.e., to send) some specific web page (which is a HTML file) to him.\nWhen you type `google.com` in your web browser, you are essentially sending a HTTP Request to Google's\nHTTP servers. This request is asking these servers to send the Google webpage to you.\n\nNonetheless, when the server receives this first message, the *HTTP Request*, it\nanalyzes this request, to understand: who the client is? What he wants the server to do?\nThis client has provided all the necessary information to perform the action that he\nasked? Etc.\n\nOnce the server understands what the client wants, he simply perform the action\nthat was requested, and, to finish the whole process, the server sends back\na HTTP message to the client, informing if the action performed was successful or not,\nand, at last, the server ends (or closes) the connection with the client.\n\nThis last HTTP message sent from the server to the client, is called the *HTTP Response*.\nBecause the server is responding to the action that was requested by the client.\nThe main objective of this response message is let the client know if the\naction requested was successful or not, before the server closes the connection.\n\n\n## How a HTTP server is normally implemented? {#sec-http-how-impl}\n\nLet's use the C language as an example. There are many materials\nteaching how to write a simple HTTP server in C code, like @jeffrey_http,\nor @nipun_http, or @eric_http.\nHaving this in mind, I will not show C code examples here, because you\ncan find them on the internet.\nBut I will describe the theory behind the necessary steps to create\nsuch HTTP server in C.\n\n\nIn essence, we normally implement a HTTP server in C by using a TCP socket,\nwhich involves the following steps:\n\n1. Create a TCP socket object.\n1. Bind a name (or more specifically, an address) to this socket object.\n1. Make this socket object to start listening and waiting for incoming connections.\n1. When a connection arrive, we accept this connection, and we exchange the HTTP messages (HTTP Request and HTTP Response).\n1. Then, we simply close this connection.\n\n\nA socket object is essentially a channel of communication.\nYou are creating a channel where people can send messages through.\nWhen you create a socket object, this object is not binded to any particular\naddress. This means that with this object you have a representation of a channel of communication\nin your hands. But this channel is not currently available, or, it is not currently accessible,\nbecause it does not have a known address where you can find it.\n\nThat is what the \"bind\" operation do. It binds a name (or more specifically, an address) to\nthis socket object, or, this channel of communication, so that it becomes available,\nor, accessible through this address. While the \"listen\" operation makes the socket object to\nlisten for incoming connections in this address. In other words, the \"listen\" operation\nmakes the socket wait for incoming connections.\n\nNow, when a client actually attempts to connect to the server through the socket address\nthat we have specified, in order to establish this connection with the client,\nthe socket object needs to accept this incoming connection. Thus, when we\naccept an incoming connection, the client and the server become\nconnected to each other, and they can start reading or writing messages into this\nestablished connection.\n\nAfter we receive the HTTP Request from the client, analyze it, and send the HTTP Response\nto the client, we can then close the connection, and end this communication.\n\n\n## Implementing the server - Part 1\n\n### Creating the socket object {#sec-create-socket}\n\nLet's begin with creating the socket object for our server.\nJust to make things shorter, I will create this socket object in\na separate Zig module. I will name it `config.zig`.\n\nIn Zig, we can create a TCP socket using\nthe `std.posix.socket()` function, from the Zig Standard Library.\nAs I mentioned earlier in @sec-http-how-impl, every socket object that we create\nrepresents a communication channel, and we need to bind this channel to a specific address.\nAn \"address\" is defined as an IP address, or, more specifically, an IPv4 address^[It can be also an IPv6 address. But normally, we use a IPv4 address for that.].\nEvery IPv4 address is composed by two components. The first component is the host,\nwhich is a sequence of 4 numbers separated by dot characters (`.`) that identifies the machine used.\nWhile the second component is a port number, which identifies the specific\ndoor, or, the specific port to use in the host machine.\n\nThe sequence of 4 numbers (i.e., the host) identifies the machine (i.e., the computer itself) where\nthis socket will live in. Every computer normally have multiple \"doors\" available inside of him, because\nthis allows the computer to receive and work with multiple connections at the same time.\nHe simply use a single door for each connection. So the port number, is\nessentially a number that identifies the specific door in the computer that will be responsible\nfor receiving the connection. That is, it identifies the \"door\" in the computer that the socket will use\nto receive incoming connections.\n\nTo make things simpler, I will use an IP address that identifies our current machine in this example.\nThis means that, our socket object will reside on the same computer that we are currently using\n(this is also known as the \"localhost\") to write this Zig source code.\n\nBy convention, the IP address that identifies the \"localhost\", which is the current machine we\nare using, is the IP `127.0.0.1`. So, that is the IP\naddress we are going to use in our server. I can declare it in Zig\nby using an array of 4 integers, like this:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst localhost = [4]u8{ 127, 0, 0, 1 };\n_ = localhost;\n```\n:::\n\n\nNow, we need to decide which port number to use. By convention, there are some\nport numbers that are reserved, meaning that, we cannot use them for our own\npurposes, like the port 22 (which is normally used for SSH connections).\nFor TCP connections, which is our case here,\na port number is a 16-bit unsigned integer (type `u16` in Zig),\nthus ranging from 0 to 65535 [@wikipedia_port].\nSo, we can choose\na number from 0 to 65535 for our port number. In the\nexample of this book, I will use the port number 3490\n(just a random number).\n\n\nNow that we have these two informations at hand, I can\nfinally create our socket object, using the `std.posix.socket()` function.\nFirst, we use the host and the port number to create an `Address` object,\nwith the `std.net.Address.initIp4()` function, like in the example below.\nAfter that, I use this address object inside the `socket()` function\nto create our socket object.\n\nThe `Socket` struct defined below summarizes all the logic behind\nthis process. In this struct, we have two data members, which are:\n1) the address object; 2) and a stream object, which is\nthe object we will use to read and write the messages into any connection we establish.\n\nNotice that, inside the constructor method of this struct,\nwhen we create the socket object, we are using the `IPROTO.TCP` property as an input to\ntell the function to create a socket for TCP connections.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst builtin = @import(\"builtin\");\nconst net = @import(\"std\").net;\n\npub const Socket = struct {\n _address: std.net.Address,\n _stream: std.net.Stream,\n\n pub fn init() !Socket {\n const host = [4]u8{ 127, 0, 0, 1 };\n const port = 3490;\n const addr = net.Address.initIp4(host, port);\n const socket = try std.posix.socket(\n addr.any.family,\n std.posix.SOCK.STREAM,\n std.posix.IPPROTO.TCP\n );\n const stream = net.Stream{ .handle = socket };\n return Socket{ ._address = addr, ._stream = stream };\n }\n};\n```\n:::\n\n\n\n### Listening and receiving connections\n\nRemember that we stored the `Socket` struct\ndeclaration that we built in @sec-create-socket inside a Zig module named `config.zig`.\nThis is why I imported this module into our main module (`main.zig`) in the example below, as the `SocketConf` object,\nto access the `Socket` struct.\n\nOnce we created our socket object, we can focus now on making this socket object\nlisten and receive new incoming connections. We do that, by calling the `listen()`\nmethod from the `Address` object that is contained inside the socket object, and then,\nwe call the `accept()` method over the result.\n\nThe `listen()` method from the `Address` object produces a server object,\nwhich is an object that will stay open and running indefinitely, waiting\nto receive an incoming connection. Therefore, if you try to run the code\nexample below, by calling the `run` command from the `zig` compiler,\nyou will notice that the programs keeps running indefinitely,\nwithout a clear end.\n\nThis happens, because the program is waiting for something to happen.\nIt's waiting for someone to try to connect to the address (`http://127.0.0.1:3490`) where\nthe server is running and listening for incoming connections. This is what\nthe `listen()` method do, it makes the socket to be active waiting for someone\nto connect.\n\nOn the other side, the `accept()` method is the function that establishes the connection\nwhen someone tries to connect to the socket. This means that, the `accept()` method\nreturns a new connection object as a result. And you can use this connection object\nto read or write messages from or to the client.\nFor now, we are not doing anything with this connection object.\nBut we are going to use it in the next section.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n try stdout.print(\"Server Addr: {any}\\n\", .{socket._address});\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n _ = connection;\n}\n```\n:::\n\n\nThis code example allows one single connection. In other words, the\nserver will wait for one incoming connection, and as soon as the\nserver is done with this first connection that it establishes, the\nprogram ends, and the server stops.\n\nThis is not the norm in the real world. Most people that write\na HTTP server like this, usually put the `accept()` method\ninside a `while` (infinite) loop, where if a connection\nis created with `accept()`, a new thread of execution is created to deal with\nthis new connection and the client. That is, real-world examples of HTTP Servers\nnormally rely on parallel computing to work.\n\nWith this design, the server simply accepts the connection,\nand the whole process of dealing with the client, and receiving\nthe HTTP Request, and sending the HTTP Response, all of this\nis done in the background, on a separate execution thread.\n\nSo, as soon as the server accepts the connection, and creates\nthe separate thread, the server goes back to what he was doing earlier,\nwhich is to wait indefinitely for a new connection to accept.\nHaving this in mind, the code example exposed above, is a\nserver that serves only a single client. Because the program\nterminates as soon as the connection is accepted.\n\n\n\n### Reading the message from the client {#sec-read-http-message}\n\nNow that we have a connection established, i.e., the connection\nobject that we created through the `accept()` function, we can now\nuse this connection object to read any messages that the client\nsend to our server. But we can also use it to send messages back\nto the client.\n\nThe basic idea is, if we **write** any data into this connection object,\nthen, we are sending data to the client, and if we **read** the data present in\nthis connection object, then, we are reading any data that the\nclient sent to us, through this connection object. So, just\nhave this logic in mind. \"Read\" is for reading messages from the client,\nand \"write\" is to send a message to the client.\n\nRemember from @sec-how-http-works that, the first thing that we need to do is to read the HTTP Request\nsent by the client to our server. Because it is the first message that happens\ninside the established connection, and, as a consequence, it is the first\nthing that we need to deal with.\n\nThat is why, I'm going to create a new Zig module in this small project, named `request.zig`\nto keep all functions related to the HTTP Request\ntogether. Then, I will create a new function named `read_request()` that will\nuse our connection object to read the message sent by the client,\nwhich is the HTTP Request.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Connection = std.net.Server.Connection;\npub fn read_request(conn: Connection,\n buffer: []u8) !void {\n const reader = conn.stream.reader();\n _ = try reader.read(buffer);\n}\n```\n:::\n\n\n\nThis function accepts a slice object which behaves as a buffer.\nThe `read_request()` function reads the message sent into\nthe connection object, and saves this message into this buffer object that\nwe have provided as input.\n\nNotice that I'm using the connection object that we created to read\nthe message from the client. I first access the `reader` object that lives inside the\nconnection object. Then, I call the `read()` method of this `reader` object\nto effectively read and save the data sent by the client into the buffer object\nthat we created earlier. I'm discarding the return value\nof the `read()` method, by assigning it to the underscore character (`_`),\nbecause this return value is not useful for us right now.\n\n\n\n## Looking at the current state of the program\n\n\nI think now is a good time to see how our program is currently working. Shall we?\nSo, the first thing I will do is to update the `main.zig` module in our small Zig project,\nso that the `main()` function call this new `read_request()` function that we have just created.\nI will also add a print statement at the end of the `main()` function,\njust so that you can see what the HTTP Request that we have just loaded into the buffer object\nlooks like.\n\nAlso, I'm creating the buffer object in the `main()` function, which will be\nresponsible for storing the message sent by the client, and, I'm also\nusing a `for` loop to initialize all fields of this buffer object to the number zero.\nThis is important to make sure that we don't have uninitialized memory in\nthis object. Because uninitialized memory may cause undefined behaviour in our program.\n\nSince the `read_request()` function should receive as input the buffer object as a slice object (`[]u8`),\nI am using the syntax `array[0..array.len]` to get access to a slice of this `buffer` object.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst Request = @import(\"request.zig\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n try stdout.print(\"Server Addr: {any}\\n\", .{socket._address});\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n var buffer: [1000]u8 = undefined;\n for (0..buffer.len) |i| {\n buffer[i] = 0;\n }\n _ = try Request.read_request(\n connection, buffer[0..buffer.len]\n );\n try stdout.print(\"{s}\\n\", .{buffer});\n}\n```\n:::\n\n\nNow, I'm going to execute this program, with the `run` command from the\n`zig` compiler. But remember, as we sad earlier, as soon as I execute this program, it will\nhang indefinitely, because the program is waiting for a client trying to\nconnect to the server.\n\nMore specifically, the program will pause at the line\nwith the `accept()` call. As soon as a client try to connect to the\nserver, then, the execution will \"unpause\", and the `accept()` function\nwill finally be executed to create the\nconnection object that we need, and the remaining of the program\nwill run.\n\nYou can see that in @fig-print-zigrun1. The message `Server Addr: 127.0.0.1:3490`\nis printed to the console, and the program is now waiting for an incoming connection.\n\n![A screenshot of running the program](./../Figures/print-zigrun1.png){#fig-print-zigrun1}\n\n\nWe can finally try to connect to this server, and there are several ways we can do this.\nFor example, we could use the following Python script:\n\n```python\nimport requests\nrequests.get(\"http://127.0.0.1:3490\")\n```\n\nOr, we could also open any web browser of our preference, and type\nthe URL `localhost:3490`. OBS: `localhost` is the same thing as the\nIP `127.0.0.1`. When you press enter, and your web browser go\nto this address, first, the browser will probably print a message\nsaying that \"this page isn't working\", and, then, it will\nprobably change to a new message saying that \"the site can't be\nreached\".\n\nYou get these \"error messages\" in the web browser, because\nit got no response back from the server. In other words, when the web\nbrowser connected to our server, it did send the HTTP Request through the established connection.\nThen, the web browser was expecting to receive a HTTP Response back, but\nit got no response from the server (we didn't implemented the HTTP Response logic yet).\n\nBut that is okay. We have achieved the result that we wanted for now,\nwhich is to connect to the server, and see the HTTP Request\nthat was sent by the web browser (or by the Python script)\nto the server.\n\nIf you comeback to the console that you left open\nwhen you have executed the program, you will see that the\nprogram finished its execution, and, a new message is\nprinted in the console, which is the actual HTTP Request\nmessage that was sent by the web browser to the server.\nYou can see this message in @fig-print-zigrun2.\n\n![A screenshot of the HTTP Request sent by the web browser](./../Figures/print-zigrun2.png){#fig-print-zigrun2}\n\n\n\n\n## Learning about Enums in Zig {#sec-enum}\n\nEnums structures are available in Zig through the `enum` keyword.\nAn enum (short for \"enumeration\") is a special structure that represents a group of constant values.\nSo, if you have a variable which can assume a short and known\nset of values, you might want to associate this variable to an enum structure,\nto make sure that this variable only assumes a value from this set.\n\nA classic example for enums are primary colors. If for some reason, your program\nneeds to represent one of the primary colors, you can create an enum\nthat represents one of these colors.\nIn the example below, we are creating the enum `PrimaryColorRGB`, which\nrepresents a primary color from the RGB color system. By using this enum,\nI am guaranteed that the `acolor` object for example, will contain\none of these three values: `RED`, `GREEN` or `BLUE`.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst PrimaryColorRGB = enum {\n RED, GREEN, BLUE\n};\nconst acolor = PrimaryColorRGB.RED;\n_ = acolor;\n```\n:::\n\n\nIf for some reason, my code tries to save in `acolor`,\na value that is not in this set, I will get an error message\nwarning me that a value such as \"MAGENTA\" do not exist\ninside the `PrimaryColorRGB` enum.\nThen I can easily fix my mistake.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst acolor = PrimaryColorRGB.MAGENTA;\n```\n:::\n\n\n```\ne1.zig:5:36: error: enum 'PrimaryColorRGB' has\n no member named 'MAGENTA':\n const acolor = PrimaryColorRGB.MAGENTA;\n ^~~~~~~\n```\n\nBehind the hood, enums in Zig work the same way that enums\nwork in C. Each enum value is essentially represented as an integer.\nThe first value in the set is represented as zero,\nthen, the second value is one, ... etc.\n\nOne thing that we are going to learn in the next section is that\nenums can have methods in them. Wait... What? This is amazing!\nYes, enums in Zig are similar to structs, and they can have\nprivate and public methods inside them.\n\n\n\n\n\n\n\n## Implementing the server - Part 2\n\nNow, on this section, I want to focus on parsing\nthe HTTP Request that we received from the client.\nHowever, to effectively parse a HTTP Request message, we first need to understand its\nstructure.\nIn summary, a HTTP Request is a text message that is divided into 3 different\nsections (or parts):\n\n- The top-level header indicating the method of the HTTP Request, the URI, and the HTTP version used in the message.\n- A list of HTTP Headers.\n- The body of the HTTP Request.\n\n### The top-level header\n\nThe first line of text in a HTTP Request always come with the three most essential\ninformation about the request. These three key attributes of the HTTP Request\nare separated by a simple space in this first line of the request.\nThe first information is the HTTP method that is being\nused in the request, second, we have the URI to which this HTTP Request is being sent to,\nand third, we have the version of the HTTP protocol that is being used in this HTTP Request.\n\nIn the snippet below, you can find an example of this first line in a HTTP Request.\nFirst, we have the HTTP method of this request (`GET`). Many programmers\nrefer to the URI component (`/users/list`) as the \"API endpoint\" to which the HTTP Request\nis being sent to. In the context of this specific request, since it's a GET request,\nyou could also say that the URI component is the path to the resource we want to access,\nor, the path to the document (or the file) that we want to retrieve from the server.\n\n```\nGET /users/list HTTP/1.1\n```\n\nAlso, notice that this HTTP Request is using the version 1.1 of the HTTP protocol,\nwhich is the most popular version of the protocol used in the web.\n\n\n\n### The list of HTTP headers\n\nMost HTTP Requests also include a section of HTTP Headers,\nwhich is just a list of attributes or key-value pairs associated with this\nparticular request. This section always comes right after the \"top-level header\" of the request.\n\nFor our purpose in this chapter, which is to build a simple HTTP Server,\nwe are going to ignore this section of the HTTP Request, for simplicity.\nBut most HTTP servers that exist in the wild parses and use these\nHTTP headers to change the way that the server responds to the request\nsent by the client.\n\nFor example, many requests we encounter in the real-world comes with\na HTTP header called `Accept`. In this header, we find a list of [MIME types](https://en.wikipedia.org/wiki/Media_type)[^mime].\nThis list indicates the file formats that the client can read, or parse, or interpret.\nIn other words, you also interpret this header as the client saying the following phrase\nto the server: \"Hey! Look, I can read only HTML documents, so please, send me back\na document that is in a HTML format.\".\n\n[^mime]: .\n\nIf the HTTP server can read and use this `Accept` header, then, the server can identify\nwhich is the best file format for the document to be sent to the client. Maybe the HTTP server have\nthe same document in multiple formats, for example, in JSON, in XML, in HTML and in PDF,\nbut the client can only understand documents in the HTML format. That is the purpose\nof this `Accept` header.\n\n\n### The body\n\nThe body comes after the list of HTTP headers, and it's an optional section of the HTTP Request, meaning that, not\nall HTTP Requests will come with a body in them. For example, every HTTP Request that uses the\nGET method usually does not come with a body.\n\nBecause a GET request is used to request data, instead of sending it to the server.\nSo, the body section is more related to the POST method, which is a method that involves\nsending data to the server, to be processed and stored.\n\nSince we are going to support only the GET method in this project, it means that\nwe also do not need to care about the body of the request.\n\n\n\n### Creating the HTTP Method enum\n\nEvery HTTP Request comes with a explicit method. The method used in a HTTP Request\nis identified by one these words:\n\n- GET;\n- POST;\n- OPTIONS;\n- PATCH;\n- DELETE;\n- and some other methods.\n\nEach HTTP method is used for a specific type of task. The POST method for example is normally\nused to post some data into the destination. In other words, it's used\nto send some data to the HTTP server, so that it can be processed and stored by the server.\n\nAs another example, the GET method is normally used to get content from the server.\nIn other words, we use this method whenever we want the server to send some\ncontent back to us. It can be any type of content. It can be a web page,\na document file, or some data in a JSON format.\n\nWhen a client sends a POST HTTP Request, the HTTP Response sent by the server normally have the sole purpose of\nletting the client know if the server processed and stored the data successfully.\nIn contrast, when the server receives a GET HTTP Request, then, the server sends the content\nthat the client asked for in the HTTP Response itself. This demonstrates that the method associated\nwith the HTTP Request changes a lot on the dynamics and the roles that each party\nplays in the whole process.\n\nSince the HTTP method of the HTTP Request is identified by this very small and specific\nset of words, it would be interesting to create an enum structure to represent a HTTP method.\nThis way, we can easily check if the HTTP Request we receive from the client is a\nHTTP method that we currently support in our small HTTP server project.\n\nThe `Method` structure below represents this enumeration.\nNotice that, for now, only the GET HTTP method is included in this\nenumeration. Because, for the purpose of this chapter, I want to\nimplement only the GET HTTP method. That is why I am not\nincluding the other HTTP methods in this enumeration.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Method = enum {\n GET\n};\n```\n:::\n\n\n\nNow, I think we should add two methods to this enum structure. One method is `is_supported()`,\nwhich will be a function that returns a boolean value, indicating if the input HTTP method is supported\nor not by our HTTP Server. The other is `init()`, which is a constructor function that takes a string as input,\nand tries to convert it into a `Method` value.\n\n\nBut in order to build these functions, I will use a functionality from the Zig Standard Library, called\n`StaticStringMap()`. This function allows us to create a simple map from strings to enum values.\nIn other words, we can use this map structure to map a string to the respective enum value.\nTo some extent, this specific structure from the standard library works almost like a \"hashtable\" structure,\nand it's optimized for small sets of words, or, small sets of keys, which is our case here.\nWe are going to talk more about hashtables in Zig in @sec-maps-hashtables.\n\nTo use this \"static string map\" structure, you have to import it from the `std.static_string_map` module\nof the Zig Standard Library. Just to make things shorter and easier to type, I am going to import this\nfunction through a different and shorter name (`Map`).\n\nWith `Map()` imported, we can just apply this function over the enum structure\nthat we are going to use in the resulting map. In our case here, it's the `Method` enum structure\nthat we declared at the last code example. Then, I call the `initComptime()` method with the\nmap, i.e., the list of key-value pairs that we are going to use.\n\nYou can see in the example below that I wrote this map using multiple anonymous struct literals.\nInside the first (or \"top-level\") struct literal, we have a list (or a sequence) of struct literals.\nEach struct literal in this list represents a separate key-value pair. The first element (or the key)\nin each key-value pair should always be a string value. While the second element should\nbe a value from the enum structure that you have used inside the `Map()` function.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Map = std.static_string_map.StaticStringMap;\nconst MethodMap = Map(Method).initComptime(.{\n .{ \"GET\", Method.GET },\n});\n```\n:::\n\n\nTherefore, the `MethodMap` object is basically a `std::map` object from C++, or,\na `dict` object from Python. You can retrieve (or get) the enum value that\ncorresponds to a particular key, by using the `get()` method from the map\nobject. This method returns an optional value, so, the `get()` method might\nresult in a null value.\n\nWe can use this in our advantage to detect if a particular HTTP method is\nsupported or not in our HTTP server. Because, if the `get()` method returns null,\nit means that it did not found the method that we provided inside the `MethodMap` object, and,\nas a consequence, this method is not supported by our HTTP server.\n\nThe `init()` method below, takes a string value as input, and then, it simply passes this string value\nto the `get()` method of our `MethodMap` object. As consequence, we should get the enum value that corresponds\nto this input string.\n\nNotice in the example below that, the `init()` method returns either an error\n(which might happen if the `?` method returns `unreacheable`, checkout @sec-null-handling for more details)\nor a `Method` object as result. Since `GET` is currently the only value in our `Method` enum\nstructure, it means that, the `init()` method will most likely return the value `Method.GET` as result.\n\nAlso notice that, in the `is_supported()` method, we are using the optional value returned\nby the `get()` method from our `MethodMap` object. The if statement unwraps the optional value\nreturned by this method, and returns `true` in case this optional value is a not-null value.\nOtherwise, it simply returns `false`.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Method = enum {\n GET,\n pub fn init(text: []const u8) !Method {\n return MethodMap.get(text).?;\n }\n pub fn is_supported(m: []const u8) bool {\n const method = MethodMap.get(m);\n if (method) |_| {\n return true;\n }\n return false;\n }\n};\n```\n:::\n\n\n\n\n\n\n\n\n### Writing the parse request function\n\nNow that we created the enum that represents our HTTP method,\nwe should start to write the function responsible for\nactually parsing the HTTP Request.\n\nThe first thing we can do, is to write a struct to represent the HTTP Request.\nTake the `Request` struct below as an example. It contains the three\nessential information from the \"top-level\" header (i.e., the first line)\nin the HTTP Request.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst Request = struct {\n method: Method,\n version: []const u8,\n uri: []const u8,\n pub fn init(method: Method,\n uri: []const u8,\n version: []const u8) Request {\n return Request{\n .method = method,\n .uri = uri,\n .version = version,\n };\n }\n};\n```\n:::\n\n\n\nThe `parse_request()` function should receive a string as input. This input string\ncontains the entire HTTP Request message, and the parsing function should\nread and understand the individual parts of this message.\n\nNow, remember that for the purpose of this chapter, we care only about the first\nline in this message, which contains the \"top-level header\", or, the three essential attributes about the HTTP Request,\nwhich are the HTTP method used, the URI and the HTTP version.\n\nNotice that I use the function `indexOfScalar()` in `parse_request()`. This function from the\nZig Standard Library returns the first index where the scalar value that we provide\nhappens in a string. In this case, I'm looking at the first occurrence of the new line character (`\\n`).\nBecause once again, we care only about the first line in the HTTP Request message.\nThis is the line where we have the three information that we want to parse\n(version of HTTP, the HTTP method and the URI).\n\nTherefore, we are using this `indexOfScalar()` function\nto limit our parsing process to the first line in the message.\nIt's also worth mentioning that, the `indexOfScalar()` function returns an optional value.\nThat is why I use the `orelse` keyword to provide an alternative value, in case\nthe value returned by the function is a null value.\n\nSince each of these three attributes are separated by a simple space, we\ncould use the function `splitScalar()` from the Zig Standard Library to split\nthe input string into sections by looking for every position that appears\na simple space. In other words, this `splitScalar()` function is equivalent\nto the `split()` method in Python, or, the `std::getline()` function from C++,\nor the `strtok()` function in C.\n\nWhen you use this `splitScalar()` function, you get an iterator as the result.\nThis iterator have a `next()` method that you can use to advance the iterator\nto the next position, or, to the next section of the splitted string.\nNote that, when you use `next()`, the method not only advances the iterator,\nbut it also returns a slice to the current section of the splitted\nstring as result.\n\nNow, if you want to get a slice to the current section of the splitted\nstring, but not advance the iterator to the next position, you can use\nthe `peek()` method. Both `next()` and `peek()` methods return an optional value, that is\nwhy I use the `?` method to unwrap these optional values.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn parse_request(text: []u8) Request {\n const line_index = std.mem.indexOfScalar(\n u8, text, '\\n'\n ) orelse text.len;\n var iterator = std.mem.splitScalar(\n u8, text[0..line_index], ' '\n );\n const method = try Method.init(iterator.next().?);\n const uri = iterator.next().?;\n const version = iterator.next().?;\n const request = Request.init(method, uri, version);\n return request;\n}\n```\n:::\n\n\n\nAs I described in @sec-zig-strings, strings in Zig are simply arrays of bytes in the language.\nSo, you will find lots of excellent utility functions to work directly with strings\ninside this `mem` module from the Zig Standard Library.\nWe have described some of these useful utility functions already\nin @sec-strings-useful-funs.\n\n\n\n### Using the parse request function\n\nNow that we wrote the function responsible for parsing the HTTP Request,\nwe can add the function call to `parse_request()` in\nthe `main()` function of our program.\n\nAfter that, is a good idea to test once again the state of our program.\nI execute this program again with the `run` command from the `zig` compiler,\nthen, I use my web browser to connect once again to the server through the URL `localhost:3490`, and finally,\nthe end result of our `Request` object is printed to the console.\n\nA quick observation, since I have used the `any` format specifier in the\nprint statement, the data members `version` and `uri` of the `Request`\nstruct were printed as raw integer values. String data being printed\nas integer values is common in Zig, and remember, these integer values are just the decimal representation of\nthe bytes that form the string in question.\n\nIn the result below, the sequence of decimal values 72, 84, 84, 80, 47, 49, 46, 49, and 13,\nare the bytes that form the text \"HTTP/1.1\". And the integer 47, is the decimal value of\nthe character `/`, which represents our URI in this request.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst Request = @import(\"request.zig\");\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n\n var buffer: [1000]u8 = undefined;\n for (0..buffer.len) |i| {\n buffer[i] = 0;\n }\n try Request.read_request(\n connection, buffer[0..buffer.len]\n );\n const request = Request.parse_request(\n buffer[0..buffer.len]\n );\n try stdout.print(\"{any}\\n\", .{request});\n}\n```\n:::\n\n\n```\nrequest.Request{\n .method = request.Method.GET,\n .version = {72, 84, 84, 80, 47, 49, 46, 49, 13},\n .uri = {47}\n}\n```\n\n\n\n### Sending the HTTP Response to the client\n\nIn this last part, we are going to write the logic responsible for\nsending the HTTP Response from the server to the client. To make things\nsimple, the server in this project will send just a simple web page\ncontaining the text \"Hello world\".\n\nFirst, I create a new Zig module in the project, named `response.zig`.\nIn this module, I will declare just two functions. Each function\ncorresponds to a specific status code in the HTTP Response.\nThe `send_200()` function will send a HTTP Response with status code 200\n(which means \"Success\") to the client. While the `send_404()` function sends a response\nwith status code 404 (which means \"Not found\").\n\nThis is definitely not the most ergonomic and adequate way of handling the\nHTTP Response, but it works for our case here. We are just building toy projects\nin this book after all, therefore, the source code that we write do not need to be perfect.\nIt just needs to work!\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Connection = std.net.Server.Connection;\npub fn send_200(conn: Connection) !void {\n const message = (\n \"HTTP/1.1 200 OK\\nContent-Length: 48\"\n ++ \"\\nContent-Type: text/html\\n\"\n ++ \"Connection: Closed\\n\\n\"\n ++ \"

    Hello, World!

    \"\n );\n _ = try conn.stream.write(message);\n}\n\npub fn send_404(conn: Connection) !void {\n const message = (\n \"HTTP/1.1 404 Not Found\\nContent-Length: 50\"\n ++ \"\\nContent-Type: text/html\\n\"\n ++ \"Connection: Closed\\n\\n\"\n ++ \"

    File not found!

    \"\n );\n _ = try conn.stream.write(message);\n}\n```\n:::\n\n\nNotice that both functions receives the connection object as input, and\nuse the `write()` method to write the HTTP Response message directly\ninto this communication channel. As result, the party in the other\nside of the connection (i.e., the client), will receive such message.\n\nMost real-world HTTP Servers will have a single function (or a single struct) to effectively handle\nthe response. It gets the HTTP Request already parsed as input, and then, it tries to build\nthe HTTP Response bit by bit, before the function sends it over the connection.\n\nWe would also have a specialized struct to represent a HTTP Response, and\na lot of methods that would be used to build each part or component of the response object.\nTake the `Response` struct created by the Javascript runtime Bun as an example.\nYou can find this struct in the [`response.zig` module](https://github.com/oven-sh/bun/blob/main/src/bun.js/webcore/response.zig)[^bun-resp]\nin their GitHub project.\n\n[^bun-resp]: .\n\n\n## The end result\n\nWe can now, update once again our `main()` function to incorporate our new\nfunctions from the `response.zig` module. First, I need to import this module\ninto our `main.zig` module, then, I add the function calls to `send_200()`\nand `send_404()`.\n\nNotice that I'm using if statements to decide which \"response function\" to call,\nbased especially on the URI present in the HTTP Request. If the user asked for\na content (or a document) that is not present in our server, we should respond\nwith a 404 status code. But since we have just a simple HTTP server, with no\nreal documents to send, we can just check if the URI is the root path (`/`)\nor not to decide which function to call.\n\nAlso, notice that I'm using the function `std.mem.eql()` from the Zig Standard Library\nto check if the string from `uri` is equal or not the string `\"/\"`. We have\ndescribed this function already in @sec-strings-useful-funs, so, comeback to\nthat section if you are not familiar yet with this function.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst SocketConf = @import(\"config.zig\");\nconst Request = @import(\"request.zig\");\nconst Response = @import(\"response.zig\");\nconst Method = Request.Method;\nconst stdout = std.io.getStdOut().writer();\n\npub fn main() !void {\n const socket = try SocketConf.Socket.init();\n try stdout.print(\"Server Addr: {any}\\n\", .{socket._address});\n var server = try socket._address.listen(.{});\n const connection = try server.accept();\n\n var buffer: [1000]u8 = undefined;\n for (0..buffer.len) |i| {\n buffer[i] = 0;\n }\n try Request.read_request(connection, buffer[0..buffer.len]);\n const request = Request.parse_request(\n buffer[0..buffer.len]\n );\n if (request.method == Method.GET) {\n if (std.mem.eql(u8, request.uri, \"/\")) {\n try Response.send_200(connection);\n } else {\n try Response.send_404(connection);\n }\n }\n}\n```\n:::\n\n\n\nNow that we adjusted our `main()` function, I can now execute our program, and\nsee the effects of these last changes. First, I execute the program once again, with the\n`run` command of the `zig` compiler. The program will hang, waiting for a client to connect.\n\nThen, I open my web browser, and try to connect to the server again, using the URL `localhost:3490`.\nThis time, instead of getting some sort of an error message from the browser, you will get the message\n\"Hello World\" printed into your web browser. Because this time, the server sended the HTTP Response\nsuccessfully to the web browser, as demonstrated by @fig-print-zigrun3.\n\n\n![The Hello World message sent in the HTTP Response](./../Figures/print-zigrun3.png){#fig-print-zigrun3}\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/05-pointers/execute-results/html.json b/_freeze/Chapters/05-pointers/execute-results/html.json index 322b1cc9..8c1fac77 100644 --- a/_freeze/Chapters/05-pointers/execute-results/html.json +++ b/_freeze/Chapters/05-pointers/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "8201d761dfd46af14c754587b77047a2", + "hash": "51c6d3c5265304100391eb65d556de78", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Pointers and Optionals {#sec-pointer}\n\nOn our next project we are going to build a HTTP server from scratch.\nBut in order to do that, we need to learn more about pointers and how they work in Zig.\nPointers in Zig are similar to pointers in C. But they come with some extra advantages in Zig.\n\nA pointer is an object that contains a memory address. This memory address is the address where\na particular value is stored in memory. It can be any value. Most of the times,\nit's a value that comes from another object (or variable) present in our code.\n\nIn the example below, I'm creating two objects (`number` and `pointer`).\nThe `pointer` object contains the memory address where the value of the `number` object\n(the number 5) is stored. So, that is a pointer in a nutshell. It's a memory\naddress that points to a particular existing value in the memory. You could\nalso say, that, the `pointer` object points to the memory address where the `number` object is\nstored.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\n_ = pointer;\n```\n:::\n\n\n\n\nWe create a pointer object in Zig by using the `&` operator. When you put this operator\nbefore the name of an existing object, you get the memory address of this object as result.\nWhen you store this memory address inside a new object, this new object becomes a pointer object.\nBecause it stores a memory address.\n\nPeople mostly use pointers as an alternative way to access a particular value.\nFor example, I can use the `pointer` object to access the value stored by\nthe `number` object. This operation of accessing the value that the\npointer \"points to\" is normally called of *dereferencing the pointer*.\nWe can dereference a pointer in Zig by using the `*` method of the pointer object. Like in the example\nbelow, where we take the number 5 pointed by the `pointer` object,\nand double it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\nconst doubled = 2 * pointer.*;\nstd.debug.print(\"{d}\\n\", .{doubled});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n10\n```\n\n\n:::\n:::\n\n\n\n\n\nThis syntax to dereference the pointer is nice. Because we can easily chain it with\nmethods of the value pointed by the pointer. We can use the `User` struct that we have\ncreated in @sec-structs-and-oop as an example. If you comeback to that section,\nyou will see that this struct have a method named `print_name()`.\n\nSo, for example, if we have an user object, and a pointer that points to this user object,\nwe can use the pointer to access this user object, and, at the same time, call the method `print_name()`\non it, by chaining the dereference method (`*`) with the `print_name()` method. Like in the\nexample below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst u = User.init(1, \"pedro\", \"email@gmail.com\");\nconst pointer = &u;\ntry pointer.*.print_name();\n```\n:::\n\n\n\n\n```\npedro\n```\n\nWe can also use pointers to effectively alter the value of an object.\nFor example, I could use the `pointer` object to set\nthe value of the object `number` to 6, like in the example below.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\n\n\n\nTherefore, as I mentioned earlier, people use pointers as an alternative way to access a particular value.\nAnd they use it especially when they do not want to \"move\" these values around. There are situations where,\nyou want to access a particular value in a different scope (i.e., a different location) of your code,\nbut you do not want to \"move\" this value to this new scope (or location) that you are in.\n\nThis matters especially if this value is big in size. Because if it is, then,\nmoving this value becomes an expensive operation to do.\nThe computer will have to spend a considerable amount of time\ncopying this value to this new location.\n\nTherefore, many programmers prefer to avoid this heavy operation of copying the value\nto the new location, by accessing this value through pointers.\nWe are going to talk more about this \"moving operation\" over the next sections.\nFor now, just keep in mind that avoiding this \"move operation\" is\none of main reasons why pointers are used in programming languages.\n\n\n\n\n\n## Constant objects vs variable objects {#sec-pointer-var}\n\nYou can have a pointer that points to a constant object, or, a pointer that points to a variable object.\nBut regardless of who this pointer is, a pointer **must always respect the characteristics of the object that it points to**.\nAs a consequence, if the pointer points to a constant object, then, you cannot use this pointer\nto change the value that it points to. Because it points to a value that is constant. As we discussed in @sec-assignments, you cannot\nchange a value that is constant.\n\nFor example, if I have a `number` object, which is constant, I cannot execute\nthe expression below where I'm trying to change the value of `number` to 6 through\nthe `pointer` object. As demonstrated below, when you try to do something\nlike that, you get a compile time error:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number = 5;\nconst pointer = &number;\npointer.* = 6;\n```\n:::\n\n\n\n\n```\np.zig:6:12: error: cannot assign to constant\n pointer.* = 6;\n```\n\nIf I change the `number` object to be a variable object, by introducing the `var` keyword,\nthen, I can successfully change the value of this object through a pointer, as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\n\n\nYou can see this relationship between \"constant versus variable\" on the data type of\nyour pointer object. In other words, the data type of a pointer object already gives you\nsome clues about whether the value that it points to is constant or not.\n\nWhen a pointer object points to a constant value, then, this pointer have a data type `*const T`,\nwhich means \"a pointer to a constant value of type `T`\".\nIn contrast, if the pointer points to a variable value, then, the type of the pointer is usually `*T`, which is\nsimply \"a pointer to a value of type `T`\".\nHence, whenever you see a pointer object whose data type is in the format `*const T`, then,\nyou know that you cannot use this pointer to change the value that it points to.\nBecause this pointer points to a constant value of type `T`.\n\n\nWe have talked about the value pointed by the pointer being constant or not,\nand the consequences that arises from it. But, what about the pointer object itself? I mean, what happens\nif the pointer object itself is constant or not? Think about it.\nWe can have a constant pointer that points to a constant value.\nBut we can also have a variable pointer that points to a constant value. And vice-versa.\n\nUntil this point, the `pointer` object was always constant,\nbut what does this mean for us? What is the consequence of the\n`pointer` object being constant? The consequence is that\nwe cannot change the pointer object, because it is constant. We can use the\npointer object in multiple ways, but we cannot change the\nmemory address that is inside this pointer object.\n\nHowever, if we mark the `pointer` object as a variable object,\nthen, we can change the memory address pointed by this `pointer` object.\nThe example below demonstrates that. Notice that the object pointed\nby the `pointer` object changes from `c1` to `c2`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c1: u8 = 5;\nconst c2: u8 = 6;\nvar pointer = &c1;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\npointer = &c2;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\n```\n:::\n\n\n\n\n```\n5\n6\n```\n\nThus, by setting the `pointer` object to a `var` or `const` object,\nyou specify if the memory address contained in this pointer object can change or not\nin your program. On the other side, you can change the value pointed by the pointer,\nif, and only if this value is stored in a variable object. If this value\nis in a constant object, then, you cannot change this value through a pointer.\n\n\n## Types of pointer\n\nIn Zig, there are two types of pointers [@zigdocs], which are:\n\n- single-item pointer (`*`);\n- many-item pointer (`[*]`);\n\n\nSingle-item pointer objects are objects whose data types are in the format `*T`.\nSo, for example, if an object have a data type `*u32`, it means that, this\nobject contains a single-item pointer that points to an unsigned 32-bit integer value.\nAs another example, if an object have type `*User`, then, it contains\na single-item pointer to an `User` value.\n\nIn contrast, many-item pointers are objects whose data types are in the format `[*]T`.\nNotice that the star symbol (`*`) is now inside a pair of brackets (`[]`). If the star\nsymbol is inside a pair of brackets, you know that this object is a many-item pointer.\n\nWhen you apply the `&` operator over an object, you will always get a single-item pointer.\nMany-item pointers are more of a \"internal type\" of the language, more closely\nrelated to slices. So, when you deliberately create a pointer with the `&` operator,\nyou always get a single-item pointer as result.\n\n\n\n## Pointer arithmetic\n\nPointer arithmetic is available in Zig, and they work the same way they work in C.\nWhen you have a pointer that points to an array, the pointer usually points to\nthe first element in the array, and you can use pointer arithmetic to\nadvance this pointer and access the other elements in the array.\n\n\nNotice in the example below, that initially, the `ptr` object was pointing\nto the first element in the array `ar`. But then, I started to walk through the array, by advancing\nthe pointer with simple pointer arithmetic.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{ 1, 2, 3, 4 };\nvar ptr: [*]const i32 = &ar;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\n```\n:::\n\n\n\n\n```\n1\n2\n3\n```\n\nAlthough you can create a pointer to an array like that, and\nstart to walk through this array by using pointer arithmetic,\nin Zig, we prefer to use slices, which were presented in @sec-arrays.\n\nBehind the hood, slices already are pointers,\nand they also come with the `len` property, which indicates\nhow many elements are in the slice. This is good because the `zig` compiler\ncan use it to check for potential buffer overflows, and other problems like that.\n\nAlso, you don't need to use pointer arithmetic to walk through the elements\nof a slice. You can simply use the `slice[index]` syntax to directly access\nany element you want in the slice.\nAs I mentioned in @sec-arrays, you can get a slice from an array by using\na range selector inside brackets. In the example below, I'm creating\na slice (`sl`) that covers the entire `ar` array. I can access any\nelement of `ar` from this slice, and, the slice itself already is a pointer\nbehind the hood.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{1,2,3,4};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n\n\n## Optionals and Optional Pointers\n\nLet's talk about optionals and how they relate to pointers in Zig.\nBy default, objects in Zig are **non-nullable**. This means that, in Zig,\nyou can safely assume that any object in your source code is not null.\n\nThis is a powerful feature of Zig when you compare it to the developer experience in C.\nBecause in C, any object can be null at any point, and, as consequence, a pointer in C\nmight point to a null value. This is a common source of undefined behaviour in C.\nWhen programmers work with pointers in C, they have to constantly check if\ntheir pointers are pointing to null values or not.\n\nIf for some reason, your Zig code produces a null value somewhere, and, this null\nvalue ends up in an object that is non-nullable, a runtime error is always\nraised by your Zig program. Take the program below as an example.\nThe `zig` compiler can see the `null` value at compile time, and, as result,\nit raises a compile time error. But, if a `null` value is raised during\nruntime, a runtime error is also raised by the Zig program, with a\n\"attempt to use null value\" message.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nnumber = null;\n```\n:::\n\n\n\n```\np5.zig:5:14: error: expected type 'u8',\n found '@TypeOf(null)'\n number = null;\n ^~~~\n```\n\n\nYou don't get this type of safety in C.\nIn C, you don't get warnings or errors about null values being produced in your program.\nIf for some reason, your code produces a null value in C, most of the times, you end up getting a segmentation fault error\nas result, which can mean many things.\nThat is why programmers have to constantly check for null values in C.\n\nPointers in Zig are also, by default, **non-nullable**. This is another amazing\nfeature in Zig. So, you can safely assume that any pointer that you create in\nyour Zig code is pointing to a non-null value.\nTherefore, you don't have this heavy work of checking if the pointers you create\nin Zig are pointing to a null value.\n\n\n### What are optionals?\n\nOk, we know now that all objects are non-nullable by default in Zig.\nBut what if we actually need to use an object that might receive a null value?\nHere is where optionals come in.\n\nAn optional object in Zig is an object that can be null.\nTo mark an object as optional, we use the `?` operator. When you put\nthis `?` operator right before the data type of an object, you transform\nthis data type into an optional data type, and the object becomes an optional object.\n\nTake the snippet below as an example. We are creating a new variable object\ncalled `num`. This object have the data type `?i32`, which means that,\nthis object contains either a signed 32-bit integer (`i32`), or, a null value.\nBoth alternatives are valid values to the `num` object.\nThat is why, I can actually change the value of this object to null, and,\nno errors are raised by the `zig` compiler, as demonstrated below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\nnum = null;\n```\n:::\n\n\n\n\n### Optional pointers\n\nYou can also mark a pointer object as an optional pointer, meaning that,\nthis object contains either a null value, or, a pointer that points to a value.\nWhen you mark a pointer as optional, the data type of this pointer object\nbecomes `?*const T` or `?*T`, depending if the value pointed by the pointer\nis a constant value or not. The `?` identifies the object as optional, while\nthe `*` identifies it as a pointer object.\n\nIn the example below, we are creating a variable object named `num`, and an\noptional pointer object named `ptr`. Notice that the data type of the object\n`ptr` indicates that it's either a null value, or a pointer to an `i32` value.\nAlso, notice that the pointer object (`ptr`) can be marked as optional, even if\nthe object `num` is not optional.\n\nWhat this code tells us is that, the `num` variable will never contain a null value.\nThis variable will always contain a valid `i32` value. But in contrast, the `ptr` object might contain either a null\nvalue, or, a pointer to an `i32` value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: i32 = 5;\nvar ptr: ?*i32 = #\nptr = null;\nnum = 6;\n```\n:::\n\n\n\n\nBut what happens if we turn the table, and mark the `num` object as optional,\ninstead of the pointer object. If we do that, then, the pointer object is\nnot optional anymore. It would be a similar (although different) result. Because then, we would have\na pointer to an optional value. In other words, a pointer to a value that is either a\nnull value, or, a not-null value.\n\nIn the example below, we are recreating this idea. Now, the `ptr` object\nhave a data type of `*?i32`, instead of `?*i32`. Notice that the `*` symbol comes before of `?`\nthis time. So now, we have a pointer that points to a value that is either null\n, or, a signed 32-bit integer.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\n// ptr have type `*?i32`, instead of `?*i32`.\nconst ptr = #\n_ = ptr;\n```\n:::\n\n\n\n\n\n### Null handling in optionals {#sec-null-handling}\n\nWhen you have an optional object in your Zig code, you have to explicitly handle\nthe possibility of this object being null. It's like error-handling with `try` and `catch`.\nIn Zig you also have to handle null values like if they were a type of error.\n\nWe can do that, by using either:\n\n- an if statement, like you would do in C.\n- the `orelse` keyword.\n- unwrap the optional value with the `?` method.\n\nWhen you use an if statement, you use a pair of pipes\nto unwrap the optional value, and use this \"unwrapped object\"\ninside the if block.\nUsing the example below as a reference, if the object `num` is null,\nthen, the code inside the if statement is not executed. Otherwise,\nthe if statement will unwrap the object `num` into the `not_null_num`\nobject. This `not_null_num` object is guaranteed to be not null inside\nthe scope of the if statement.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst num: ?i32 = 5;\nif (num) |not_null_num| {\n try stdout.print(\"{d}\\n\", .{not_null_num});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n5\n```\n\n\n:::\n:::\n\n\n\n\nNow, the `orelse` keyword behaves like a binary operator. You connect two expressions with this keyword.\nOn the left side of `orelse`, you provide the expression that might result\nin a null value, and on the right side of `orelse`, you provide another expression\nthat will not result in a null value.\n\nThe idea behind the `orelse` keyword is: if the expression on the left side\nresult in a not-null value, then, this not-null value is used. However,\nif this expression on the left side result in a null value, then, the value\nof the expression on the right side is used instead.\n\nLooking at the example below, since the `x` object is currently null, the\n`orelse` decided to use the alternative value, which is the number 15.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x: ?i32 = null;\nconst dbl = (x orelse 15) * 2;\ntry stdout.print(\"{d}\\n\", .{dbl});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n30\n```\n\n\n:::\n:::\n\n\n\n\nYou can use the if statement or the `orelse` keyword, when you want to\nsolve (or deal with) this null value. However, if there is no clear solution\nto this null value, and the most logic and sane path is to simply panic\nand raise a loud error in your program when this null value is encountered,\nyou can use the `?` method of your optional object.\n\nIn essence, when you use this `?` method, the optional object is unwrapped.\nIf a not-null value is found in the optional object, then, this not-null value is used.\nOtherwise, the `unreachable` keyword is used. You can read more about this\n[`unreacheable` keyword at the official documentation](https://ziglang.org/documentation/master/#unreachable)[^un-docs].\nBut in essence, when you build your Zig source code using the build modes `ReleaseSafe` or `Debug`, this\n`unreacheable` keyword causes the program to panic and raise an error during runtime,\nlike in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn return_null(n: i32) ?i32 {\n if (n == 5) return null;\n return n;\n}\n\npub fn main() !void {\n const x: i32 = 5;\n const y: ?i32 = return_null(x);\n try stdout.print(\"{d}\\n\", .{y.?});\n}\n```\n:::\n\n\n\n\n```\nthread 12767 panic: attempt to use null value\np7.zig:12:34: 0x103419d in main (p7):\n try stdout.print(\"{d}\\n\", .{y.?});\n ^\n```\n\n\n[^un-docs]: .\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n# Pointers and Optionals {#sec-pointer}\n\nOn our next project we are going to build a HTTP server from scratch.\nBut in order to do that, we need to learn more about pointers and how they work in Zig.\nPointers in Zig are similar to pointers in C. But they come with some extra advantages in Zig.\n\nA pointer is an object that contains a memory address. This memory address is the address where\na particular value is stored in memory. It can be any value. Most of the times,\nit's a value that comes from another object (or variable) present in our code.\n\nIn the example below, I'm creating two objects (`number` and `pointer`).\nThe `pointer` object contains the memory address where the value of the `number` object\n(the number 5) is stored. So, that is a pointer in a nutshell. It's a memory\naddress that points to a particular existing value in the memory. You could\nalso say, that, the `pointer` object points to the memory address where the `number` object is\nstored.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\n_ = pointer;\n```\n:::\n\n\nWe create a pointer object in Zig by using the `&` operator. When you put this operator\nbefore the name of an existing object, you get the memory address of this object as result.\nWhen you store this memory address inside a new object, this new object becomes a pointer object.\nBecause it stores a memory address.\n\nPeople mostly use pointers as an alternative way to access a particular value.\nFor example, I can use the `pointer` object to access the value stored by\nthe `number` object. This operation of accessing the value that the\npointer \"points to\" is normally called of *dereferencing the pointer*.\nWe can dereference a pointer in Zig by using the `*` method of the pointer object. Like in the example\nbelow, where we take the number 5 pointed by the `pointer` object,\nand double it.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number: u8 = 5;\nconst pointer = &number;\nconst doubled = 2 * pointer.*;\nstd.debug.print(\"{d}\\n\", .{doubled});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n10\n```\n\n\n:::\n:::\n\n\n\nThis syntax to dereference the pointer is nice. Because we can easily chain it with\nmethods of the value pointed by the pointer. We can use the `User` struct that we have\ncreated in @sec-structs-and-oop as an example. If you comeback to that section,\nyou will see that this struct have a method named `print_name()`.\n\nSo, for example, if we have an user object, and a pointer that points to this user object,\nwe can use the pointer to access this user object, and, at the same time, call the method `print_name()`\non it, by chaining the dereference method (`*`) with the `print_name()` method. Like in the\nexample below:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst u = User.init(1, \"pedro\", \"email@gmail.com\");\nconst pointer = &u;\ntry pointer.*.print_name();\n```\n:::\n\n\n```\npedro\n```\n\nWe can also use pointers to effectively alter the value of an object.\nFor example, I could use the `pointer` object to set\nthe value of the object `number` to 6, like in the example below.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\n\nTherefore, as I mentioned earlier, people use pointers as an alternative way to access a particular value.\nAnd they use it especially when they do not want to \"move\" these values around. There are situations where,\nyou want to access a particular value in a different scope (i.e., a different location) of your code,\nbut you do not want to \"move\" this value to this new scope (or location) that you are in.\n\nThis matters especially if this value is big in size. Because if it is, then,\nmoving this value becomes an expensive operation to do.\nThe computer will have to spend a considerable amount of time\ncopying this value to this new location.\n\nTherefore, many programmers prefer to avoid this heavy operation of copying the value\nto the new location, by accessing this value through pointers.\nWe are going to talk more about this \"moving operation\" over the next sections.\nFor now, just keep in mind that avoiding this \"move operation\" is\none of main reasons why pointers are used in programming languages.\n\n\n\n\n\n## Constant objects vs variable objects {#sec-pointer-var}\n\nYou can have a pointer that points to a constant object, or, a pointer that points to a variable object.\nBut regardless of who this pointer is, a pointer **must always respect the characteristics of the object that it points to**.\nAs a consequence, if the pointer points to a constant object, then, you cannot use this pointer\nto change the value that it points to. Because it points to a value that is constant. As we discussed in @sec-assignments, you cannot\nchange a value that is constant.\n\nFor example, if I have a `number` object, which is constant, I cannot execute\nthe expression below where I'm trying to change the value of `number` to 6 through\nthe `pointer` object. As demonstrated below, when you try to do something\nlike that, you get a compile time error:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number = 5;\nconst pointer = &number;\npointer.* = 6;\n```\n:::\n\n\n```\np.zig:6:12: error: cannot assign to constant\n pointer.* = 6;\n```\n\nIf I change the `number` object to be a variable object, by introducing the `var` keyword,\nthen, I can successfully change the value of this object through a pointer, as demonstrated below:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nconst pointer = &number;\npointer.* = 6;\ntry stdout.print(\"{d}\\n\", .{number});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n6\n```\n\n\n:::\n:::\n\n\nYou can see this relationship between \"constant versus variable\" on the data type of\nyour pointer object. In other words, the data type of a pointer object already gives you\nsome clues about whether the value that it points to is constant or not.\n\nWhen a pointer object points to a constant value, then, this pointer have a data type `*const T`,\nwhich means \"a pointer to a constant value of type `T`\".\nIn contrast, if the pointer points to a variable value, then, the type of the pointer is usually `*T`, which is\nsimply \"a pointer to a value of type `T`\".\nHence, whenever you see a pointer object whose data type is in the format `*const T`, then,\nyou know that you cannot use this pointer to change the value that it points to.\nBecause this pointer points to a constant value of type `T`.\n\n\nWe have talked about the value pointed by the pointer being constant or not,\nand the consequences that arises from it. But, what about the pointer object itself? I mean, what happens\nif the pointer object itself is constant or not? Think about it.\nWe can have a constant pointer that points to a constant value.\nBut we can also have a variable pointer that points to a constant value. And vice-versa.\n\nUntil this point, the `pointer` object was always constant,\nbut what does this mean for us? What is the consequence of the\n`pointer` object being constant? The consequence is that\nwe cannot change the pointer object, because it is constant. We can use the\npointer object in multiple ways, but we cannot change the\nmemory address that is inside this pointer object.\n\nHowever, if we mark the `pointer` object as a variable object,\nthen, we can change the memory address pointed by this `pointer` object.\nThe example below demonstrates that. Notice that the object pointed\nby the `pointer` object changes from `c1` to `c2`.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c1: u8 = 5;\nconst c2: u8 = 6;\nvar pointer = &c1;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\npointer = &c2;\ntry stdout.print(\"{d}\\n\", .{pointer.*});\n```\n:::\n\n\n```\n5\n6\n```\n\nThus, by setting the `pointer` object to a `var` or `const` object,\nyou specify if the memory address contained in this pointer object can change or not\nin your program. On the other side, you can change the value pointed by the pointer,\nif, and only if this value is stored in a variable object. If this value\nis in a constant object, then, you cannot change this value through a pointer.\n\n\n## Types of pointer\n\nIn Zig, there are two types of pointers [@zigdocs], which are:\n\n- single-item pointer (`*`);\n- many-item pointer (`[*]`);\n\n\nSingle-item pointer objects are objects whose data types are in the format `*T`.\nSo, for example, if an object have a data type `*u32`, it means that, this\nobject contains a single-item pointer that points to an unsigned 32-bit integer value.\nAs another example, if an object have type `*User`, then, it contains\na single-item pointer to an `User` value.\n\nIn contrast, many-item pointers are objects whose data types are in the format `[*]T`.\nNotice that the star symbol (`*`) is now inside a pair of brackets (`[]`). If the star\nsymbol is inside a pair of brackets, you know that this object is a many-item pointer.\n\nWhen you apply the `&` operator over an object, you will always get a single-item pointer.\nMany-item pointers are more of a \"internal type\" of the language, more closely\nrelated to slices. So, when you deliberately create a pointer with the `&` operator,\nyou always get a single-item pointer as result.\n\n\n\n## Pointer arithmetic\n\nPointer arithmetic is available in Zig, and they work the same way they work in C.\nWhen you have a pointer that points to an array, the pointer usually points to\nthe first element in the array, and you can use pointer arithmetic to\nadvance this pointer and access the other elements in the array.\n\n\nNotice in the example below, that initially, the `ptr` object was pointing\nto the first element in the array `ar`. But then, I started to walk through the array, by advancing\nthe pointer with simple pointer arithmetic.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{ 1, 2, 3, 4 };\nvar ptr: [*]const i32 = &ar;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\nptr += 1;\ntry stdout.print(\"{d}\\n\", .{ptr[0]});\n```\n:::\n\n\n```\n1\n2\n3\n```\n\nAlthough you can create a pointer to an array like that, and\nstart to walk through this array by using pointer arithmetic,\nin Zig, we prefer to use slices, which were presented in @sec-arrays.\n\nBehind the hood, slices already are pointers,\nand they also come with the `len` property, which indicates\nhow many elements are in the slice. This is good because the `zig` compiler\ncan use it to check for potential buffer overflows, and other problems like that.\n\nAlso, you don't need to use pointer arithmetic to walk through the elements\nof a slice. You can simply use the `slice[index]` syntax to directly access\nany element you want in the slice.\nAs I mentioned in @sec-arrays, you can get a slice from an array by using\na range selector inside brackets. In the example below, I'm creating\na slice (`sl`) that covers the entire `ar` array. I can access any\nelement of `ar` from this slice, and, the slice itself already is a pointer\nbehind the hood.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst ar = [_]i32{1,2,3,4};\nconst sl = ar[0..ar.len];\n_ = sl;\n```\n:::\n\n\n\n## Optionals and Optional Pointers\n\nLet's talk about optionals and how they relate to pointers in Zig.\nBy default, objects in Zig are **non-nullable**. This means that, in Zig,\nyou can safely assume that any object in your source code is not null.\n\nThis is a powerful feature of Zig when you compare it to the developer experience in C.\nBecause in C, any object can be null at any point, and, as consequence, a pointer in C\nmight point to a null value. This is a common source of undefined behaviour in C.\nWhen programmers work with pointers in C, they have to constantly check if\ntheir pointers are pointing to null values or not.\n\nIn contrast, when working in Zig, if for some reason, your Zig code produces a null value somewhere, and, this null\nvalue ends up in an object that is non-nullable, a runtime error is always\nraised by your Zig program. Take the program below as an example.\nThe `zig` compiler can see the `null` value at compile time, and, as result,\nit raises a compile time error. But, if a `null` value is raised during\nruntime, a runtime error is also raised by the Zig program, with a\n\"attempt to use null value\" message.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar number: u8 = 5;\nnumber = null;\n```\n:::\n\n```\np5.zig:5:14: error: expected type 'u8',\n found '@TypeOf(null)'\n number = null;\n ^~~~\n```\n\n\nYou don't get this type of safety in C.\nIn C, you don't get warnings or errors about null values being produced in your program.\nIf for some reason, your code produces a null value in C, most of the times, you end up getting a segmentation fault error\nas result, which can mean many things.\nThat is why programmers have to constantly check for null values in C.\n\nPointers in Zig are also, by default, **non-nullable**. This is another amazing\nfeature in Zig. So, you can safely assume that any pointer that you create in\nyour Zig code is pointing to a non-null value.\nTherefore, you don't have this heavy work of checking if the pointers you create\nin Zig are pointing to a null value.\n\n\n### What are optionals?\n\nOk, we know now that all objects are non-nullable by default in Zig.\nBut what if we actually need to use an object that might receive a null value?\nHere is where optionals come in.\n\nAn optional object in Zig is rather similar to a [`std::optional` object in C++](https://en.cppreference.com/w/cpp/utility/optional.html).\nIt is an object that can either contain a value, or nothing at all (a.k.a. the object can be null).\nTo mark an object in our Zig code as \"optional\", we use the `?` operator. When you put\nthis `?` operator right before the data type of an object, you transform\nthis data type into an optional data type, and the object becomes an optional object.\n\nTake the snippet below as an example. We are creating a new variable object\ncalled `num`. This object have the data type `?i32`, which means that,\nthis object contains either a signed 32-bit integer (`i32`), or, a null value.\nBoth alternatives are valid values to the `num` object.\nThat is why, I can actually change the value of this object to null, and,\nno errors are raised by the `zig` compiler, as demonstrated below:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\nnum = null;\n```\n:::\n\n\n### Optional pointers\n\nYou can also mark a pointer object as an optional pointer, meaning that,\nthis object contains either a null value, or, a pointer that points to a value.\nWhen you mark a pointer as optional, the data type of this pointer object\nbecomes `?*const T` or `?*T`, depending if the value pointed by the pointer\nis a constant value or not. The `?` identifies the object as optional, while\nthe `*` identifies it as a pointer object.\n\nIn the example below, we are creating a variable object named `num`, and an\noptional pointer object named `ptr`. Notice that the data type of the object\n`ptr` indicates that it's either a null value, or a pointer to an `i32` value.\nAlso, notice that the pointer object (`ptr`) can be marked as optional, even if\nthe object `num` is not optional.\n\nWhat this code tells us is that, the `num` variable will never contain a null value.\nThis variable will always contain a valid `i32` value. But in contrast, the `ptr` object might contain either a null\nvalue, or, a pointer to an `i32` value.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: i32 = 5;\nvar ptr: ?*i32 = #\nptr = null;\nnum = 6;\n```\n:::\n\n\nBut what happens if we turn the table, and mark the `num` object as optional,\ninstead of the pointer object. If we do that, then, the pointer object is\nnot optional anymore. It would be a similar (although different) result. Because then, we would have\na pointer to an optional value. In other words, a pointer to a value that is either a\nnull value, or, a not-null value.\n\nIn the example below, we are recreating this idea. Now, the `ptr` object\nhave a data type of `*?i32`, instead of `?*i32`. Notice that the `*` symbol comes before of `?`\nthis time. So now, we have a pointer that points to a value that is either null\n, or, a signed 32-bit integer.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar num: ?i32 = 5;\n// ptr have type `*?i32`, instead of `?*i32`.\nconst ptr = #\n_ = ptr;\n```\n:::\n\n\n\n### Null handling in optionals {#sec-null-handling}\n\nWhen you have an optional object in your Zig code, you have to explicitly handle\nthe possibility of this object being null. It's like error-handling with `try` and `catch`.\nIn Zig you also have to handle null values like if they were a type of error.\n\nWe can do that, by using either:\n\n- an if statement, like you would do in C.\n- the `orelse` keyword.\n- unwrap the optional value with the `?` method.\n\nWhen you use an if statement, you use a pair of pipes\nto unwrap the optional value, and use this \"unwrapped object\"\ninside the if block.\nUsing the example below as a reference, if the object `num` is null,\nthen, the code inside the if statement is not executed. Otherwise,\nthe if statement will unwrap the object `num` into the `not_null_num`\nobject. This `not_null_num` object is guaranteed to be not null inside\nthe scope of the if statement.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst num: ?i32 = 5;\nif (num) |not_null_num| {\n try stdout.print(\"{d}\\n\", .{not_null_num});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n5\n```\n\n\n:::\n:::\n\n\nNow, the `orelse` keyword behaves like a binary operator. You connect two expressions with this keyword.\nOn the left side of `orelse`, you provide the expression that might result\nin a null value, and on the right side of `orelse`, you provide another expression\nthat will not result in a null value.\n\nThe idea behind the `orelse` keyword is: if the expression on the left side\nresult in a not-null value, then, this not-null value is used. However,\nif this expression on the left side result in a null value, then, the value\nof the expression on the right side is used instead.\n\nLooking at the example below, since the `x` object is currently null, the\n`orelse` decided to use the alternative value, which is the number 15.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst x: ?i32 = null;\nconst dbl = (x orelse 15) * 2;\ntry stdout.print(\"{d}\\n\", .{dbl});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n30\n```\n\n\n:::\n:::\n\n\nYou can use the if statement or the `orelse` keyword, when you want to\nsolve (or deal with) this null value. However, if there is no clear solution\nto this null value, and the most logic and sane path is to simply panic\nand raise a loud error in your program when this null value is encountered,\nyou can use the `?` method of your optional object.\n\nIn essence, when you use this `?` method, the optional object is unwrapped.\nIf a not-null value is found in the optional object, then, this not-null value is used.\nOtherwise, the `unreachable` keyword is used. You can read more about this\n[`unreacheable` keyword at the official documentation](https://ziglang.org/documentation/master/#unreachable)[^un-docs].\nBut in essence, when you build your Zig source code using the build modes `ReleaseSafe` or `Debug`, this\n`unreacheable` keyword causes the program to panic and raise an error during runtime,\nlike in the example below:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nfn return_null(n: i32) ?i32 {\n if (n == 5) return null;\n return n;\n}\n\npub fn main() !void {\n const x: i32 = 5;\n const y: ?i32 = return_null(x);\n try stdout.print(\"{d}\\n\", .{y.?});\n}\n```\n:::\n\n\n```\nthread 12767 panic: attempt to use null value\np7.zig:12:34: 0x103419d in main (p7):\n try stdout.print(\"{d}\\n\", .{y.?});\n ^\n```\n\n\n[^un-docs]: .\n", "supporting": [ "05-pointers_files" ], diff --git a/_freeze/Chapters/07-build-system/execute-results/epub.json b/_freeze/Chapters/07-build-system/execute-results/epub.json deleted file mode 100644 index 57752a70..00000000 --- a/_freeze/Chapters/07-build-system/execute-results/epub.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "hash": "0286d5b6db10173d3df147400fd019aa", - "result": { - "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Build System {#sec-build-system}\n\n\nIn this chapter, we are going to talk about the build system, and how an entire project\nis built in Zig.\nOne key advantage of Zig is that it includes a build system embedded in the language itself.\nThis is great, because then you do not have to depend on an external system, separated\nfrom the compiler, to build your code.\n\n\nYou can find a good description of Zig's build system\nin the [article entitled \"Build System\"](https://ziglang.org/learn/build-system/#user-provided-options)[^zig-art1]\nfrom the official Zig's website.\nWe also have the excellent [series of posts written by Felix](https://zig.news/xq/zig-build-explained-part-1-59lf)[^felix].\nHence, this chapter represents an extra resource for you to consult and rely on.\n\n[^felix]: \n[^zig-art1]: \n\nBuilding code is one of the things that Zig is best at. One thing that is particularly\ndifficult in C/C++ and even in Rust, is to cross-compile source code to multiple targets\n(e.g. multiple computer architectures and operating systems),\nand the `zig` compiler is known for being one of the best existing pieces of software\nfor this particular task.\n\n\n\n\n## How source code is built?\n\nWe already have talked about the challenges of building source code in low-level languages\nin @sec-project-files. As we described at that section, programmers invented Build Systems\nto surpass these challenges on the process of building source code in low-level languages.\n\nLow-level languages uses a compiler to compile (or to build) your source code into binary instructions.\nIn C and C++, we normally use compilers like `gcc`, `g++` or `clang` to compile\nour C and C++ source code into these instructions.\nEvery language have its own compiler, and this is no different in Zig.\n\nIn Zig, we have the `zig` compiler to compile our Zig source code into\nbinary instructions that can be executed by our computer.\nIn Zig, the compilation (or the build) process involves\nthe following components:\n\n- The Zig modules that contains your source code;\n- Library files (either a dynamic library or a static library);\n- Compiler flags that tailors the build process to your needs.\n\nThese are the things that you need to connect together in order to build your\nsource code in Zig. In C and C++, you would have an extra component, which are the header files of\nthe libraries that you are using. But header files do not exist in Zig, so, you only need\nto care about them if you are linking your Zig source code with a C library.\nIf that is not your case, you can forget about it.\n\nYour build process is usually organized in a build script. In Zig, we normally\nwrite this build script into a Zig module in the root directory of our project,\nnamed as `build.zig`. You write this build script, then, when you run it, your project\ngets built into binary files that you can use and distribute to your users.\n\nThis build script is normally organized around *target objects*. A target is simply\nsomething to be built, or, in other words, it's something that you want the `zig` compiler\nto build for you. This concept of \"targets\" is present in most Build Systems,\nespecially in CMake[^cmake].\n\n[^cmake]: \n\nThere are four types of target objects that you can build in Zig, which are:\n\n- An executable (e.g. a `.exe` file on Windows).\n- A shared library (e.g. a `.so` file in Linux or a `.dll` file on Windows).\n- A static library (e.g. a `.a` file in Linux or a `.lib` file on Windows).\n- An executable file that executes only unit tests (or, a \"unit tests executable\").\n\nWe are going to talk more about these target objects in @sec-targets.\n\n\n\n## The `build()` function {#sec-build-fun}\n\nA build script in Zig always contains a public (and top-level) `build()` function declared.\nIt's like the `main()` function in the main Zig module of your project, that we discussed in @sec-main-file.\nBut instead of creating the entrypoint to your code, this `build()` function is the entrypoint to the build process.\n\nThis `build()` function should accept a pointer to a `Build` object as input, and it should use this \"build object\" to perform\nthe necessary steps to build your project. The return type of this function is always `void`,\nand this `Build` struct comes directly from the Zig Standard Library (`std.Build`). So, you can\naccess this struct by just importing the Zig Standard Library into your `build.zig` module.\n\nJust as a very simple example, here you can see the source code necessary to build\nan executable file from the `hello.zig` Zig module.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n });\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\nYou can define and use other functions and objects in this build script. You can also import\nother Zig modules as you would normally do in any other module of your project.\nThe only real requirement for this build script, is to have a public and top-level\n`build()` function defined, that accepts a pointer to a `Build` struct as input.\n\n\n## Target objects {#sec-targets}\n\nAs we described over the previous sections, a build script is composed around target objects.\nEach target object is normally a binary file (or an output) that you want to get from the build process. You can list\nmultiple target objects in your build script, so that the build process generates multiple\nbinary files for you at once.\n\nFor example, maybe you are a developer working in a cross-platform application,\nand, because this application is cross-platform, you probably need to release\nbinary files of your software for each OS supported by your application to your end users.\nThus, you can define a different target object in your build script\nfor each OS (Windows, Linux, etc.) where you want to publish your software.\nThis will make the `zig` compiler to build your project to multiple target OS's at once.\nThe Zig Build System official documentation have a [great code example that demonstrates this strategy](https://ziglang.org/learn/build-system/#handy-examples)[^zig-ex].\n\n[^zig-ex]: \n\n\nA target object is created by the following methods of the `Build` struct that we introduced\nin @sec-build-fun:\n\n- `addExecutable()` creates an executable file;\n- `addSharedLibrary()` creates a shared library file;\n- `addStaticLibrary()` creates a static library file;\n- `addTest()` creates an executable file that executes unit tests.\n\n\nThese functions are methods from the `Build` struct that you receive\nas input of the `build()` function. All of them, create as output\na `Compile` object, which represents a target object to be compiled\nby the `zig` compiler. All of these functions accept a similar struct literal as input.\nThis struct literal defines three essential specs about this target object that you are building:\n`name`, `target` and `root_source_file`.\n\nWe have already seen these three options being used on the previous example,\nwhere we used the `addExecutable()` method to create an executable target object.\nThis example is reproduced below. Notice the use of the `path()` method\nfrom the `Build` struct, to define a path in the `root_source_file` option.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n});\n```\n:::\n\n\n\nThe `name` option specify the name that you want to give to the binary file defined\nby this target object. So, in this example, we are building an executable file named `hello`.\nIt's common to set this `name` option to the name of your project.\n\n\nFurthermore, the `target` option specify the target computer architecture (or the target operating system) of this\nbinary file. For example, if you want this target object to run on a Windows machine\nthat uses a `x86_64` architecture, you can set this `target` option to `x86_64-windows-gnu` for example.\nThis will make the `zig` compiler to compile the project to run on a `x86_64` Windows machine.\nYou can see the full list of architectures and OS's that the `zig` compiler supports by running\nthe `zig targets` command in the terminal.\n\nNow, if you are building the project to run on the current machine\nthat you are using to run this build script, you can set this `target`\noption to the `host` method of the `Build` object, like we did in the example above.\nThis `host` method identifies the current machine where you are\ncurrently running the `zig` compiler.\n\n\nAt last, the `root_source_file` option specifies the root Zig module of your project.\nThat is the Zig module that contains the entrypoint to your application (i.e., the `main()` function), or, the main API of your library.\nThis also means that, all the Zig modules that compose your project are automatically discovered\nfrom the import statements you have inside this \"root source file\".\nThe `zig` compiler can detect when a Zig module depends on the other through the import statements,\nand, as a result, it can discover the entire map of Zig modules used in your project.\n\nThis is handy, and it's different from what happens in other build systems.\nIn CMake for example, you have to explicitly list the paths to all source files that you want to\ninclude in your build process. This is probably a symptom of the \"lack of conditional\ncompilation\" in the C and C++ compilers. Since they lack this feature, you have\nto explicitly choose which source files should be sent to the C/C++ compiler, because not\nevery C/C++ code is portable or supported in every operating system, and, therefore,\nwould cause a compilation error in the C/C++ compiler.\n\n\nNow, one important detail about the build process is that, you have to **explicitly\ninstall the target objects that you create in your build script**, by using the\n`installArtifact()` method of the `Build` struct.\n\nEverytime you invoke the build process of your project, by calling the `build` command\nof the `zig` compiler, a new directory named `zig-out` is created in the root\ndirectory of your project. This new directory contains the outputs of the build process,\nthat is, the binary files built from your source code.\n\nWhat the `installArtifact()` method do is to install (or copy) the built target objects\nthat you defined to this `zig-out` directory.\nThis means that, if you do not\ninstall the target objects you define in your build script, these target objects are\nessentially discarded at the end of the build process.\n\nFor example, you might be building a project that uses a third party library that is built\ntogether with the project. So, when you build your project, you would need first, to\nbuild the third party library, and then, you link it with the source code of your project.\nSo, in this case, we have two binary files that are generated in the build process (the executable file of your project, and the third party library).\nBut only one is of interest, which is the executable file of our project.\nWe can discard the binary file of the third party library, by simply not installing it\ninto this `zig-out` directory.\n\nThis `installArtifact()` method is pretty straightforward. Just remember to apply it to every\ntarget object that you want to save into the `zig-out` directory, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n});\n\nb.installArtifact(exe);\n```\n:::\n\n\n\n\n## Setting the build mode\n\nWe have talked about the three essential options that are set when you create a new target object.\nBut there is also a fourth option that you can use to set the build mode of this target object,\nwhich is the `optimize` option.\nThis option is called this way, because the build modes in Zig are treated more of\nan \"optimization vs safety\" problem. So optimization plays an important role here.\nDon't worry, I'm going back to this question very soon.\n\nIn Zig, we have four build modes (which are listed below). Each one of these build modes offer\ndifferent advantages and characteristics. As we described in @sec-compile-debug-mode, the `zig` compiler\nuses the `Debug` build mode by default, when you don't explicitly choose a build mode.\n\n- `Debug`, mode that produces and includes debugging information in the output of the build process (i.e., the binary file defined by the target object);\n- `ReleaseSmall`, mode that tries to produce a binary file that is small in size;\n- `ReleaseFast`, mode that tries to optimize your code, in order to produce a binary file that is as fast as possible;\n- `ReleaseSafe`, mode that tries to make your code as safe as possible, by including safeguards when possible.\n\nSo, when you build your project, you can set the build mode of your target object to `ReleaseFast` for example, which will tell\nthe `zig` compiler to apply important optimizations in your code. This creates a binary file\nthat simply runs faster on most contexts, because it contains a more optimized version of your code.\nHowever, as a result, we often lose some safety features in our code.\nBecause some safety checks are removed from the final binary file,\nwhich makes your code run faster, but in a less safe manner.\n\nThis choice depends on your current priorities. If you are building a cryptography or banking system, you might\nprefer to prioritize safety in your code, so, you would choose the `ReleaseSafe` build mode, which is a little\nslower to run, but much more secure, because it includes all possible runtime safety checks in the binary file\nbuilt in the build process. In the other hand, if you are writing a game for example, you might prefer to prioritize performance\nover safety, by using the `ReleaseFast` build mode, so that your users can experience faster frame rates in your game.\n\nIn the example below, we are creating the same target object that we have used on previous examples.\nBut this time, we are specifying the build mode of this target object to the `ReleaseSafe` mode.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n .optimize = .ReleaseSafe\n});\nb.installArtifact(exe);\n```\n:::\n\n\n\n\n## Setting the version of your build\n\nEverytime you build a target object in your build script, you can assign a version\nnumber to this specific build, following a semantic versioning framework.\nYou can find more about semantic versioning by visiting the [Semantic Versioning website](https://semver.org/)[^semver].\nAnyway, in Zig, you can specify the version of your build, by providing a `SemanticVersion` struct to\nthe `version` option, like in the example below:\n\n\n[^semver]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n .version = .{\n .major = 2, .minor = 9, .patch = 7\n }\n});\nb.installArtifact(exe);\n```\n:::\n\n\n\n\n## Detecting the OS in your build script {#sec-detect-os}\n\nIt's very common in Build Systems to use different options, or, to include different modules, or,\nto link against different libraries depending on the Operational System (OS)\nthat you are targeting in the build process.\n\nIn Zig, you can detect the target OS of the build process, by looking\nat the `os.tag` inside the `builtin` module from the Zig library.\nIn the example below, we are using an if statement to run some\narbitrary code when the target of the build process is a\nWindows system.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nif (builtin.target.os.tag == .windows) {\n // Code that runs only when the target of\n // the compilation process is Windows.\n}\n```\n:::\n\n\n\n\n## Adding a run step to your build process\n\nOne thing that is neat in Rust is that you can compile and run your\nsource code with one single command (`cargo run`) from the Rust compiler.\nWe saw in @sec-compile-run-code how can we perform a similar job in Zig, by\nbuilding and running our Zig source code through the `run` command from the `zig` compiler.\n\nBut how can we, at the same time, build and run the binary file specified by a target object in our\nbuild script?\nThe answer is by including a \"run artifact\" in our build script.\nA run artifact is created through the `addRunArtifact()` method from the `Build` struct.\nWe simply provide as input to this function the target object that describes the binary file that we\nwant to execute. As a result, this function creates a run artifact that is capable of executing\nthis binary file.\n\nIn the example below, we are defining an executable binary file named `hello`,\nand we use this `addRunArtifact()` method to create a run artifact that will execute\nthis `hello` executable file.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"src/hello.zig\"),\n .target = b.host\n});\nb.installArtifact(exe);\nconst run_arti = b.addRunArtifact(exe);\n```\n:::\n\n\n\nNow that we have created this run artifact, we need to include it in\nthe build process. We do that by declaring a new step in our build\nscript to call this artifact, through the `step()` method of the `Build`\nstruct.\n\nWe can give any name we want to this step, but, for our\ncontext here, I'm going to name this step as \"run\".\nAlso, I give it a brief description to this step (\"Run the project\").\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst run_step = b.step(\n \"run\", \"Run the project\"\n);\n```\n:::\n\n\n\n\nNow that we have declared this \"run step\" we need to tell Zig that\nthis \"run step\" depends on the run artifact.\nIn other words, a run artifact always depends on a \"step\" to effectively be executed.\nBy creating this dependency\nwe finally stablish the necessary commands to build and run the executable file\nfrom the build script.\n\nWe can establish a dependency between the run step and the run artifact\nby using the `dependsOn()` method from the run step. So, we first\ncreate the run step, and then, we link it with the run artifact, by\nusing this `dependsOn()` method from the run step.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nrun_step.dependOn(&run_arti.step);\n```\n:::\n\n\n\nThe entire source code of this specific build script that\nwe wrote, piece by piece, in this section, is\navailable in the `build_and_run.zig` module. You can\nsee this module by\n[visiting the official repository of this book](https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_and_run.zig)\n[^module-src].\n\n\n[^module-src]: \n\nWhen you declare a new step in your build script, this step\nbecomes available through the `build` command in the `zig` compiler.\nYou can actually see this step by running `zig build --help` in the terminal, like\nin the example below, where we can see that this new \"run\"\nstep that we declared in the build script appeared in the output.\n\n```bash\nzig build --help\n```\n\n```\nSteps:\n ...\n run Run the project\n ...\n```\n\nNow, everything that we need to is to\ncall this \"run\" step that we created in our build script. We\ncall it by using the name that we gave to this step\nafter the `build` command from the `zig` compiler.\nThis will cause the compiler to build our executable file\nand execute it at the same time.\n\n```bash\nzig build run\n```\n\n## Build unit tests in your project\n\nWe have talked at length about writing unit tests in Zig in @sec-unittests,\nand we also have talked about how to execute these unit tests through\nthe `test` command of the `zig` compiler. However,\nas we did with the `run` command on the previous section, we also might want to\ninclude some commands in our build script to also build and execute the unit tests in our project.\n\nSo, once again, we are going to discuss how a specific built-in command from the `zig` compiler,\n(in this case, the `test` command) can be used in a build script in Zig.\nHere is where a \"test target object\" comes into play.\nAs was described in @sec-targets, we can create a test target object by using the `addTest()` method of\nthe `Build` struct. The first thing that we need to do is to\ndeclare a test target object in our build script.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst test_exe = b.addTest(.{\n .name = \"unit_tests\",\n .root_source_file = b.path(\"src/main.zig\"),\n .target = b.host,\n});\nb.installArtifact(test_exe);\n```\n:::\n\n\n\n\nA test target object essentially selects all `test` blocks in all Zig modules\nacross your project, and builds only the source code present inside\nthese `test` blocks in your project. As a result, this target object\ncreates an executable file that contains only the source code present\nin all of these `test` blocks (i.e., the unit tests) in your project.\n\nPerfect! Now that we have declared this test target object, an executable file\nnamed `unit_tests` is built by the `zig` compiler when we trigger the build\nscript with the `build` command. After the build\nprocess is finished, we can simply execute this `unit_tests` executable\nin the terminal.\n\nHowever, if you remember the previous section, we already learned\nhow can we create a run step in our build script, to execute an executable file\nbuilt by the build script.\n\nSo, we could simply add a run step in our build script to run these unit tests\nfrom a single command in the `zig` compiler, to make our lifes easier.\nIn the example below, we demonstrate the commands to\nregister a new build step called \"tests\" in our build script\nto run these unit tests.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst run_arti = b.addRunArtifact(test_exe);\nconst run_step = b.step(\"tests\", \"Run unit tests\");\nrun_step.dependOn(&run_arti.step);\n```\n:::\n\n\n\nNow that we registered this new build step, we can trigger it by calling the command below\nin the terminal. You can also checkout the complete source\ncode for this specific build script at the `build_tests.zig` module at the\n[official repository of this book](https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_tests.zig)\n[^module-src2].\n\n\n[^module-src2]: \n\n\n```bash\nzig build tests\n```\n\n\n## Tailoring your build process with user-provided options\n\nSometimes, you want to make a build script that is customizable by the user\nof your project. You can do that by creating user-provided options in\nyour build script. We create an user-provided option by using the\n`option()` method from the `Build` struct.\n\nWith this method, we create a \"build option\" which can be passed\nto the `build.zig` script at the command line. The user have the power of setting\nthis option at the `build` command from the\n`zig` compiler. In other words, each build option that we create\nbecomes a new command line argument that is accessible through the `build` command\nof the compiler.\n\nThese \"user-provided options\" are set by using the prefix `-D` in the command line.\nFor example, if we declare an option named `use_zlib`, that receives a boolean value which\nindicates if we should link our source code to `zlib` or not, we can set the value\nof this option in the command line with `-Duse_zlib`. The code example below\ndemonstrates this idea:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const use_zlib = b.option(\n bool,\n \"use_zlib\",\n \"Should link to zlib?\"\n ) orelse false;\n const exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"example.zig\"),\n .target = b.host,\n });\n if (use_zlib) {\n exe.linkSystemLibrary(\"zlib\");\n }\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n```bash\nzig build -Duse_zlib=false\n```\n\n\n## Linking to external libraries\n\n\nOne essential part of every build process is the linking stage.\nThis stage is responsible for combining the multiple object files\nthat represent your code, into a single executable file. It also links\nthis executable file to external libraries, if you use any in your code.\n\nIn Zig, we have two notions of a \"library\", which are: 1) a system's library;\n2) a local library. A system's library is just a library that is already installed\nin your system. While a local library is a library that belongs to the current\nproject; a library that is present in your project directory, and\nthat you are building together with your project source code.\n\nThe basic difference between the two, is that a system's library is already\nbuilt and installed in your system, supposedly, and all you need to do\nis to link your source code to this library to start using it.\nWe do that by using the `linkSystemLibrary()` method from a\n`Compile` object. This method accepts the name of the library\nin a string as input. Remember from @sec-targets that a `Compile` object\nis a target object that you declare in your build script.\n\nWhen you link a particular target object with a system's library,\nthe `zig` compiler will use `pkg-config` to find where\nare the binary files and also the header files of this library\nin your system.\nWhen it finds these files, the linker present in the `zig` compiler\nwill link your object files with the files of this library to\nproduce a single binary file for you.\n\nIn the example below, we are creating an executable file named `image_filter`,\nand, we are linking this executable file to the C Standard Library with the\nmethod `linkLibC()`, but we also are linking this executable file to the\nC library `libpng` that is currently installed in my system.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const exe = b.addExecutable(.{\n .name = \"image_filter\",\n .root_source_file = b.path(\"src/main.zig\"),\n .target = target,\n .optimize = optimize,\n });\n exe.linkLibC();\n exe.linkSystemLibrary(\"png\");\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\nIf you are linking with a C library in your project, is generally a good idea\nto also link your code with the C Standard Library. Because is very likely\nthat this C library uses some functionality of the C Standard Library at some point.\nThe same goes to C++ libraries. So, if you are linking with\nC++ libraries, is a good idea to link your project with the C++\nStandard Library by using the `linkLibCpp()` method.\n\nOn the order side, when you want to link with a local library,\nyou should use the `linkLibrary()` method of a `Compile` object.\nThis method expects to receive another `Compile` object as input.\nThat is, another target object defined in your build script,\nusing either the `addStaticLibrary()` or `addSharedLibrary()` methods\nwhich defines a library to be built.\n\nAs we discussed earlier, a local library is a library\nthat is local to your project, and that is being built together\nwith your project. So, you need to create a target object in your build script\nto build this local library. Then, you link the target objects of interest in your project,\nwith this target object that identifies this local library.\n\nTake a look at this example extracted from the build script of the [`libxev` library](https://github.com/mitchellh/libxev/tree/main)[^libxev2].\nYou can see in this snippet that\nwe are declaring a shared library file, from the `c_api.zig`\nmodule. Then, later in the build script, we declare an\nexecutable file named `\"dynamic-binding-test\"`, which\nlinks to this shared library that we defined earlier\nin the script.\n\n[^libxev2]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst optimize = b.standardOptimizeOption(.{});\nconst target = b.standardTargetOptions(.{});\n\nconst dynamic_lib = b.addSharedLibrary(.{\n .name = dynamic_lib_name,\n .root_source_file = b.path(\"src/c_api.zig\"),\n .target = target,\n .optimize = optimize,\n});\nb.installArtifact(dynamic_lib);\n// ... more lines in the script\nconst dynamic_binding_test = b.addExecutable(.{\n .name = \"dynamic-binding-test\",\n .target = target,\n .optimize = optimize,\n});\ndynamic_binding_test.linkLibrary(dynamic_lib);\n```\n:::\n\n\n\n\n\n## Building C code {#sec-building-c-code}\n\nThe `zig` compiler comes with a C compiler embedded in it. In other words,\nyou can use the `zig` compiler to build C projects. This C compiler is available\nthrough the `cc` command of the `zig` compiler.\n\nAs an example, let's use the famous [FreeType library](https://freetype.org/)[^freetype].\nFreeType is one of the most widely used pieces of software in the world.\nIt's a C library designed to produce high-quality fonts. But it's also\nheavily used in the industry to natively render text and fonts\nin the screen of your computer.\n\nIn this section, we are going to write a build script, piece by piece, that is capable\nof building the FreeType project from source.\nYou can find the source code of this build script on the\n[`freetype-zig` repository](https://github.com/pedropark99/freetype-zig/tree/main)[^freetype-zig]\navailable at GitHub.\n\n[^freetype]: \n[^freetype-zig]: \n\nAfter you download the source code of FreeType from the official website[^freetype],\nyou can start writing the `build.zig` module. We begin by defining the target object\nthat defines the binary file that we want to compile.\n\nAs an example, I will build the project as a static library file using the `addStaticLibrary()` method\nto create the target object.\nAlso, since FreeType is a C library, I will also link the library\nagainst `libc` through the `linkLibC()` method, to guarantee that any use\nof the C Standard Library is covered in the compilation process.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst target = b.standardTargetOptions(.{});\nconst opti = b.standardOptimizeOption(.{});\nconst lib = b.addStaticLibrary(.{\n .name = \"freetype\",\n .optimize = opti,\n .target = target,\n});\nlib.linkLibC();\n```\n:::\n\n\n\n### Creating C compiler flags\n\nCompiler flags are also known as \"compiler options\" by many programmers,\nor also, as \"command options\" in the GCC official documentation.\nIt's fair to also call them as the \"command-line arguments\" of the C compiler.\nIn general, we use compiler flags to turn on (or turn off) some features from the compiler,\nor to tweak the compilation process to fit the needs of our project.\n\nIn build scripts written in Zig, we normally list the C compiler flags to be used in the compilation process\nin a simple array, like in the example below.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c_flags = [_][]const u8{\n \"-Wall\",\n \"-Wextra\",\n \"-Werror\",\n};\n```\n:::\n\n\n\nIn theory, there is nothing stopping you from using this array to add \"include paths\" (with the `-I` flag)\nor \"library paths\" (with the `-L` flag) to the compilation process. But there are formal ways in Zig to\nadd these types of paths in the compilation process. Both are discussed in @sec-include-paths\nand @sec-library-paths.\n\nAnyway, in Zig, we add C flags to the build process together with the C files that we want to compile, by using the\n`addCSourceFile()` and `addCSourceFiles()` methods. In the example above, we have just declared\nthe C flags that we want to use. But we haven't added them to the build process yet.\nTo do that, we also need to list the C files to be compiled.\n\n### Listing your C files\n\nThe C files that contains \"cross-platform\" source code are listed in the `c_source_files`\nobject below. These are the C files that are included by default in every platform\nsupported by the FreeType library. Now, since the amount of C files in the FreeType library is big,\nI have omitted the rest of the files in the code example below, for brevity purposes.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c_source_files = [_][]const u8{\n \"src/autofit/autofit.c\",\n \"src/base/ftbase.c\",\n // ... and many other C files.\n};\n```\n:::\n\n\n\nNow, in addition to \"cross-platform\" source code, we also have some C files in the FreeType project\nthat are platform-specific, meaning that, they contain source code that can only be compiled in specific platforms,\nand, as a result, they are only included in the build process on these specific target platforms.\nThe objects that list these C files are exposed in the code example below.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst windows_c_source_files = [_][]const u8{\n \"builds/windows/ftdebug.c\",\n \"builds/windows/ftsystem.c\"\n};\nconst linux_c_source_files = [_][]const u8{\n \"src/base/ftsystem.c\",\n \"src/base/ftdebug.c\"\n};\n```\n:::\n\n\n\nNow that we declared both the files that we want to include and the C compiler flags to be used,\nwe can add them to the target object that describes the FreeType library, by using the\n`addCSourceFile()` and `addCSourceFiles()` methods.\n\nBoth of these functions are methods from a `Compile` object (i.e., a target object).\nThe `addCSourceFile()` method is capable of adding a single C file to the target object,\nwhile the `addCSourceFiles()` method is used to add multiple C files in a single command.\nYou might prefer to use `addCSourceFile()` when you need to use different compiler flags\non specific C files in your project. But, if you can use the same compiler flags\nacross all C files, then, you will probably find `addCSourceFiles()` a better choice.\n\nNotice that we are using the `addCSourceFiles()` method in the example below,\nto add both the C files and the C compiler flags. Also notice that we\nare using the `os.tag` that we learned about in @sec-detect-os, to add the platform-specific\nC files.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nlib.addCSourceFiles(\n &c_source_files, &c_flags\n);\n\nswitch (builtin.target.os.tag) {\n .windows => {\n lib.addCSourceFiles(\n &windows_c_source_files,\n &c_flags\n );\n },\n .linux => {\n lib.addCSourceFiles(\n &linux_c_source_files,\n &c_flags\n );\n },\n else => {},\n}\n```\n:::\n\n\n\n\n### Defining C Macros\n\nC Macros are an essential part of the C programming language,\nand they are commonly defined through the `-D` flag from a C compiler.\nIn Zig, you can define a C Macro to be used in your build process\nby using the `defineCMacro()` method from the target object that\ndefines the binary file that you are building.\n\nIn the example below, we are using the `lib` object that we have defined\nin the previous sections to define some C Macros used by the FreeType project\nin the compilation process. These C Macros specify if FreeType\nshould (or should not) include functionalities from different\nexternal libraries.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nlib.defineCMacro(\"FT_DISABLE_ZLIB\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_PNG\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_HARFBUZZ\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_BZIP2\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_BROTLI\", \"TRUE\");\nlib.defineCMacro(\"FT2_BUILD_LIBRARY\", \"TRUE\");\n```\n:::\n\n\n\n\n### Adding library paths {#sec-library-paths}\n\nLibrary paths are paths in your computer where the C compiler will look (or search) for\nlibrary files to link against your source code. In other words, when you use a library in your\nC source code, and you ask the C compiler to link your source code against this library,\nthe C compiler will search for the binary files of this library across the paths listed\nin this \"library paths\" set.\n\nThese paths are platform specific, and, by default, the C compiler starts by looking at a\npre-defined set of places in your computer. But you can add more paths (or more places)\nto this list. For example, you may have a library installed in a non-conventional place of your\ncomputer, and you can make the C compiler \"see\" this \"non-conventional place\" by adding this path\nto this list of pre-defined paths.\n\nIn Zig, you can add more paths to this set by using the `addLibraryPath()` method from your target object.\nFirst, you defined a `LazyPath` object, containing the path you want to add, then,\nyou provide this object as input to the `addLibraryPath()` method, like in the example below:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst lib_path: std.Build.LazyPath = .{\n .cwd_relative = \"/usr/local/lib/\"\n};\nlib.addLibraryPath(lib_path);\n```\n:::\n\n\n\n\n\n\n### Adding include paths {#sec-include-paths}\n\nThe preprocessor search path is a popular concept from the\nC community, but it's also known by many C programmers as \"include paths\", because\nthe paths in this \"search path\" relate to the `#include` statements found in the C files.\n\nInclude paths are similar to library paths. They are a set of pre-defined places in your computer where\nthe C compiler will look for files during the compilation process. But instead of looking for\nlibrary files, the include paths are places where the compiler looks for header files included\nin your C source code.\nThis is why many C programmers prefer to call these paths as the \"preprocessor search path\".\nBecause header files are processed during the preprocessor stage of the compilation\nprocess.\n\nSo, every header file that you include in your C source code, through a `#include` statements needs to\nbe found somewhere, and the C compiler will search for this header file across the paths listed in this \"include paths\" set.\nInclude paths are added to the compilation process through the `-I` flag.\n\nIn Zig, you can add new paths to this pre-defined set of paths, by using the `addIncludePath()` method\nfrom your target object. This method also accepts a `LazyPath` object as input.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst inc_path: std.Build.LazyPath = .{\n .path = \"./include\"\n};\nlib.addIncludePath(inc_path);\n```\n:::\n", - "supporting": [ - "07-build-system_files" - ], - "filters": [ - "rmarkdown/pagebreak.lua" - ], - "includes": {}, - "engineDependencies": { - "knitr": [ - "{\"type\":\"list\",\"attributes\":{},\"value\":[]}" - ] - }, - "preserve": null, - "postProcess": false - } -} \ No newline at end of file diff --git a/_freeze/Chapters/07-build-system/execute-results/html.json b/_freeze/Chapters/07-build-system/execute-results/html.json index 8d0f268d..b1269ae0 100644 --- a/_freeze/Chapters/07-build-system/execute-results/html.json +++ b/_freeze/Chapters/07-build-system/execute-results/html.json @@ -2,10 +2,8 @@ "hash": "0286d5b6db10173d3df147400fd019aa", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Build System {#sec-build-system}\n\n\nIn this chapter, we are going to talk about the build system, and how an entire project\nis built in Zig.\nOne key advantage of Zig is that it includes a build system embedded in the language itself.\nThis is great, because then you do not have to depend on an external system, separated\nfrom the compiler, to build your code.\n\n\nYou can find a good description of Zig's build system\nin the [article entitled \"Build System\"](https://ziglang.org/learn/build-system/#user-provided-options)[^zig-art1]\nfrom the official Zig's website.\nWe also have the excellent [series of posts written by Felix](https://zig.news/xq/zig-build-explained-part-1-59lf)[^felix].\nHence, this chapter represents an extra resource for you to consult and rely on.\n\n[^felix]: \n[^zig-art1]: \n\nBuilding code is one of the things that Zig is best at. One thing that is particularly\ndifficult in C/C++ and even in Rust, is to cross-compile source code to multiple targets\n(e.g. multiple computer architectures and operating systems),\nand the `zig` compiler is known for being one of the best existing pieces of software\nfor this particular task.\n\n\n\n\n## How source code is built?\n\nWe already have talked about the challenges of building source code in low-level languages\nin @sec-project-files. As we described at that section, programmers invented Build Systems\nto surpass these challenges on the process of building source code in low-level languages.\n\nLow-level languages uses a compiler to compile (or to build) your source code into binary instructions.\nIn C and C++, we normally use compilers like `gcc`, `g++` or `clang` to compile\nour C and C++ source code into these instructions.\nEvery language have its own compiler, and this is no different in Zig.\n\nIn Zig, we have the `zig` compiler to compile our Zig source code into\nbinary instructions that can be executed by our computer.\nIn Zig, the compilation (or the build) process involves\nthe following components:\n\n- The Zig modules that contains your source code;\n- Library files (either a dynamic library or a static library);\n- Compiler flags that tailors the build process to your needs.\n\nThese are the things that you need to connect together in order to build your\nsource code in Zig. In C and C++, you would have an extra component, which are the header files of\nthe libraries that you are using. But header files do not exist in Zig, so, you only need\nto care about them if you are linking your Zig source code with a C library.\nIf that is not your case, you can forget about it.\n\nYour build process is usually organized in a build script. In Zig, we normally\nwrite this build script into a Zig module in the root directory of our project,\nnamed as `build.zig`. You write this build script, then, when you run it, your project\ngets built into binary files that you can use and distribute to your users.\n\nThis build script is normally organized around *target objects*. A target is simply\nsomething to be built, or, in other words, it's something that you want the `zig` compiler\nto build for you. This concept of \"targets\" is present in most Build Systems,\nespecially in CMake[^cmake].\n\n[^cmake]: \n\nThere are four types of target objects that you can build in Zig, which are:\n\n- An executable (e.g. a `.exe` file on Windows).\n- A shared library (e.g. a `.so` file in Linux or a `.dll` file on Windows).\n- A static library (e.g. a `.a` file in Linux or a `.lib` file on Windows).\n- An executable file that executes only unit tests (or, a \"unit tests executable\").\n\nWe are going to talk more about these target objects in @sec-targets.\n\n\n\n## The `build()` function {#sec-build-fun}\n\nA build script in Zig always contains a public (and top-level) `build()` function declared.\nIt's like the `main()` function in the main Zig module of your project, that we discussed in @sec-main-file.\nBut instead of creating the entrypoint to your code, this `build()` function is the entrypoint to the build process.\n\nThis `build()` function should accept a pointer to a `Build` object as input, and it should use this \"build object\" to perform\nthe necessary steps to build your project. The return type of this function is always `void`,\nand this `Build` struct comes directly from the Zig Standard Library (`std.Build`). So, you can\naccess this struct by just importing the Zig Standard Library into your `build.zig` module.\n\nJust as a very simple example, here you can see the source code necessary to build\nan executable file from the `hello.zig` Zig module.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n });\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n\nYou can define and use other functions and objects in this build script. You can also import\nother Zig modules as you would normally do in any other module of your project.\nThe only real requirement for this build script, is to have a public and top-level\n`build()` function defined, that accepts a pointer to a `Build` struct as input.\n\n\n## Target objects {#sec-targets}\n\nAs we described over the previous sections, a build script is composed around target objects.\nEach target object is normally a binary file (or an output) that you want to get from the build process. You can list\nmultiple target objects in your build script, so that the build process generates multiple\nbinary files for you at once.\n\nFor example, maybe you are a developer working in a cross-platform application,\nand, because this application is cross-platform, you probably need to release\nbinary files of your software for each OS supported by your application to your end users.\nThus, you can define a different target object in your build script\nfor each OS (Windows, Linux, etc.) where you want to publish your software.\nThis will make the `zig` compiler to build your project to multiple target OS's at once.\nThe Zig Build System official documentation have a [great code example that demonstrates this strategy](https://ziglang.org/learn/build-system/#handy-examples)[^zig-ex].\n\n[^zig-ex]: \n\n\nA target object is created by the following methods of the `Build` struct that we introduced\nin @sec-build-fun:\n\n- `addExecutable()` creates an executable file;\n- `addSharedLibrary()` creates a shared library file;\n- `addStaticLibrary()` creates a static library file;\n- `addTest()` creates an executable file that executes unit tests.\n\n\nThese functions are methods from the `Build` struct that you receive\nas input of the `build()` function. All of them, create as output\na `Compile` object, which represents a target object to be compiled\nby the `zig` compiler. All of these functions accept a similar struct literal as input.\nThis struct literal defines three essential specs about this target object that you are building:\n`name`, `target` and `root_source_file`.\n\nWe have already seen these three options being used on the previous example,\nwhere we used the `addExecutable()` method to create an executable target object.\nThis example is reproduced below. Notice the use of the `path()` method\nfrom the `Build` struct, to define a path in the `root_source_file` option.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n});\n```\n:::\n\n\n\n\nThe `name` option specify the name that you want to give to the binary file defined\nby this target object. So, in this example, we are building an executable file named `hello`.\nIt's common to set this `name` option to the name of your project.\n\n\nFurthermore, the `target` option specify the target computer architecture (or the target operating system) of this\nbinary file. For example, if you want this target object to run on a Windows machine\nthat uses a `x86_64` architecture, you can set this `target` option to `x86_64-windows-gnu` for example.\nThis will make the `zig` compiler to compile the project to run on a `x86_64` Windows machine.\nYou can see the full list of architectures and OS's that the `zig` compiler supports by running\nthe `zig targets` command in the terminal.\n\nNow, if you are building the project to run on the current machine\nthat you are using to run this build script, you can set this `target`\noption to the `host` method of the `Build` object, like we did in the example above.\nThis `host` method identifies the current machine where you are\ncurrently running the `zig` compiler.\n\n\nAt last, the `root_source_file` option specifies the root Zig module of your project.\nThat is the Zig module that contains the entrypoint to your application (i.e., the `main()` function), or, the main API of your library.\nThis also means that, all the Zig modules that compose your project are automatically discovered\nfrom the import statements you have inside this \"root source file\".\nThe `zig` compiler can detect when a Zig module depends on the other through the import statements,\nand, as a result, it can discover the entire map of Zig modules used in your project.\n\nThis is handy, and it's different from what happens in other build systems.\nIn CMake for example, you have to explicitly list the paths to all source files that you want to\ninclude in your build process. This is probably a symptom of the \"lack of conditional\ncompilation\" in the C and C++ compilers. Since they lack this feature, you have\nto explicitly choose which source files should be sent to the C/C++ compiler, because not\nevery C/C++ code is portable or supported in every operating system, and, therefore,\nwould cause a compilation error in the C/C++ compiler.\n\n\nNow, one important detail about the build process is that, you have to **explicitly\ninstall the target objects that you create in your build script**, by using the\n`installArtifact()` method of the `Build` struct.\n\nEverytime you invoke the build process of your project, by calling the `build` command\nof the `zig` compiler, a new directory named `zig-out` is created in the root\ndirectory of your project. This new directory contains the outputs of the build process,\nthat is, the binary files built from your source code.\n\nWhat the `installArtifact()` method do is to install (or copy) the built target objects\nthat you defined to this `zig-out` directory.\nThis means that, if you do not\ninstall the target objects you define in your build script, these target objects are\nessentially discarded at the end of the build process.\n\nFor example, you might be building a project that uses a third party library that is built\ntogether with the project. So, when you build your project, you would need first, to\nbuild the third party library, and then, you link it with the source code of your project.\nSo, in this case, we have two binary files that are generated in the build process (the executable file of your project, and the third party library).\nBut only one is of interest, which is the executable file of our project.\nWe can discard the binary file of the third party library, by simply not installing it\ninto this `zig-out` directory.\n\nThis `installArtifact()` method is pretty straightforward. Just remember to apply it to every\ntarget object that you want to save into the `zig-out` directory, like in the example below:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n});\n\nb.installArtifact(exe);\n```\n:::\n\n\n\n\n\n## Setting the build mode\n\nWe have talked about the three essential options that are set when you create a new target object.\nBut there is also a fourth option that you can use to set the build mode of this target object,\nwhich is the `optimize` option.\nThis option is called this way, because the build modes in Zig are treated more of\nan \"optimization vs safety\" problem. So optimization plays an important role here.\nDon't worry, I'm going back to this question very soon.\n\nIn Zig, we have four build modes (which are listed below). Each one of these build modes offer\ndifferent advantages and characteristics. As we described in @sec-compile-debug-mode, the `zig` compiler\nuses the `Debug` build mode by default, when you don't explicitly choose a build mode.\n\n- `Debug`, mode that produces and includes debugging information in the output of the build process (i.e., the binary file defined by the target object);\n- `ReleaseSmall`, mode that tries to produce a binary file that is small in size;\n- `ReleaseFast`, mode that tries to optimize your code, in order to produce a binary file that is as fast as possible;\n- `ReleaseSafe`, mode that tries to make your code as safe as possible, by including safeguards when possible.\n\nSo, when you build your project, you can set the build mode of your target object to `ReleaseFast` for example, which will tell\nthe `zig` compiler to apply important optimizations in your code. This creates a binary file\nthat simply runs faster on most contexts, because it contains a more optimized version of your code.\nHowever, as a result, we often lose some safety features in our code.\nBecause some safety checks are removed from the final binary file,\nwhich makes your code run faster, but in a less safe manner.\n\nThis choice depends on your current priorities. If you are building a cryptography or banking system, you might\nprefer to prioritize safety in your code, so, you would choose the `ReleaseSafe` build mode, which is a little\nslower to run, but much more secure, because it includes all possible runtime safety checks in the binary file\nbuilt in the build process. In the other hand, if you are writing a game for example, you might prefer to prioritize performance\nover safety, by using the `ReleaseFast` build mode, so that your users can experience faster frame rates in your game.\n\nIn the example below, we are creating the same target object that we have used on previous examples.\nBut this time, we are specifying the build mode of this target object to the `ReleaseSafe` mode.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n .optimize = .ReleaseSafe\n});\nb.installArtifact(exe);\n```\n:::\n\n\n\n\n\n## Setting the version of your build\n\nEverytime you build a target object in your build script, you can assign a version\nnumber to this specific build, following a semantic versioning framework.\nYou can find more about semantic versioning by visiting the [Semantic Versioning website](https://semver.org/)[^semver].\nAnyway, in Zig, you can specify the version of your build, by providing a `SemanticVersion` struct to\nthe `version` option, like in the example below:\n\n\n[^semver]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n .version = .{\n .major = 2, .minor = 9, .patch = 7\n }\n});\nb.installArtifact(exe);\n```\n:::\n\n\n\n\n\n## Detecting the OS in your build script {#sec-detect-os}\n\nIt's very common in Build Systems to use different options, or, to include different modules, or,\nto link against different libraries depending on the Operational System (OS)\nthat you are targeting in the build process.\n\nIn Zig, you can detect the target OS of the build process, by looking\nat the `os.tag` inside the `builtin` module from the Zig library.\nIn the example below, we are using an if statement to run some\narbitrary code when the target of the build process is a\nWindows system.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nif (builtin.target.os.tag == .windows) {\n // Code that runs only when the target of\n // the compilation process is Windows.\n}\n```\n:::\n\n\n\n\n\n## Adding a run step to your build process\n\nOne thing that is neat in Rust is that you can compile and run your\nsource code with one single command (`cargo run`) from the Rust compiler.\nWe saw in @sec-compile-run-code how can we perform a similar job in Zig, by\nbuilding and running our Zig source code through the `run` command from the `zig` compiler.\n\nBut how can we, at the same time, build and run the binary file specified by a target object in our\nbuild script?\nThe answer is by including a \"run artifact\" in our build script.\nA run artifact is created through the `addRunArtifact()` method from the `Build` struct.\nWe simply provide as input to this function the target object that describes the binary file that we\nwant to execute. As a result, this function creates a run artifact that is capable of executing\nthis binary file.\n\nIn the example below, we are defining an executable binary file named `hello`,\nand we use this `addRunArtifact()` method to create a run artifact that will execute\nthis `hello` executable file.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"src/hello.zig\"),\n .target = b.host\n});\nb.installArtifact(exe);\nconst run_arti = b.addRunArtifact(exe);\n```\n:::\n\n\n\n\nNow that we have created this run artifact, we need to include it in\nthe build process. We do that by declaring a new step in our build\nscript to call this artifact, through the `step()` method of the `Build`\nstruct.\n\nWe can give any name we want to this step, but, for our\ncontext here, I'm going to name this step as \"run\".\nAlso, I give it a brief description to this step (\"Run the project\").\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst run_step = b.step(\n \"run\", \"Run the project\"\n);\n```\n:::\n\n\n\n\n\nNow that we have declared this \"run step\" we need to tell Zig that\nthis \"run step\" depends on the run artifact.\nIn other words, a run artifact always depends on a \"step\" to effectively be executed.\nBy creating this dependency\nwe finally stablish the necessary commands to build and run the executable file\nfrom the build script.\n\nWe can establish a dependency between the run step and the run artifact\nby using the `dependsOn()` method from the run step. So, we first\ncreate the run step, and then, we link it with the run artifact, by\nusing this `dependsOn()` method from the run step.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nrun_step.dependOn(&run_arti.step);\n```\n:::\n\n\n\n\nThe entire source code of this specific build script that\nwe wrote, piece by piece, in this section, is\navailable in the `build_and_run.zig` module. You can\nsee this module by\n[visiting the official repository of this book](https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_and_run.zig)\n[^module-src].\n\n\n[^module-src]: \n\nWhen you declare a new step in your build script, this step\nbecomes available through the `build` command in the `zig` compiler.\nYou can actually see this step by running `zig build --help` in the terminal, like\nin the example below, where we can see that this new \"run\"\nstep that we declared in the build script appeared in the output.\n\n```bash\nzig build --help\n```\n\n```\nSteps:\n ...\n run Run the project\n ...\n```\n\nNow, everything that we need to is to\ncall this \"run\" step that we created in our build script. We\ncall it by using the name that we gave to this step\nafter the `build` command from the `zig` compiler.\nThis will cause the compiler to build our executable file\nand execute it at the same time.\n\n```bash\nzig build run\n```\n\n## Build unit tests in your project\n\nWe have talked at length about writing unit tests in Zig in @sec-unittests,\nand we also have talked about how to execute these unit tests through\nthe `test` command of the `zig` compiler. However,\nas we did with the `run` command on the previous section, we also might want to\ninclude some commands in our build script to also build and execute the unit tests in our project.\n\nSo, once again, we are going to discuss how a specific built-in command from the `zig` compiler,\n(in this case, the `test` command) can be used in a build script in Zig.\nHere is where a \"test target object\" comes into play.\nAs was described in @sec-targets, we can create a test target object by using the `addTest()` method of\nthe `Build` struct. The first thing that we need to do is to\ndeclare a test target object in our build script.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst test_exe = b.addTest(.{\n .name = \"unit_tests\",\n .root_source_file = b.path(\"src/main.zig\"),\n .target = b.host,\n});\nb.installArtifact(test_exe);\n```\n:::\n\n\n\n\n\nA test target object essentially selects all `test` blocks in all Zig modules\nacross your project, and builds only the source code present inside\nthese `test` blocks in your project. As a result, this target object\ncreates an executable file that contains only the source code present\nin all of these `test` blocks (i.e., the unit tests) in your project.\n\nPerfect! Now that we have declared this test target object, an executable file\nnamed `unit_tests` is built by the `zig` compiler when we trigger the build\nscript with the `build` command. After the build\nprocess is finished, we can simply execute this `unit_tests` executable\nin the terminal.\n\nHowever, if you remember the previous section, we already learned\nhow can we create a run step in our build script, to execute an executable file\nbuilt by the build script.\n\nSo, we could simply add a run step in our build script to run these unit tests\nfrom a single command in the `zig` compiler, to make our lifes easier.\nIn the example below, we demonstrate the commands to\nregister a new build step called \"tests\" in our build script\nto run these unit tests.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst run_arti = b.addRunArtifact(test_exe);\nconst run_step = b.step(\"tests\", \"Run unit tests\");\nrun_step.dependOn(&run_arti.step);\n```\n:::\n\n\n\n\nNow that we registered this new build step, we can trigger it by calling the command below\nin the terminal. You can also checkout the complete source\ncode for this specific build script at the `build_tests.zig` module at the\n[official repository of this book](https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_tests.zig)\n[^module-src2].\n\n\n[^module-src2]: \n\n\n```bash\nzig build tests\n```\n\n\n## Tailoring your build process with user-provided options\n\nSometimes, you want to make a build script that is customizable by the user\nof your project. You can do that by creating user-provided options in\nyour build script. We create an user-provided option by using the\n`option()` method from the `Build` struct.\n\nWith this method, we create a \"build option\" which can be passed\nto the `build.zig` script at the command line. The user have the power of setting\nthis option at the `build` command from the\n`zig` compiler. In other words, each build option that we create\nbecomes a new command line argument that is accessible through the `build` command\nof the compiler.\n\nThese \"user-provided options\" are set by using the prefix `-D` in the command line.\nFor example, if we declare an option named `use_zlib`, that receives a boolean value which\nindicates if we should link our source code to `zlib` or not, we can set the value\nof this option in the command line with `-Duse_zlib`. The code example below\ndemonstrates this idea:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const use_zlib = b.option(\n bool,\n \"use_zlib\",\n \"Should link to zlib?\"\n ) orelse false;\n const exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"example.zig\"),\n .target = b.host,\n });\n if (use_zlib) {\n exe.linkSystemLibrary(\"zlib\");\n }\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n\n```bash\nzig build -Duse_zlib=false\n```\n\n\n## Linking to external libraries\n\n\nOne essential part of every build process is the linking stage.\nThis stage is responsible for combining the multiple object files\nthat represent your code, into a single executable file. It also links\nthis executable file to external libraries, if you use any in your code.\n\nIn Zig, we have two notions of a \"library\", which are: 1) a system's library;\n2) a local library. A system's library is just a library that is already installed\nin your system. While a local library is a library that belongs to the current\nproject; a library that is present in your project directory, and\nthat you are building together with your project source code.\n\nThe basic difference between the two, is that a system's library is already\nbuilt and installed in your system, supposedly, and all you need to do\nis to link your source code to this library to start using it.\nWe do that by using the `linkSystemLibrary()` method from a\n`Compile` object. This method accepts the name of the library\nin a string as input. Remember from @sec-targets that a `Compile` object\nis a target object that you declare in your build script.\n\nWhen you link a particular target object with a system's library,\nthe `zig` compiler will use `pkg-config` to find where\nare the binary files and also the header files of this library\nin your system.\nWhen it finds these files, the linker present in the `zig` compiler\nwill link your object files with the files of this library to\nproduce a single binary file for you.\n\nIn the example below, we are creating an executable file named `image_filter`,\nand, we are linking this executable file to the C Standard Library with the\nmethod `linkLibC()`, but we also are linking this executable file to the\nC library `libpng` that is currently installed in my system.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const exe = b.addExecutable(.{\n .name = \"image_filter\",\n .root_source_file = b.path(\"src/main.zig\"),\n .target = target,\n .optimize = optimize,\n });\n exe.linkLibC();\n exe.linkSystemLibrary(\"png\");\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n\nIf you are linking with a C library in your project, is generally a good idea\nto also link your code with the C Standard Library. Because is very likely\nthat this C library uses some functionality of the C Standard Library at some point.\nThe same goes to C++ libraries. So, if you are linking with\nC++ libraries, is a good idea to link your project with the C++\nStandard Library by using the `linkLibCpp()` method.\n\nOn the order side, when you want to link with a local library,\nyou should use the `linkLibrary()` method of a `Compile` object.\nThis method expects to receive another `Compile` object as input.\nThat is, another target object defined in your build script,\nusing either the `addStaticLibrary()` or `addSharedLibrary()` methods\nwhich defines a library to be built.\n\nAs we discussed earlier, a local library is a library\nthat is local to your project, and that is being built together\nwith your project. So, you need to create a target object in your build script\nto build this local library. Then, you link the target objects of interest in your project,\nwith this target object that identifies this local library.\n\nTake a look at this example extracted from the build script of the [`libxev` library](https://github.com/mitchellh/libxev/tree/main)[^libxev2].\nYou can see in this snippet that\nwe are declaring a shared library file, from the `c_api.zig`\nmodule. Then, later in the build script, we declare an\nexecutable file named `\"dynamic-binding-test\"`, which\nlinks to this shared library that we defined earlier\nin the script.\n\n[^libxev2]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst optimize = b.standardOptimizeOption(.{});\nconst target = b.standardTargetOptions(.{});\n\nconst dynamic_lib = b.addSharedLibrary(.{\n .name = dynamic_lib_name,\n .root_source_file = b.path(\"src/c_api.zig\"),\n .target = target,\n .optimize = optimize,\n});\nb.installArtifact(dynamic_lib);\n// ... more lines in the script\nconst dynamic_binding_test = b.addExecutable(.{\n .name = \"dynamic-binding-test\",\n .target = target,\n .optimize = optimize,\n});\ndynamic_binding_test.linkLibrary(dynamic_lib);\n```\n:::\n\n\n\n\n\n\n## Building C code {#sec-building-c-code}\n\nThe `zig` compiler comes with a C compiler embedded in it. In other words,\nyou can use the `zig` compiler to build C projects. This C compiler is available\nthrough the `cc` command of the `zig` compiler.\n\nAs an example, let's use the famous [FreeType library](https://freetype.org/)[^freetype].\nFreeType is one of the most widely used pieces of software in the world.\nIt's a C library designed to produce high-quality fonts. But it's also\nheavily used in the industry to natively render text and fonts\nin the screen of your computer.\n\nIn this section, we are going to write a build script, piece by piece, that is capable\nof building the FreeType project from source.\nYou can find the source code of this build script on the\n[`freetype-zig` repository](https://github.com/pedropark99/freetype-zig/tree/main)[^freetype-zig]\navailable at GitHub.\n\n[^freetype]: \n[^freetype-zig]: \n\nAfter you download the source code of FreeType from the official website[^freetype],\nyou can start writing the `build.zig` module. We begin by defining the target object\nthat defines the binary file that we want to compile.\n\nAs an example, I will build the project as a static library file using the `addStaticLibrary()` method\nto create the target object.\nAlso, since FreeType is a C library, I will also link the library\nagainst `libc` through the `linkLibC()` method, to guarantee that any use\nof the C Standard Library is covered in the compilation process.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst target = b.standardTargetOptions(.{});\nconst opti = b.standardOptimizeOption(.{});\nconst lib = b.addStaticLibrary(.{\n .name = \"freetype\",\n .optimize = opti,\n .target = target,\n});\nlib.linkLibC();\n```\n:::\n\n\n\n\n### Creating C compiler flags\n\nCompiler flags are also known as \"compiler options\" by many programmers,\nor also, as \"command options\" in the GCC official documentation.\nIt's fair to also call them as the \"command-line arguments\" of the C compiler.\nIn general, we use compiler flags to turn on (or turn off) some features from the compiler,\nor to tweak the compilation process to fit the needs of our project.\n\nIn build scripts written in Zig, we normally list the C compiler flags to be used in the compilation process\nin a simple array, like in the example below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c_flags = [_][]const u8{\n \"-Wall\",\n \"-Wextra\",\n \"-Werror\",\n};\n```\n:::\n\n\n\n\nIn theory, there is nothing stopping you from using this array to add \"include paths\" (with the `-I` flag)\nor \"library paths\" (with the `-L` flag) to the compilation process. But there are formal ways in Zig to\nadd these types of paths in the compilation process. Both are discussed in @sec-include-paths\nand @sec-library-paths.\n\nAnyway, in Zig, we add C flags to the build process together with the C files that we want to compile, by using the\n`addCSourceFile()` and `addCSourceFiles()` methods. In the example above, we have just declared\nthe C flags that we want to use. But we haven't added them to the build process yet.\nTo do that, we also need to list the C files to be compiled.\n\n### Listing your C files\n\nThe C files that contains \"cross-platform\" source code are listed in the `c_source_files`\nobject below. These are the C files that are included by default in every platform\nsupported by the FreeType library. Now, since the amount of C files in the FreeType library is big,\nI have omitted the rest of the files in the code example below, for brevity purposes.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c_source_files = [_][]const u8{\n \"src/autofit/autofit.c\",\n \"src/base/ftbase.c\",\n // ... and many other C files.\n};\n```\n:::\n\n\n\n\nNow, in addition to \"cross-platform\" source code, we also have some C files in the FreeType project\nthat are platform-specific, meaning that, they contain source code that can only be compiled in specific platforms,\nand, as a result, they are only included in the build process on these specific target platforms.\nThe objects that list these C files are exposed in the code example below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst windows_c_source_files = [_][]const u8{\n \"builds/windows/ftdebug.c\",\n \"builds/windows/ftsystem.c\"\n};\nconst linux_c_source_files = [_][]const u8{\n \"src/base/ftsystem.c\",\n \"src/base/ftdebug.c\"\n};\n```\n:::\n\n\n\n\nNow that we declared both the files that we want to include and the C compiler flags to be used,\nwe can add them to the target object that describes the FreeType library, by using the\n`addCSourceFile()` and `addCSourceFiles()` methods.\n\nBoth of these functions are methods from a `Compile` object (i.e., a target object).\nThe `addCSourceFile()` method is capable of adding a single C file to the target object,\nwhile the `addCSourceFiles()` method is used to add multiple C files in a single command.\nYou might prefer to use `addCSourceFile()` when you need to use different compiler flags\non specific C files in your project. But, if you can use the same compiler flags\nacross all C files, then, you will probably find `addCSourceFiles()` a better choice.\n\nNotice that we are using the `addCSourceFiles()` method in the example below,\nto add both the C files and the C compiler flags. Also notice that we\nare using the `os.tag` that we learned about in @sec-detect-os, to add the platform-specific\nC files.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nlib.addCSourceFiles(\n &c_source_files, &c_flags\n);\n\nswitch (builtin.target.os.tag) {\n .windows => {\n lib.addCSourceFiles(\n &windows_c_source_files,\n &c_flags\n );\n },\n .linux => {\n lib.addCSourceFiles(\n &linux_c_source_files,\n &c_flags\n );\n },\n else => {},\n}\n```\n:::\n\n\n\n\n\n### Defining C Macros\n\nC Macros are an essential part of the C programming language,\nand they are commonly defined through the `-D` flag from a C compiler.\nIn Zig, you can define a C Macro to be used in your build process\nby using the `defineCMacro()` method from the target object that\ndefines the binary file that you are building.\n\nIn the example below, we are using the `lib` object that we have defined\nin the previous sections to define some C Macros used by the FreeType project\nin the compilation process. These C Macros specify if FreeType\nshould (or should not) include functionalities from different\nexternal libraries.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nlib.defineCMacro(\"FT_DISABLE_ZLIB\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_PNG\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_HARFBUZZ\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_BZIP2\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_BROTLI\", \"TRUE\");\nlib.defineCMacro(\"FT2_BUILD_LIBRARY\", \"TRUE\");\n```\n:::\n\n\n\n\n\n### Adding library paths {#sec-library-paths}\n\nLibrary paths are paths in your computer where the C compiler will look (or search) for\nlibrary files to link against your source code. In other words, when you use a library in your\nC source code, and you ask the C compiler to link your source code against this library,\nthe C compiler will search for the binary files of this library across the paths listed\nin this \"library paths\" set.\n\nThese paths are platform specific, and, by default, the C compiler starts by looking at a\npre-defined set of places in your computer. But you can add more paths (or more places)\nto this list. For example, you may have a library installed in a non-conventional place of your\ncomputer, and you can make the C compiler \"see\" this \"non-conventional place\" by adding this path\nto this list of pre-defined paths.\n\nIn Zig, you can add more paths to this set by using the `addLibraryPath()` method from your target object.\nFirst, you defined a `LazyPath` object, containing the path you want to add, then,\nyou provide this object as input to the `addLibraryPath()` method, like in the example below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst lib_path: std.Build.LazyPath = .{\n .cwd_relative = \"/usr/local/lib/\"\n};\nlib.addLibraryPath(lib_path);\n```\n:::\n\n\n\n\n\n\n\n### Adding include paths {#sec-include-paths}\n\nThe preprocessor search path is a popular concept from the\nC community, but it's also known by many C programmers as \"include paths\", because\nthe paths in this \"search path\" relate to the `#include` statements found in the C files.\n\nInclude paths are similar to library paths. They are a set of pre-defined places in your computer where\nthe C compiler will look for files during the compilation process. But instead of looking for\nlibrary files, the include paths are places where the compiler looks for header files included\nin your C source code.\nThis is why many C programmers prefer to call these paths as the \"preprocessor search path\".\nBecause header files are processed during the preprocessor stage of the compilation\nprocess.\n\nSo, every header file that you include in your C source code, through a `#include` statements needs to\nbe found somewhere, and the C compiler will search for this header file across the paths listed in this \"include paths\" set.\nInclude paths are added to the compilation process through the `-I` flag.\n\nIn Zig, you can add new paths to this pre-defined set of paths, by using the `addIncludePath()` method\nfrom your target object. This method also accepts a `LazyPath` object as input.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst inc_path: std.Build.LazyPath = .{\n .path = \"./include\"\n};\nlib.addIncludePath(inc_path);\n```\n:::\n", - "supporting": [ - "07-build-system_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n# Build System {#sec-build-system}\n\n\nIn this chapter, we are going to talk about the build system, and how an entire project\nis built in Zig.\nOne key advantage of Zig is that it includes a build system embedded in the language itself.\nThis is great, because then you do not have to depend on an external system, separated\nfrom the compiler, to build your code.\n\n\nYou can find a good description of Zig's build system\nin the [article entitled \"Build System\"](https://ziglang.org/learn/build-system/#user-provided-options)[^zig-art1]\nfrom the official Zig's website.\nWe also have the excellent [series of posts written by Felix](https://zig.news/xq/zig-build-explained-part-1-59lf)[^felix].\nHence, this chapter represents an extra resource for you to consult and rely on.\n\n[^felix]: \n[^zig-art1]: \n\nBuilding code is one of the things that Zig is best at. One thing that is particularly\ndifficult in C/C++ and even in Rust, is to cross-compile source code to multiple targets\n(e.g. multiple computer architectures and operating systems),\nand the `zig` compiler is known for being one of the best existing pieces of software\nfor this particular task.\n\n\n\n\n## How source code is built?\n\nWe already have talked about the challenges of building source code in low-level languages\nin @sec-project-files. As we described at that section, programmers invented Build Systems\nto surpass these challenges on the process of building source code in low-level languages.\n\nLow-level languages uses a compiler to compile (or to build) your source code into binary instructions.\nIn C and C++, we normally use compilers like `gcc`, `g++` or `clang` to compile\nour C and C++ source code into these instructions.\nEvery language have its own compiler, and this is no different in Zig.\n\nIn Zig, we have the `zig` compiler to compile our Zig source code into\nbinary instructions that can be executed by our computer.\nIn Zig, the compilation (or the build) process involves\nthe following components:\n\n- The Zig modules that contains your source code;\n- Library files (either a dynamic library or a static library);\n- Compiler flags that tailors the build process to your needs.\n\nThese are the things that you need to connect together in order to build your\nsource code in Zig. In C and C++, you would have an extra component, which are the header files of\nthe libraries that you are using. But header files do not exist in Zig, so, you only need\nto care about them if you are linking your Zig source code with a C library.\nIf that is not your case, you can forget about it.\n\nYour build process is usually organized in a build script. In Zig, we normally\nwrite this build script into a Zig module in the root directory of our project,\nnamed as `build.zig`. You write this build script, then, when you run it, your project\ngets built into binary files that you can use and distribute to your users.\n\nThis build script is normally organized around *target objects*. A target is simply\nsomething to be built, or, in other words, it's something that you want the `zig` compiler\nto build for you. This concept of \"targets\" is present in most Build Systems,\nespecially in CMake[^cmake].\n\n[^cmake]: \n\nThere are four types of target objects that you can build in Zig, which are:\n\n- An executable (e.g. a `.exe` file on Windows).\n- A shared library (e.g. a `.so` file in Linux or a `.dll` file on Windows).\n- A static library (e.g. a `.a` file in Linux or a `.lib` file on Windows).\n- An executable file that executes only unit tests (or, a \"unit tests executable\").\n\nWe are going to talk more about these target objects in @sec-targets.\n\n\n\n## The `build()` function {#sec-build-fun}\n\nA build script in Zig always contains a public (and top-level) `build()` function declared.\nIt's like the `main()` function in the main Zig module of your project, that we discussed in @sec-main-file.\nBut instead of creating the entrypoint to your code, this `build()` function is the entrypoint to the build process.\n\nThis `build()` function should accept a pointer to a `Build` object as input, and it should use this \"build object\" to perform\nthe necessary steps to build your project. The return type of this function is always `void`,\nand this `Build` struct comes directly from the Zig Standard Library (`std.Build`). So, you can\naccess this struct by just importing the Zig Standard Library into your `build.zig` module.\n\nJust as a very simple example, here you can see the source code necessary to build\nan executable file from the `hello.zig` Zig module.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n });\n b.installArtifact(exe);\n}\n```\n:::\n\n\nYou can define and use other functions and objects in this build script. You can also import\nother Zig modules as you would normally do in any other module of your project.\nThe only real requirement for this build script, is to have a public and top-level\n`build()` function defined, that accepts a pointer to a `Build` struct as input.\n\n\n## Target objects {#sec-targets}\n\nAs we described over the previous sections, a build script is composed around target objects.\nEach target object is normally a binary file (or an output) that you want to get from the build process. You can list\nmultiple target objects in your build script, so that the build process generates multiple\nbinary files for you at once.\n\nFor example, maybe you are a developer working in a cross-platform application,\nand, because this application is cross-platform, you probably need to release\nbinary files of your software for each OS supported by your application to your end users.\nThus, you can define a different target object in your build script\nfor each OS (Windows, Linux, etc.) where you want to publish your software.\nThis will make the `zig` compiler to build your project to multiple target OS's at once.\nThe Zig Build System official documentation have a [great code example that demonstrates this strategy](https://ziglang.org/learn/build-system/#handy-examples)[^zig-ex].\n\n[^zig-ex]: \n\n\nA target object is created by the following methods of the `Build` struct that we introduced\nin @sec-build-fun:\n\n- `addExecutable()` creates an executable file;\n- `addSharedLibrary()` creates a shared library file;\n- `addStaticLibrary()` creates a static library file;\n- `addTest()` creates an executable file that executes unit tests.\n\n\nThese functions are methods from the `Build` struct that you receive\nas input of the `build()` function. All of them, create as output\na `Compile` object, which represents a target object to be compiled\nby the `zig` compiler. All of these functions accept a similar struct literal as input.\nThis struct literal defines three essential specs about this target object that you are building:\n`name`, `target` and `root_source_file`.\n\nWe have already seen these three options being used on the previous example,\nwhere we used the `addExecutable()` method to create an executable target object.\nThis example is reproduced below. Notice the use of the `path()` method\nfrom the `Build` struct, to define a path in the `root_source_file` option.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n});\n```\n:::\n\n\nThe `name` option specify the name that you want to give to the binary file defined\nby this target object. So, in this example, we are building an executable file named `hello`.\nIt's common to set this `name` option to the name of your project.\n\n\nFurthermore, the `target` option specify the target computer architecture (or the target operating system) of this\nbinary file. For example, if you want this target object to run on a Windows machine\nthat uses a `x86_64` architecture, you can set this `target` option to `x86_64-windows-gnu` for example.\nThis will make the `zig` compiler to compile the project to run on a `x86_64` Windows machine.\nYou can see the full list of architectures and OS's that the `zig` compiler supports by running\nthe `zig targets` command in the terminal.\n\nNow, if you are building the project to run on the current machine\nthat you are using to run this build script, you can set this `target`\noption to the `host` method of the `Build` object, like we did in the example above.\nThis `host` method identifies the current machine where you are\ncurrently running the `zig` compiler.\n\n\nAt last, the `root_source_file` option specifies the root Zig module of your project.\nThat is the Zig module that contains the entrypoint to your application (i.e., the `main()` function), or, the main API of your library.\nThis also means that, all the Zig modules that compose your project are automatically discovered\nfrom the import statements you have inside this \"root source file\".\nThe `zig` compiler can detect when a Zig module depends on the other through the import statements,\nand, as a result, it can discover the entire map of Zig modules used in your project.\n\nThis is handy, and it's different from what happens in other build systems.\nIn CMake for example, you have to explicitly list the paths to all source files that you want to\ninclude in your build process. This is probably a symptom of the \"lack of conditional\ncompilation\" in the C and C++ compilers. Since they lack this feature, you have\nto explicitly choose which source files should be sent to the C/C++ compiler, because not\nevery C/C++ code is portable or supported in every operating system, and, therefore,\nwould cause a compilation error in the C/C++ compiler.\n\n\nNow, one important detail about the build process is that, you have to **explicitly\ninstall the target objects that you create in your build script**, by using the\n`installArtifact()` method of the `Build` struct.\n\nEverytime you invoke the build process of your project, by calling the `build` command\nof the `zig` compiler, a new directory named `zig-out` is created in the root\ndirectory of your project. This new directory contains the outputs of the build process,\nthat is, the binary files built from your source code.\n\nWhat the `installArtifact()` method do is to install (or copy) the built target objects\nthat you defined to this `zig-out` directory.\nThis means that, if you do not\ninstall the target objects you define in your build script, these target objects are\nessentially discarded at the end of the build process.\n\nFor example, you might be building a project that uses a third party library that is built\ntogether with the project. So, when you build your project, you would need first, to\nbuild the third party library, and then, you link it with the source code of your project.\nSo, in this case, we have two binary files that are generated in the build process (the executable file of your project, and the third party library).\nBut only one is of interest, which is the executable file of our project.\nWe can discard the binary file of the third party library, by simply not installing it\ninto this `zig-out` directory.\n\nThis `installArtifact()` method is pretty straightforward. Just remember to apply it to every\ntarget object that you want to save into the `zig-out` directory, like in the example below:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n});\n\nb.installArtifact(exe);\n```\n:::\n\n\n\n## Setting the build mode\n\nWe have talked about the three essential options that are set when you create a new target object.\nBut there is also a fourth option that you can use to set the build mode of this target object,\nwhich is the `optimize` option.\nThis option is called this way, because the build modes in Zig are treated more of\nan \"optimization vs safety\" problem. So optimization plays an important role here.\nDon't worry, I'm going back to this question very soon.\n\nIn Zig, we have four build modes (which are listed below). Each one of these build modes offer\ndifferent advantages and characteristics. As we described in @sec-compile-debug-mode, the `zig` compiler\nuses the `Debug` build mode by default, when you don't explicitly choose a build mode.\n\n- `Debug`, mode that produces and includes debugging information in the output of the build process (i.e., the binary file defined by the target object);\n- `ReleaseSmall`, mode that tries to produce a binary file that is small in size;\n- `ReleaseFast`, mode that tries to optimize your code, in order to produce a binary file that is as fast as possible;\n- `ReleaseSafe`, mode that tries to make your code as safe as possible, by including safeguards when possible.\n\nSo, when you build your project, you can set the build mode of your target object to `ReleaseFast` for example, which will tell\nthe `zig` compiler to apply important optimizations in your code. This creates a binary file\nthat simply runs faster on most contexts, because it contains a more optimized version of your code.\nHowever, as a result, we often lose some safety features in our code.\nBecause some safety checks are removed from the final binary file,\nwhich makes your code run faster, but in a less safe manner.\n\nThis choice depends on your current priorities. If you are building a cryptography or banking system, you might\nprefer to prioritize safety in your code, so, you would choose the `ReleaseSafe` build mode, which is a little\nslower to run, but much more secure, because it includes all possible runtime safety checks in the binary file\nbuilt in the build process. In the other hand, if you are writing a game for example, you might prefer to prioritize performance\nover safety, by using the `ReleaseFast` build mode, so that your users can experience faster frame rates in your game.\n\nIn the example below, we are creating the same target object that we have used on previous examples.\nBut this time, we are specifying the build mode of this target object to the `ReleaseSafe` mode.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n .optimize = .ReleaseSafe\n});\nb.installArtifact(exe);\n```\n:::\n\n\n\n## Setting the version of your build\n\nEverytime you build a target object in your build script, you can assign a version\nnumber to this specific build, following a semantic versioning framework.\nYou can find more about semantic versioning by visiting the [Semantic Versioning website](https://semver.org/)[^semver].\nAnyway, in Zig, you can specify the version of your build, by providing a `SemanticVersion` struct to\nthe `version` option, like in the example below:\n\n\n[^semver]: \n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"hello.zig\"),\n .target = b.host,\n .version = .{\n .major = 2, .minor = 9, .patch = 7\n }\n});\nb.installArtifact(exe);\n```\n:::\n\n\n\n## Detecting the OS in your build script {#sec-detect-os}\n\nIt's very common in Build Systems to use different options, or, to include different modules, or,\nto link against different libraries depending on the Operational System (OS)\nthat you are targeting in the build process.\n\nIn Zig, you can detect the target OS of the build process, by looking\nat the `os.tag` inside the `builtin` module from the Zig library.\nIn the example below, we are using an if statement to run some\narbitrary code when the target of the build process is a\nWindows system.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nif (builtin.target.os.tag == .windows) {\n // Code that runs only when the target of\n // the compilation process is Windows.\n}\n```\n:::\n\n\n\n## Adding a run step to your build process\n\nOne thing that is neat in Rust is that you can compile and run your\nsource code with one single command (`cargo run`) from the Rust compiler.\nWe saw in @sec-compile-run-code how can we perform a similar job in Zig, by\nbuilding and running our Zig source code through the `run` command from the `zig` compiler.\n\nBut how can we, at the same time, build and run the binary file specified by a target object in our\nbuild script?\nThe answer is by including a \"run artifact\" in our build script.\nA run artifact is created through the `addRunArtifact()` method from the `Build` struct.\nWe simply provide as input to this function the target object that describes the binary file that we\nwant to execute. As a result, this function creates a run artifact that is capable of executing\nthis binary file.\n\nIn the example below, we are defining an executable binary file named `hello`,\nand we use this `addRunArtifact()` method to create a run artifact that will execute\nthis `hello` executable file.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"src/hello.zig\"),\n .target = b.host\n});\nb.installArtifact(exe);\nconst run_arti = b.addRunArtifact(exe);\n```\n:::\n\n\nNow that we have created this run artifact, we need to include it in\nthe build process. We do that by declaring a new step in our build\nscript to call this artifact, through the `step()` method of the `Build`\nstruct.\n\nWe can give any name we want to this step, but, for our\ncontext here, I'm going to name this step as \"run\".\nAlso, I give it a brief description to this step (\"Run the project\").\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst run_step = b.step(\n \"run\", \"Run the project\"\n);\n```\n:::\n\n\n\nNow that we have declared this \"run step\" we need to tell Zig that\nthis \"run step\" depends on the run artifact.\nIn other words, a run artifact always depends on a \"step\" to effectively be executed.\nBy creating this dependency\nwe finally stablish the necessary commands to build and run the executable file\nfrom the build script.\n\nWe can establish a dependency between the run step and the run artifact\nby using the `dependsOn()` method from the run step. So, we first\ncreate the run step, and then, we link it with the run artifact, by\nusing this `dependsOn()` method from the run step.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nrun_step.dependOn(&run_arti.step);\n```\n:::\n\n\nThe entire source code of this specific build script that\nwe wrote, piece by piece, in this section, is\navailable in the `build_and_run.zig` module. You can\nsee this module by\n[visiting the official repository of this book](https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_and_run.zig)\n[^module-src].\n\n\n[^module-src]: \n\nWhen you declare a new step in your build script, this step\nbecomes available through the `build` command in the `zig` compiler.\nYou can actually see this step by running `zig build --help` in the terminal, like\nin the example below, where we can see that this new \"run\"\nstep that we declared in the build script appeared in the output.\n\n```bash\nzig build --help\n```\n\n```\nSteps:\n ...\n run Run the project\n ...\n```\n\nNow, everything that we need to is to\ncall this \"run\" step that we created in our build script. We\ncall it by using the name that we gave to this step\nafter the `build` command from the `zig` compiler.\nThis will cause the compiler to build our executable file\nand execute it at the same time.\n\n```bash\nzig build run\n```\n\n## Build unit tests in your project\n\nWe have talked at length about writing unit tests in Zig in @sec-unittests,\nand we also have talked about how to execute these unit tests through\nthe `test` command of the `zig` compiler. However,\nas we did with the `run` command on the previous section, we also might want to\ninclude some commands in our build script to also build and execute the unit tests in our project.\n\nSo, once again, we are going to discuss how a specific built-in command from the `zig` compiler,\n(in this case, the `test` command) can be used in a build script in Zig.\nHere is where a \"test target object\" comes into play.\nAs was described in @sec-targets, we can create a test target object by using the `addTest()` method of\nthe `Build` struct. The first thing that we need to do is to\ndeclare a test target object in our build script.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst test_exe = b.addTest(.{\n .name = \"unit_tests\",\n .root_source_file = b.path(\"src/main.zig\"),\n .target = b.host,\n});\nb.installArtifact(test_exe);\n```\n:::\n\n\n\nA test target object essentially selects all `test` blocks in all Zig modules\nacross your project, and builds only the source code present inside\nthese `test` blocks in your project. As a result, this target object\ncreates an executable file that contains only the source code present\nin all of these `test` blocks (i.e., the unit tests) in your project.\n\nPerfect! Now that we have declared this test target object, an executable file\nnamed `unit_tests` is built by the `zig` compiler when we trigger the build\nscript with the `build` command. After the build\nprocess is finished, we can simply execute this `unit_tests` executable\nin the terminal.\n\nHowever, if you remember the previous section, we already learned\nhow can we create a run step in our build script, to execute an executable file\nbuilt by the build script.\n\nSo, we could simply add a run step in our build script to run these unit tests\nfrom a single command in the `zig` compiler, to make our lifes easier.\nIn the example below, we demonstrate the commands to\nregister a new build step called \"tests\" in our build script\nto run these unit tests.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst run_arti = b.addRunArtifact(test_exe);\nconst run_step = b.step(\"tests\", \"Run unit tests\");\nrun_step.dependOn(&run_arti.step);\n```\n:::\n\n\nNow that we registered this new build step, we can trigger it by calling the command below\nin the terminal. You can also checkout the complete source\ncode for this specific build script at the `build_tests.zig` module at the\n[official repository of this book](https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_tests.zig)\n[^module-src2].\n\n\n[^module-src2]: \n\n\n```bash\nzig build tests\n```\n\n\n## Tailoring your build process with user-provided options\n\nSometimes, you want to make a build script that is customizable by the user\nof your project. You can do that by creating user-provided options in\nyour build script. We create an user-provided option by using the\n`option()` method from the `Build` struct.\n\nWith this method, we create a \"build option\" which can be passed\nto the `build.zig` script at the command line. The user have the power of setting\nthis option at the `build` command from the\n`zig` compiler. In other words, each build option that we create\nbecomes a new command line argument that is accessible through the `build` command\nof the compiler.\n\nThese \"user-provided options\" are set by using the prefix `-D` in the command line.\nFor example, if we declare an option named `use_zlib`, that receives a boolean value which\nindicates if we should link our source code to `zlib` or not, we can set the value\nof this option in the command line with `-Duse_zlib`. The code example below\ndemonstrates this idea:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const use_zlib = b.option(\n bool,\n \"use_zlib\",\n \"Should link to zlib?\"\n ) orelse false;\n const exe = b.addExecutable(.{\n .name = \"hello\",\n .root_source_file = b.path(\"example.zig\"),\n .target = b.host,\n });\n if (use_zlib) {\n exe.linkSystemLibrary(\"zlib\");\n }\n b.installArtifact(exe);\n}\n```\n:::\n\n\n```bash\nzig build -Duse_zlib=false\n```\n\n\n## Linking to external libraries\n\n\nOne essential part of every build process is the linking stage.\nThis stage is responsible for combining the multiple object files\nthat represent your code, into a single executable file. It also links\nthis executable file to external libraries, if you use any in your code.\n\nIn Zig, we have two notions of a \"library\", which are: 1) a system's library;\n2) a local library. A system's library is just a library that is already installed\nin your system. While a local library is a library that belongs to the current\nproject; a library that is present in your project directory, and\nthat you are building together with your project source code.\n\nThe basic difference between the two, is that a system's library is already\nbuilt and installed in your system, supposedly, and all you need to do\nis to link your source code to this library to start using it.\nWe do that by using the `linkSystemLibrary()` method from a\n`Compile` object. This method accepts the name of the library\nin a string as input. Remember from @sec-targets that a `Compile` object\nis a target object that you declare in your build script.\n\nWhen you link a particular target object with a system's library,\nthe `zig` compiler will use `pkg-config` to find where\nare the binary files and also the header files of this library\nin your system.\nWhen it finds these files, the linker present in the `zig` compiler\nwill link your object files with the files of this library to\nproduce a single binary file for you.\n\nIn the example below, we are creating an executable file named `image_filter`,\nand, we are linking this executable file to the C Standard Library with the\nmethod `linkLibC()`, but we also are linking this executable file to the\nC library `libpng` that is currently installed in my system.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const exe = b.addExecutable(.{\n .name = \"image_filter\",\n .root_source_file = b.path(\"src/main.zig\"),\n .target = target,\n .optimize = optimize,\n });\n exe.linkLibC();\n exe.linkSystemLibrary(\"png\");\n b.installArtifact(exe);\n}\n```\n:::\n\n\nIf you are linking with a C library in your project, is generally a good idea\nto also link your code with the C Standard Library. Because is very likely\nthat this C library uses some functionality of the C Standard Library at some point.\nThe same goes to C++ libraries. So, if you are linking with\nC++ libraries, is a good idea to link your project with the C++\nStandard Library by using the `linkLibCpp()` method.\n\nOn the order side, when you want to link with a local library,\nyou should use the `linkLibrary()` method of a `Compile` object.\nThis method expects to receive another `Compile` object as input.\nThat is, another target object defined in your build script,\nusing either the `addStaticLibrary()` or `addSharedLibrary()` methods\nwhich defines a library to be built.\n\nAs we discussed earlier, a local library is a library\nthat is local to your project, and that is being built together\nwith your project. So, you need to create a target object in your build script\nto build this local library. Then, you link the target objects of interest in your project,\nwith this target object that identifies this local library.\n\nTake a look at this example extracted from the build script of the [`libxev` library](https://github.com/mitchellh/libxev/tree/main)[^libxev2].\nYou can see in this snippet that\nwe are declaring a shared library file, from the `c_api.zig`\nmodule. Then, later in the build script, we declare an\nexecutable file named `\"dynamic-binding-test\"`, which\nlinks to this shared library that we defined earlier\nin the script.\n\n[^libxev2]: \n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst optimize = b.standardOptimizeOption(.{});\nconst target = b.standardTargetOptions(.{});\n\nconst dynamic_lib = b.addSharedLibrary(.{\n .name = dynamic_lib_name,\n .root_source_file = b.path(\"src/c_api.zig\"),\n .target = target,\n .optimize = optimize,\n});\nb.installArtifact(dynamic_lib);\n// ... more lines in the script\nconst dynamic_binding_test = b.addExecutable(.{\n .name = \"dynamic-binding-test\",\n .target = target,\n .optimize = optimize,\n});\ndynamic_binding_test.linkLibrary(dynamic_lib);\n```\n:::\n\n\n\n\n## Building C code {#sec-building-c-code}\n\nThe `zig` compiler comes with a C compiler embedded in it. In other words,\nyou can use the `zig` compiler to build C projects. This C compiler is available\nthrough the `cc` command of the `zig` compiler.\n\nAs an example, let's use the famous [FreeType library](https://freetype.org/)[^freetype].\nFreeType is one of the most widely used pieces of software in the world.\nIt's a C library designed to produce high-quality fonts. But it's also\nheavily used in the industry to natively render text and fonts\nin the screen of your computer.\n\nIn this section, we are going to write a build script, piece by piece, that is capable\nof building the FreeType project from source.\nYou can find the source code of this build script on the\n[`freetype-zig` repository](https://github.com/pedropark99/freetype-zig/tree/main)[^freetype-zig]\navailable at GitHub.\n\n[^freetype]: \n[^freetype-zig]: \n\nAfter you download the source code of FreeType from the official website[^freetype],\nyou can start writing the `build.zig` module. We begin by defining the target object\nthat defines the binary file that we want to compile.\n\nAs an example, I will build the project as a static library file using the `addStaticLibrary()` method\nto create the target object.\nAlso, since FreeType is a C library, I will also link the library\nagainst `libc` through the `linkLibC()` method, to guarantee that any use\nof the C Standard Library is covered in the compilation process.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst target = b.standardTargetOptions(.{});\nconst opti = b.standardOptimizeOption(.{});\nconst lib = b.addStaticLibrary(.{\n .name = \"freetype\",\n .optimize = opti,\n .target = target,\n});\nlib.linkLibC();\n```\n:::\n\n\n### Creating C compiler flags\n\nCompiler flags are also known as \"compiler options\" by many programmers,\nor also, as \"command options\" in the GCC official documentation.\nIt's fair to also call them as the \"command-line arguments\" of the C compiler.\nIn general, we use compiler flags to turn on (or turn off) some features from the compiler,\nor to tweak the compilation process to fit the needs of our project.\n\nIn build scripts written in Zig, we normally list the C compiler flags to be used in the compilation process\nin a simple array, like in the example below.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c_flags = [_][]const u8{\n \"-Wall\",\n \"-Wextra\",\n \"-Werror\",\n};\n```\n:::\n\n\nIn theory, there is nothing stopping you from using this array to add \"include paths\" (with the `-I` flag)\nor \"library paths\" (with the `-L` flag) to the compilation process. But there are formal ways in Zig to\nadd these types of paths in the compilation process. Both are discussed in @sec-include-paths\nand @sec-library-paths.\n\nAnyway, in Zig, we add C flags to the build process together with the C files that we want to compile, by using the\n`addCSourceFile()` and `addCSourceFiles()` methods. In the example above, we have just declared\nthe C flags that we want to use. But we haven't added them to the build process yet.\nTo do that, we also need to list the C files to be compiled.\n\n### Listing your C files\n\nThe C files that contains \"cross-platform\" source code are listed in the `c_source_files`\nobject below. These are the C files that are included by default in every platform\nsupported by the FreeType library. Now, since the amount of C files in the FreeType library is big,\nI have omitted the rest of the files in the code example below, for brevity purposes.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c_source_files = [_][]const u8{\n \"src/autofit/autofit.c\",\n \"src/base/ftbase.c\",\n // ... and many other C files.\n};\n```\n:::\n\n\nNow, in addition to \"cross-platform\" source code, we also have some C files in the FreeType project\nthat are platform-specific, meaning that, they contain source code that can only be compiled in specific platforms,\nand, as a result, they are only included in the build process on these specific target platforms.\nThe objects that list these C files are exposed in the code example below.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst windows_c_source_files = [_][]const u8{\n \"builds/windows/ftdebug.c\",\n \"builds/windows/ftsystem.c\"\n};\nconst linux_c_source_files = [_][]const u8{\n \"src/base/ftsystem.c\",\n \"src/base/ftdebug.c\"\n};\n```\n:::\n\n\nNow that we declared both the files that we want to include and the C compiler flags to be used,\nwe can add them to the target object that describes the FreeType library, by using the\n`addCSourceFile()` and `addCSourceFiles()` methods.\n\nBoth of these functions are methods from a `Compile` object (i.e., a target object).\nThe `addCSourceFile()` method is capable of adding a single C file to the target object,\nwhile the `addCSourceFiles()` method is used to add multiple C files in a single command.\nYou might prefer to use `addCSourceFile()` when you need to use different compiler flags\non specific C files in your project. But, if you can use the same compiler flags\nacross all C files, then, you will probably find `addCSourceFiles()` a better choice.\n\nNotice that we are using the `addCSourceFiles()` method in the example below,\nto add both the C files and the C compiler flags. Also notice that we\nare using the `os.tag` that we learned about in @sec-detect-os, to add the platform-specific\nC files.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst builtin = @import(\"builtin\");\nlib.addCSourceFiles(\n &c_source_files, &c_flags\n);\n\nswitch (builtin.target.os.tag) {\n .windows => {\n lib.addCSourceFiles(\n &windows_c_source_files,\n &c_flags\n );\n },\n .linux => {\n lib.addCSourceFiles(\n &linux_c_source_files,\n &c_flags\n );\n },\n else => {},\n}\n```\n:::\n\n\n\n### Defining C Macros\n\nC Macros are an essential part of the C programming language,\nand they are commonly defined through the `-D` flag from a C compiler.\nIn Zig, you can define a C Macro to be used in your build process\nby using the `defineCMacro()` method from the target object that\ndefines the binary file that you are building.\n\nIn the example below, we are using the `lib` object that we have defined\nin the previous sections to define some C Macros used by the FreeType project\nin the compilation process. These C Macros specify if FreeType\nshould (or should not) include functionalities from different\nexternal libraries.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nlib.defineCMacro(\"FT_DISABLE_ZLIB\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_PNG\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_HARFBUZZ\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_BZIP2\", \"TRUE\");\nlib.defineCMacro(\"FT_DISABLE_BROTLI\", \"TRUE\");\nlib.defineCMacro(\"FT2_BUILD_LIBRARY\", \"TRUE\");\n```\n:::\n\n\n\n### Adding library paths {#sec-library-paths}\n\nLibrary paths are paths in your computer where the C compiler will look (or search) for\nlibrary files to link against your source code. In other words, when you use a library in your\nC source code, and you ask the C compiler to link your source code against this library,\nthe C compiler will search for the binary files of this library across the paths listed\nin this \"library paths\" set.\n\nThese paths are platform specific, and, by default, the C compiler starts by looking at a\npre-defined set of places in your computer. But you can add more paths (or more places)\nto this list. For example, you may have a library installed in a non-conventional place of your\ncomputer, and you can make the C compiler \"see\" this \"non-conventional place\" by adding this path\nto this list of pre-defined paths.\n\nIn Zig, you can add more paths to this set by using the `addLibraryPath()` method from your target object.\nFirst, you defined a `LazyPath` object, containing the path you want to add, then,\nyou provide this object as input to the `addLibraryPath()` method, like in the example below:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst lib_path: std.Build.LazyPath = .{\n .cwd_relative = \"/usr/local/lib/\"\n};\nlib.addLibraryPath(lib_path);\n```\n:::\n\n\n\n\n\n### Adding include paths {#sec-include-paths}\n\nThe preprocessor search path is a popular concept from the\nC community, but it's also known by many C programmers as \"include paths\", because\nthe paths in this \"search path\" relate to the `#include` statements found in the C files.\n\nInclude paths are similar to library paths. They are a set of pre-defined places in your computer where\nthe C compiler will look for files during the compilation process. But instead of looking for\nlibrary files, the include paths are places where the compiler looks for header files included\nin your C source code.\nThis is why many C programmers prefer to call these paths as the \"preprocessor search path\".\nBecause header files are processed during the preprocessor stage of the compilation\nprocess.\n\nSo, every header file that you include in your C source code, through a `#include` statements needs to\nbe found somewhere, and the C compiler will search for this header file across the paths listed in this \"include paths\" set.\nInclude paths are added to the compilation process through the `-I` flag.\n\nIn Zig, you can add new paths to this pre-defined set of paths, by using the `addIncludePath()` method\nfrom your target object. This method also accepts a `LazyPath` object as input.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst inc_path: std.Build.LazyPath = .{\n .path = \"./include\"\n};\nlib.addIncludePath(inc_path);\n```\n:::\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/09-data-structures/execute-results/epub.json b/_freeze/Chapters/09-data-structures/execute-results/epub.json deleted file mode 100644 index 9a281348..00000000 --- a/_freeze/Chapters/09-data-structures/execute-results/epub.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "hash": "0d90c199a3a2c5a7a25c66baac2ca8aa", - "result": { - "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Data Structures\n\nIn this chapter, I want to present the most common Data Structures that are available from\nthe Zig Standard Library, especially `ArrayList` and also `HashMap`. These are generic Data Structures\nthat you can use to store and control any type of data that is produced by your application.\n\n## Dynamic Arrays {#sec-dynamic-array}\n\nIn high level languages, arrays are usually dynamic. They can easily grow\nin size when they have to, and you don't need to worry about it.\nIn contrast, arrays in low level languages are usually static by default.\nThis is the reality of C, C++, Rust and also Zig. Static arrays were presented at\n@sec-arrays, but in this section, we are going to talk about dynamic arrays in Zig.\n\nDynamic arrays are simply arrays that can grow in size during the runtime\nof your program. Most low level languages have some implementation of\na dynamic array in their standard library. C++ have `std::vector`, Rust have `Vec`,\nand Zig have `std.ArrayList`.\n\nThe `std.ArrayList` struct provides a contiguous and growable array for you.\nIt works like any other dynamic array, it allocates a contiguous block of memory, and when this block have no space left,\n`ArrayList` allocates another contiguous and bigger block of memory, copies the\nelements to this new location, and erases (or frees) the previous block of memory.\n\n\n### Capacity vs Length\n\nWhen we talk about dynamic arrays, we usually have two similar concepts that\nare very essential to how a dynamic array works behind the hood.\nThese concepts are *capacity* and *length*. In some contexts, especially\nin C++, *length* is also called of *size*.\n\nAlthough they look similar, these concepts represent different things\nin the context of a dynamic array. *Capacity* is the number of items (or elements)\nthat your dynamic array can currently hold without the need to allocate more memory.\n\nIn contrast, the *length* refers to how many elements in the array\nare currently being used, or, in other words, how many elements in this array\nthat you have assigned a value to. Every dynamic array works around\na block of allocated memory, which represents an array with total capacity for $n$ elements.\nHowever, only a portion of these $n$ elements are being used most of the time. This portion\nof $n$ is the *length* of the array. So every time you append a new value\nto the array, you are incrementing its *length* by one.\n\nThis means that a dynamic array usually works with an extra margin, or an extra space\nthat is currently empty, but waiting and ready to be used. This \"extra space\"\nis essentially the difference between *capacity* and *length*. *Capacity* represents\nthe total number of elements that the array can hold without the need to re-allocate\nor re-expand the array, while the *length* represents how much of this capacity\nis currently being used to hold/store values.\n\n@fig-capacity-length presents this idea visually. Notice that, at first,\nthe capacity of the array is greater than the length of the array.\nSo, the dynamic array have extra space that is currently empty, but it\nis ready to receive a value to be stored.\n\n![Difference between capacity and length in a dynamic array](./../Figures/dynamic-array.png){#fig-capacity-length}\n\nWe can also see in @fig-capacity-length that, when *length* and *capacity* are equal, it means that the array have no space left.\nWe have reached the ceiling of our capacity, and because of that, if we want to store more values\nin this array, we need to expand it. We need to get a bigger space that can hold more values\nthan what we currently have.\n\nA dynamic array works by expanding the underlying array, whenever the *length* becomes equal\nto the *capacity* of the array. It basically allocates a new contiguous block of memory that is bigger\nthan the previous one, then, it copies all values that are currently being stored to this new\nlocation (i.e., this new block of memory), then, it frees the previous block of\nmemory. At the end of this process, the new underlying array have a bigger *capacity*, and, therefore,\nthe *length* becomes, once again, smaller than the *capacity* of the array.\n\nThis is the cycle of a dynamic array. Notice that, throughout this cycle, the *capacity* is always\neither equal to or higher than the *length* of the array. If you have an `ArrayList` object (let's suppose\nyou named it `buffer`), you can check the current capacity of your array by accessing the `capacity`\nattribute of your `ArrayList` object, while the current *length* of it is available at the `items.len`\nattribute.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// Check capacity\nbuffer.capacity;\n// Check length\nbuffer.items.len;\n```\n:::\n\n\n\n\n### Creating an `ArrayList` object\n\nIn order to use `ArrayList`, you must provide an allocator object to it.\nRemember, Zig does not have a default memory allocator. And as I described in @sec-allocators, all memory\nallocations must be done by an allocator object that you define, that\nyou have control over. In our example here, I'm going to use\na general purpose allocator, but you can use any other allocator\nof your preference.\n\nWhen you initialize an `ArrayList` object, you must provide the data type of the elements of\nthe array. In other words, this defines the type of data that this array (or container) will\nstore. Therefore, if I provide the `u8` type to it, then, I will create a dynamic\narray of `u8` values. However, if I provide a struct that I have defined instead, like the struct `User`\nfrom @sec-structs-and-oop, then, a dynamic array of `User` values\nwill be created. In the example below, with the expression `ArrayList(u8)` we\nare creating a dynamic array of `u8` values.\n\nAfter you provide the data type of the elements of the array, you can initialize\nan `ArrayList` object by either using the `init()` or the `initCapacity()` methods.\nThe former method receives only the allocator object\nas input, while the latter method receives both the allocator object and a capacity number as inputs.\nWith the latter method, you not only initialize the struct, but you\nalso set the starting capacity of the allocated array.\n\nUsing the `initCapacity()` method is the preferred way to initialize your dynamic array.\nBecause reallocations, or, in other words, the process of expanding the capacity of the array,\nis always a high cost operation. You should take any possible opportunity to avoid reallocations in\nyour array. If you know how much space your array needs to occupy at the beginning,\nyou should always use `initCapacity()` to create your dynamic array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 100);\ndefer buffer.deinit();\n```\n:::\n\n\n\n\nIn the example above, the `buffer` object starts as an array of 100 elements. If this\n`buffer` object needs to create more space to accomodate more elements during the runtime of your program, the `ArrayList`\ninternals will perform the necessary actions for you automatically.\nAlso notice the `deinit()` method being used to destroy the `buffer` object at the\nend of the current scope, by freeing all the memory that was allocated for the dynamic\narray stored in this `buffer` object.\n\n\n### Adding new elements to the array\n\nNow that we have created our dynamic array, we can start to use it. You can append (a.k.a \"add\")\nnew values to this array by using the `append()` method. This method works the same way\nas the `append()` method from a Python list, or, the `emplace_back()` method from `std::vector` of C++.\nYou provide a single value to this method, and the method appends this value to the array.\n\nYou can also use the `appendSlice()` method to append multiple values at once. You provide\na slice (slices were described in @sec-arrays) to this method, and the method adds all values present\nin this slice to your dynamic array.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry buffer.append('H');\ntry buffer.append('e');\ntry buffer.append('l');\ntry buffer.append('l');\ntry buffer.append('o');\ntry buffer.appendSlice(\" World!\");\n```\n:::\n\n\n\n### Removing elements from the array {#sec-dynamic-array-remove}\n\nYou can use the `pop()` method to \"pop\" or remove\nthe last element in the array. It's worth noting that this method\ndo not change the capacity of the array. It just deletes or erases\nthe last value stored in the array.\n\nAlso, this method returns as result the value that got deleted. That is, you can\nuse this method to both get the last value in the array, and also, remove\nit from the array. It's a \"get and remove value\" type of method.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst exclamation_mark = buffer.pop();\n```\n:::\n\n\n\nNow, if you want to remove specific elements from specific positions\nof your array, you can use the `orderedRemove()` method from your\n`ArrayList` object. With this method, you can provide an index as input,\nthen, the method will delete the value that is at this index in the array.\nYou are effectively reducing the *length* of the array everytime you execute\nan `orderedRemove()` operation.\n\nIn the example below, we first create an `ArrayList` object, and we fill it\nwith numbers. Then, we use `orderedRemove()` to remove the value at\nindex 3 in the array, two consecutive times.\n\nAlso, notice that we are assigning the result of `orderedRemove()` to the\nunderscore character. So we are discarding the result value of this method.\nThe `orderedRemove()` method returns the value that got deleted, in a similar\nstyle to the `pop()` method.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 100);\ndefer buffer.deinit();\n\nfor (0..10) |i| {\n const index: u8 = @intCast(i);\n try buffer.append(index);\n}\n\nstd.debug.print(\n \"{any}\\n\", .{buffer.items}\n);\n_ = buffer.orderedRemove(3);\n_ = buffer.orderedRemove(3);\n\nstd.debug.print(\"{any}\\n\", .{buffer.items});\nstd.debug.print(\"{any}\\n\", .{buffer.items.len});\n```\n:::\n\n\n\n```\n{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }\n{ 0, 1, 2, 5, 6, 7, 8, 9 }\n8\n```\n\nOne key characteristic about `orderedRemove()` is that it preserves the order\nof the values in the array. So, it deletes the value that you asked it to\nremove, but it also makes sure that the order of the values that remain in the array\nstay the same as before.\n\nNow, if you don't care about the order of the values, for example, maybe you want to treat\nyour dynamic array as a set of values, like the `std::unordered_set`\nstructure from C++, you can use the `swapRemove()` method instead. This method\nworks similarly to the `orderedRemove()` method. You give an index to this\nmethod, then, it deletes the value that is at this index in the array.\nBut this method does not preserve the original order of the values that remain\nin the array. As a result, `swapRemove()` is, in general, faster than `orderedRemove()`.\n\n\n### Inserting elements at specific indexes\n\nWhen you need to insert values in the middle of your array,\ninstead of just appending them to the end of the array, you need to use\nthe `insert()` and `insertSlice()` methods, instead of\nthe `append()` and `appendSlice()` methods.\n\nThese two methods work very similarly to `insert()` and `insert_range()`\nfrom the C++ `std::vector` class. You provide an index to these methods,\nand they insert the values that you provide at that index in the array.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nvar buffer = try std.ArrayList(u8)\n .initCapacity(allocator, 10);\ndefer buffer.deinit();\n\ntry buffer.appendSlice(\"My Pedro\");\ntry buffer.insert(4, '3');\ntry buffer.insertSlice(2, \" name\");\nfor (buffer.items) |char| {\n try stdout.print(\"{c}\", .{char});\n}\n```\n:::\n\n\n\n```\nMy name P3edro\n```\n\n\n### Conclusion\n\nIf you feel the lack of some other method, I recommend\nyou to read the [official documentation for the `ArrayListAligned`](https://ziglang.org/documentation/master/std/#std.array_list.ArrayListAligned)[^zig-array2]\nstruct, which describes most of the methods available\nthrough the `ArrayList` object.\n\nYou will notice that there is a lot of other methods in this page that\nI did not described here, and I recommend you to explore these methods,\nand understand how they work.\n\n[^zig-array2]: \n\n\n\n## Maps or HashTables {#sec-maps-hashtables}\n\nSome professionals know this type of data structure by different terms, like \"map\",\n\"hashmap\" or \"associative arrays\". But the most common term used is *hashtable*.\nEvery programming language normally have some implementation of a hashtable in their\nstandard libraries. Python have `dict()`, C++ have `std::map` and `std::unordered_map`, Rust\nhave `HashMap`, Javascript have `Object()` and `Map()`, etc.\n\n\n\n### What is a hashtable?\n\nA hashtable is a data structure based on key-value pairs.\nYou provide a key and a value to this structure, then, the hashtable will store\nthe input value at a location that can be identified by the input\nkey that you provided.\nIt does that by using an underlying array and a hash function.\nThese two components are essential to how a hashtable works.\n\nUnder the hood, the hashtable contains an array. This array is where the values\nare stored, and the elements of this array are usually called of *buckets*.\nSo the values that you provide to the hashtable are stored inside buckets,\nand you access each bucket by using an index.\n\nWhen you provide a key to a hashtable, it passes this key to the\nhash function. This hash function uses some sort of hashing algorithm to transform\nthis key into an index. This index is actually an array index. It's a position\nin the underlying array of the hashtable.\nThis is how a key identifies a specific position (or location) inside the hashtable\nstructure.\n\nTherefore, you provide a key to the hashtable, and this key identifies a specific location\ninside the hashtable, then, the hashtable takes the input value that you provided,\nand stores this value in the location identified by this input key.\nYou could say that the key maps to the value stored in the hashtable. You find\nthe value, by using the key that identifies the location where the value is stored.\nThe @fig-hashtable presents this process visually.\n\n\n![A diagram of a Hashtable. Source: Wikipedia, the free encyclopedia.](./../Figures/hashtable.svg){#fig-hashtable}\n\n\nThe operation described in the previous paragraph is normally called an *insertion* operation.\nBecause you are inserting new values into the hashtable.\nBut there are other types of operations in hashtables such as *delete* and *lookup*.\nDelete is self describing, it's when you delete (or remove) a value from the hashtable.\nWhile lookup corresponds to when you look at a value that is stored in\nthe hashtable, by using the key that identifies the location where this value is stored.\n\nSometimes, instead of storing the values directly, the underlying array of the hashtable might be an array of pointers,\ni.e., the buckets of the array stores pointers that points to the value,\nor also, may be an array of linked lists.\nThese cases are common on hashtables that allows duplicate keys, or, in other words,\non hashtables that effectively handle \"collisions\" that may arise from the hash function.\n\nDuplicate keys, or this \"collision\" thing that I'm talking about, is when you have two different keys\nthat points to the same location (i.e., to the same index)\nin the underlying array of the hashtable. This might happen depending on the characteristics of the hash function\nthat is being used in the hashtable. Some implementations of the hashtable will actively deal with collisions,\nmeaning that, they will handle this case in some way. For example, the hashtable\nmight transform all buckets into linked lists. Because with a linked list you can store\nmultiple values into a single bucket.\n\nThere are different techniques to handle collisions in hashtables, which I will not describe\nin this book, because it's not our main scope here. But you can find a good description of\nsome of the most common techniques at the Wikipedia page of hashtables [@wikipedia_hashtables].\n\n\n### Hashtables in Zig {#sec-hashmap}\n\nThe Zig Standard Library provides different implementations of a hashtable.\nEach implementation have its own cons and pros, which we will\ndiscuss later on, and all of them are available through the `std.hash_map` module.\n\nThe `HashMap` struct is a general-purpose hashtable,\nwhich have very fast operations (lookup, insertion, delete), and also,\nquite high load factors for low memory usage. You can create and provide a context object\nto the `HashMap` constructor. This context object allows you to tailor\nthe behaviour of the hashtable itself, because you can\nprovide a hash function implementation to be used by the hashtable\nthrough this context object.\n\nBut let's not worry about this context object now, because it's meant to be used\nby \"experts in the field of hashtables\". Since we are most likely not\nexperts in this field, we are going to take the easy way to create\na hashtable. Which is by using the `AutoHashMap()` function.\n\n\nThis `AutoHashMap()` function is essentially a \"create a hashtable object that uses the default settings\"\ntype of function. It automatically chooses a context object, and, therefore, a hash function implementation,\nfor you. This function receives two data types as input, the first input is the data type of the keys\nthat will be used in this hashtable, while the second input is the data type of the data that will be\nstored inside the hashtable, that is, the data type of the values to be stored.\n\nIn the example below, we are providing the data type `u32` in the first argument, and `u16` in the second argument of this\nfunction. This means that we are going to use `u32` values as keys in this hashtable, while `u16` values are the actual values\nthat are going to be stored into this hashtable.\nAt the end of this process, the `hash_table` object contains a `HashMap` object\nthat uses the default settings and context.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst AutoHashMap = std.hash_map.AutoHashMap;\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var hash_table = AutoHashMap(u32, u16).init(allocator);\n defer hash_table.deinit();\n\n try hash_table.put(54321, 89);\n try hash_table.put(50050, 55);\n try hash_table.put(57709, 41);\n std.debug.print(\n \"N of values stored: {d}\\n\",\n .{hash_table.count()}\n );\n std.debug.print(\n \"Value at key 50050: {d}\\n\",\n .{hash_table.get(50050).?}\n );\n\n if (hash_table.remove(57709)) {\n std.debug.print(\n \"Value at key 57709 successfully removed!\\n\",\n .{}\n );\n }\n std.debug.print(\n \"N of values stored: {d}\\n\",\n .{hash_table.count()}\n );\n}\n```\n:::\n\n\n\n```\nN of values stored: 3\nValue at key 50050: 55\nValue at key 57709 successfully removed!\nN of values stored: 2\n```\n\nYou can add/put new values into the hashtable by using the `put()` method. The first argument\nis the key to be used, and the second argument is the actual value that you want to store inside\nthe hashtable. In the example below, we first add the value 89 using the key 54321, next, we add\nthe value 55 using the key 50050, etc.\n\nNotice that we have used the method `count()` to see how many values are currently stored in the\nhashtable. After that, we also use the `get()` method to access (or look) at the value stored in\nthe position identified by the key 500050. The output of this `get()` method is an optional value.\nThis is why we use the `?` method at the end to get the actual value.\n\nAlso notice that we can remove (or delete) values from the hashtable by using the `remove()` method.\nYou provide the key that identifies the value that you want to delete, then, the method will\ndelete this value and return a `true` value as output. This `true` value essentially tells us\nthat the method successfully deleted the value.\n\nBut this delete operation might not be always successful. For example, you might provide the wrong\nkey to this method. I mean, maybe you provide\n(either intentionally or unintentionally) a key that points to an empty bucket,\ni.e., a bucket that still doesn't have a value in it.\nIn this case, the `remove()` method would return a `false` value.\n\n\n\n### Iterating through the hashtable\n\nIterating through the keys and values that are currently being stored in\nthe hashtable is a very common necessity.\nYou can do that in Zig by using an iterator object that can iterate\nthrough the elements of your hashtable object.\n\nThis iterator object works like any other iterator object that you would\nfind in languages such as C++ and Rust. It's basically a pointer object\nthat points to some value in the container, and has a `next()` method\nthat you can use to navigate (or iterate) through the values in the\ncontainer.\n\nYou can create such iterator object by using the `iterator()` method of the hashtable object.\nThis method returns an iterator object, from which you can use the `next()` method in conjunction\nwith a while loop to iterate through the elements of your hashtable. The `next()` method returns an optional\n`Entry` value, and therefore, you must unwrap this optional value to get the actual `Entry` value\nfrom which you can access the key and also the value identified by this key.\n\nWith this `Entry` value at hand, you can access the key of this current entry by using the `key_ptr`\nattribute and dereferencing the pointer that lives inside of it, while the value identified by this\nkey is accessed through the `value_ptr` attribute instead, which is also a pointer to be dereferenced.\nThe code example below demonstrates the use of these elements:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst AutoHashMap = std.hash_map.AutoHashMap;\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var hash_table = AutoHashMap(u32, u16).init(allocator);\n defer hash_table.deinit();\n\n try hash_table.put(54321, 89);\n try hash_table.put(50050, 55);\n try hash_table.put(57709, 41);\n\n var it = hash_table.iterator();\n while (it.next()) |kv| {\n // Access the current key\n std.debug.print(\"Key: {d} | \", .{kv.key_ptr.*});\n // Access the current value\n std.debug.print(\"Value: {d}\\n\", .{kv.value_ptr.*});\n }\n}\n```\n:::\n\n\n\n```\nKey: 54321 | Value: 89\nKey: 50050 | Value: 55\nKey: 57709 | Value: 41\n```\n\n\nIf you want to iterate specifically through the values or the keys of your hashtable,\nyou can create a key iterator or a value iterator object. These are also iterator\nobjects, which have the same `next()` method that you can use to iterate through the\nhashtable.\n\nKey iterators are created from the `keyIterator()` method of your\nhashtable object, while value iterators are created from the `valueIterator()` method.\nAll you have to do is to unwrap the value from the `next()` method and deference it\ndirectly to access the key or the value that you are iterating over.\nThe code example below demonstrates the use of a key iterator,\nbut you can replicate the same logic to a value iterator.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar kit = hash_table.keyIterator();\nwhile (kit.next()) |key| {\n std.debug.print(\"Key: {d}\\n\", .{key.*});\n}\n```\n:::\n\n\n\n```\nKey: 54321\nKey: 50050\nKey: 57709\n```\n\n\n### The `ArrayHashMap` hashtable {#sec-array-map}\n\nIf you need to iterate through the elements of your hashtable constantly,\nyou might want to use the `ArrayHashMap` struct for your specific case,\ninstead of going with the usual and general-purpose `HashMap` struct.\n\nThe `ArrayHashMap` struct creates a hashtable that is faster to iterate over.\nThat is why this specific type of hashtable might be valuable to you.\nSome other properties of a `ArrayHashMap` hashtable are:\n\n- the order of insertion is preserved, i.e., the order of the values that you find while iterating through this hashtable is actually the order in which these values were inserted in the hashtable.\n- the key-value pairs are stored sequentially, one after another.\n\n\nYou can create an `ArrayHashMap` object by using, once again, a helper function that\nchooses automatically for you a hash function implementation. This is the\n`AutoArrayHashMap()` function, which works very similarly to the `AutoHashMap()`\nfunction that we presented in @sec-hashmap.\n\nYou provide two data types to this function. The data type of the keys that will be\nused in this hashtable, and the data type of the values that will be stored in\nthis hashtable.\n\nAn `ArrayHashMap` object have essentially the exact same methods from the `HashMap` struct.\nSo you can insert new values into the hashtable by using the `put()` method, and you can look (or get)\na value from the hashtable by using the `get()` method. But the `remove()` method is not available\nin this specific type of hashtable.\n\nIn order to delete values from the hashtable, you would use the same methods that you find in\nan `ArrayList` object, i.e., a dynamic array. I presented these methods in @sec-dynamic-array-remove,\nwhich are the `swapRemove()` and `orderedRemove()` methods. These methods have the same meaning here, or,\nthe same effect that they have in an `ArrayList` object.\n\nThis means that, with `swapRemove()` you remove the value from the hashtable, but you do not preserve\nthe order in which the values were inserted into the structure. While `orderedRemove()` is able\nto retain the order in which these values were inserted.\n\nBut instead of providing an index as input to `swapRemove()` or `orderedRemove()`, like I described\nin @sec-dynamic-array-remove, these methods here in an `ArrayHashMap` take a key as input, like\nthe `remove()` method from a `HashMap` object. If you want to provide an index as input, instead\nof a key, you should use the `swapRemoveAt()` and `orderedRemoveAt()` methods.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar hash_table = AutoArrayHashMap(u32, u16)\n .init(allocator);\ndefer hash_table.deinit();\n```\n:::\n\n\n\n\n\n### The `StringHashMap` hashtable {#sec-string-hash-map}\n\nOne thing that you will notice in the other two types of hashtables that I have\npresented over the last sections, is that neither of them accepts a slice data type\nin their keys.\nWhat this means is that you cannot use a slice value to represent a key in\nthese types of hashtable.\n\nThe most obvious consequence of this, is that you cannot use strings as keys\nin these hashtables. But it's extremely common to use strings as keys\nin hashtables.\n\nTake this very simple Javascript code snippet as an example. We are creating\na simple hashtable object named `people`. Then, we add a new entry to this\nhashtable, which is identified by the string `'Pedro'`. This string is the\nkey in this case, while the object containing different personal information such as\nage, height and city, is the value to be stored in the hashtable.\n\n```js\nvar people = new Object();\npeople['Pedro'] = {\n 'age': 25,\n 'height': 1.67,\n 'city': 'Belo Horizonte'\n};\n```\n\nThis pattern of using strings as keys is very common in\nall sorts of situations. That is why the Zig Standard Library offers a\nspecific type of hashtable for this purpose, which is created through the `StringHashMap()` function.\nThis function creates a hashtable that uses strings as keys. The only input of this\nfunction is the data type of the values that will be stored into this hashtable.\n\nIn the example below, I'm creating a hashtable to store the ages of different people.\nEach key in this hashtable is represented by the name of each person, while the value stored in the\nhashtable is the age of this person identified by the key.\n\nThat is why I provide the `u8` data type (which is the data type used by the age values) as input to this `StringHashMap()` function.\nAs the result, it creates a hashtable that uses string values as keys, and, that stores\n`u8` values in it. Notice that an allocator object is provided at the `init()` method of the\nresulting object from the `StringHashMap()` function.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var ages = std.StringHashMap(u8).init(allocator);\n defer ages.deinit();\n\n try ages.put(\"Pedro\", 25);\n try ages.put(\"Matheus\", 21);\n try ages.put(\"Abgail\", 42);\n\n var it = ages.iterator();\n while (it.next()) |kv| {\n std.debug.print(\"Key: {s} | \", .{kv.key_ptr.*});\n std.debug.print(\"Age: {d}\\n\", .{kv.value_ptr.*});\n }\n}\n```\n:::\n\n\n\n```\nKey: Pedro | Age: 25\nKey: Abgail | Age: 42\nKey: Matheus | Age: 21\n```\n\n\n### The `StringArrayHashMap` hashtable\n\nThe Zig Standard Library also provides a type of hashtable that mix the cons and pros of the\n`StringHashMap` and `ArrayHashMap` together. That is, a hashtable\nthat uses strings as keys, but also have the advantages from `ArrayHashMap`.\nIn other words, you can have a hashtable that is fast to iterate over,\nthat preserves insertion order, and also, that uses strings as keys.\n\nYou can create such type of hashtable by using the `StringArrayHashMap()` function.\nThis function accepts a data type as input, which is the data type of the values that are\ngoing to be stored inside this hashtable, in the same style as the function presented\nin @sec-string-hash-map.\n\nYou can insert new values into this hashtable by using the same `put()` method that\nwe have discussed in @sec-string-hash-map. And you can also get values from the hashtable\nby using the same `get()` method.\nLike its `ArrayHashMap` brother, to delete values from this specific type of hashtable,\nwe also use the `orderedRemove()` and `swapRemove()` methods, with the same effects that\nI have described in @sec-array-map.\n\nIf we take the code example that was exposed in @sec-string-hash-map, we can\nachieve the exact same result with `StringArrayHashMap()`:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar ages = std.StringArrayHashMap(u8).init(allocator);\n```\n:::\n\n\n\n\n\n\n## Linked lists\n\nThe Zig Standard Library provides an implementation for both singly and doubly linked lists.\nMore specifically, through the structs `SinglyLinkedList` and `DoublyLinkedList`.\n\nIn case you are not familiar with these data structures, a linked list is a linear data structure that looks\nlike a chain, or, a rope. The main advantage of this data structure is that you normally have very fast\ninsertion and deletion operations. But, as a disadvantage, iterating through\nthis data structure is usually not so fast as iterating through an array.\n\nThe idea behind a linked list is to build a structure that consists of a sequence of nodes\nconnected to each other by pointers. This means that linked lists are usually not contiguous\nin memory, because each node might be anywhere in memory. They do not need to be close to\none another.\n\nIn @fig-linked-list we can see a diagram of a singly linked list. We begin at the first node\n(which is usually called \"the head of the linked list\"). Then, from this\nfirst node we uncover the remaining nodes in the structure, by following the locations pointed\nby the pointers found in each node.\n\nEach node has two things in it. It has the value that is stored in the current node\n, and also, a pointer. This pointer points to the next node in the list. If this pointer\nis null, then, it means that we have reached the end of our linked list.\n\n![A diagram of a singly linked list.](./../Figures/linked-list.png){#fig-linked-list}\n\n\nIn @fig-linked-list2 we can see a diagram of a doubly linked list. The only thing that really\nchanges now is that every node in the linked list has both a pointer to the previous node,\nand, a pointer to the next node. So every node in a doubly linked list has two pointers in it. These are\nusually called the `prev` (for \"previous\") and the `next` (for \"next\") pointers of the node.\n\nIn the singly linked list example, we had only one single pointer in each node, and this singular\npointer was always pointing to the next node in the sequence. This means that singly linked lists\nnormally have only the `next` pointer in them.\n\n![A diagram of a doubly linked list.](./../Figures/doubly-linked-list.png){#fig-linked-list2}\n\n\n\n### Recent change in the API\n\nOn previous versions of Zig, the `SinglyLinkedList` and `DoublyLinkedList` structs were initially implemented as \"generics data structures\".\nMeaning that, you would use a generic function to create a singly (or doubly) linked list that could store\nthe specific data type that you wanted to use. We will learn more about generics at @sec-generics, and also,\nhow we can create a \"generic data structure\" at @sec-generic-struct.\n\nHowever, on the latest versions of Zig, the structs `SinglyLinkedList` and `DoublyLinkedList` were altered to use a\n\"less generic API\". This specific change was introduced on April 3, 2025. Therefore, check if your Zig version is one released after this\ndate. Just have in mind that if you don't have a very recent version of the Zig compiler,\nyou might have problems while trying to compile the next examples exposed here.\n\n\n\n### How to use a singly linked list\n\nFor example, consider that you are creating a singly linked list that is going to store `u32` values.\nGiven this scenario, the first thing that we need to do, is to create a \"node type\" that is capable\nof storing a `u32` value. The `NodeU32` type exposed below demonstrates such \"node type\".\n\nNotice that the data type associated with the member named `data` is the most important part of this\ncustom \"node type\". It determines the data type that is going to be stored in each node.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst NodeU32 = struct {\n data: u32,\n node: std.SinglyLinkedList.Node = .{},\n};\n```\n:::\n\n\n\nAfter we created our custom \"node type\" that can store the specific data type that we\nwant, we can just create a new and empty singly linked list, which will store our nodes.\nTo do that, we just create a new object with the type `SinglyLinkedList`, like this:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar list: std.SinglyLinkedList = .{};\n```\n:::\n\n\n\nNow, we have our linked list... But how can we insert nodes in it? Well, first of all,\nwe need to create our nodes. So let's focus on that first. The snippet exposed below demonstrates\nhow we could use our `NodeU32` struct to create such nodes.\n\nNotice in this snippet that we are just setting the `data` member of the struct for now.\nWe don't need to connect these nodes together in this first instance. This is why we ignore\nthe `node` member at first. But we are going to connect these nodes in a future point of the code, which is\nwhy these objects are marked as \"variable objects\", so that we can alter them in the future.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar one: NodeU32 = .{ .data = 1 };\nvar two: NodeU32 = .{ .data = 2 };\nvar three: NodeU32 = .{ .data = 3 };\nvar five: NodeU32 = .{ .data = 5 };\n```\n:::\n\n\n\nNow that we have both the linked list and also the nodes created, we can start to connect them together.\nYou can use the `prepend()` method from the linked list object to insert the first node in the list, which\nis the \"head\" of the linked list. As the name suggests, this specific method prepends the input node to the linked list,\nor, in other words, it transforms the input node into the first node of the list.\n\nAfter we added the \"head node\" of the list, we can start to add the \"next nodes\" in the list by using the `insertAfter()` method\nfrom the `SinglyLinkedList.Node` type, which, in our case here, is accessible through the `node` member of our\n`NodeU32` type. Thus, we can start to create the connections between the nodes by calling this method from the node objects\nthat are present in the list. Like in this example below:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nlist.prepend(&two.node); // {2}\ntwo.node.insertAfter(&five.node); // {2, 5}\ntwo.node.insertAfter(&three.node); // {2, 3, 5}\n```\n:::\n\n\n\nYou can also call the `prepend()` method again to add new nodes to the beginning of the linked list, which\nmeans, effectively, changing the \"head node\" of the list, like this:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nlist.prepend(&one.node); // {1, 2, 3, 5}\n```\n:::\n\n\n\n\nThere are other methods available from the singly linked list object that you might be interested. You can find a\nsummary of them in the bullet points below:\n\n- `remove()` to remove a specific node from the linked list.\n- `len()` to count how many nodes there is in the linked list.\n- `popFirst()` to remove the first node (i.e., the \"head\") from the linked list.\n\nSo, that is how singly linked lists work in Zig in a nutshell. To sum up,\nthis is all the source code that was exposed in this section inside the single cell:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst NodeU32 = struct {\n data: u32,\n node: std.SinglyLinkedList.Node = .{},\n};\n\nvar list: std.SinglyLinkedList = .{};\nvar one: NodeU32 = .{ .data = 1 };\nvar two: NodeU32 = .{ .data = 2 };\nvar three: NodeU32 = .{ .data = 3 };\nvar five: NodeU32 = .{ .data = 5 };\n\nlist.prepend(&two.node); // {2}\ntwo.node.insertAfter(&five.node); // {2, 5}\ntwo.node.insertAfter(&three.node); // {2, 3, 5}\nlist.prepend(&one.node); // {1, 2, 3, 5}\n\ntry stdout.print(\"Number of nodes: {}\", .{list.len()});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nNumber of nodes: 4\n```\n\n\n:::\n:::\n\n\n\n\n### How to use a doubly linked list\n\nIf you want to use a doubly linked list instead, you will face a similar workflow compared to the\nsingly linked list:\n\n1. You first create a \"custom node type\" that can store the specific data type that you want.\n2. Create an empty doubly linked list object.\n3. Create the nodes of linked list.\n4. Start to insert the nodes inside the list.\n\nIn your \"custom node type\", you should use the `DoublyLinkedList.Node` type to denote\nthe `node` member of the struct. The snippet below demonstrates that. Here we are creating,\nonce again, a node type that can store `u32` values. But this time, this struct is tailored\nto be used inside a `DoublyLinkedList` struct.\n\nAfter this step, the way that you create the new empty linked list, and the nodes that you want insert,\nis practically identical to the singly linked list case. But, this time,\nwe normally use the `append()` method from the linked list object to add new nodes to the list.\n\nThis `append()` method from the linked list object will always append the input node to the end of the\nlinked list. However, in case you want to add the new node into a different position of the list, then,\nyou should take a look at the `insertAfter()` and `insertBefore()` methods of the linked list object.\nThese methods allow you to insert the new node either after or before an existing node in the list.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst NodeU32 = struct {\n data: u32,\n node: std.DoublyLinkedList.Node = .{},\n};\n\nvar list: std.DoublyLinkedList = .{};\nvar one: NodeU32 = .{ .data = 1 };\nvar two: NodeU32 = .{ .data = 2 };\nvar three: NodeU32 = .{ .data = 3 };\nvar five: NodeU32 = .{ .data = 5 };\n\nlist.append(&one.node); // {1}\nlist.append(&three.node); // {1, 3}\nlist.insertAfter(\n &one.node,\n &five.node\n); // {1, 5, 3}\nlist.append(&two.node); // {1, 5, 3, 2}\n\ntry stdout.print(\"Number of nodes: {}\", .{list.len()});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nNumber of nodes: 4\n```\n\n\n:::\n:::\n\n\n\nThese are other methods from the `DoublyLinkedList` object that might interest you:\n\n- `remove()`: to remove a specific node from the list.\n- `len()`: to count the number of nodes in the list.\n- `prepend()`: to add a node to the beginning of the list (i.e. set the head node of the list).\n- `pop()`: to remove the last node of the list.\n- `popFirst()`: to remove the first node of the list.\n- `concatByMoving()`: to concat two doubly linked lists together.\n\n\n### Iterating through the linked list\n\nIf you want to iterate over the elements of the linked list, all you need to do is to follow\nthe trail created by the \"pointer to next node\". We usually do that inside a while loop, that simply goes to the\nnext node over and over, until it finds a null pointer, which means that we hit the end of the list.\n\nThis next example demonstrates how such while loop would work. Notice that we are using the `@fieldParentPtr()`\nbuilt-in function to get access to a pointer that points to the parent instance of the `node` object. In other words,\nwe get access to a pointer to the `NodeU32` instance that contains the current node. This way, we can use this pointer\nto access the data that is currently stored in this node.\n\nAlso notice that in each iteration of the while loop, we are changing the value of the `it` variable to the next node\nin the list. The while loop is interrupted in the moment that this `it` variable becomes null, which will happen\nwhen the there is not \"next node\" in the list, which means that we have reached the end of the list.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst NodeU32 = struct {\n data: u32,\n node: std.SinglyLinkedList.Node = .{},\n};\n\nvar list: std.SinglyLinkedList = .{};\nvar one: NodeU32 = .{ .data = 1 };\nvar two: NodeU32 = .{ .data = 2 };\nvar three: NodeU32 = .{ .data = 3 };\nvar five: NodeU32 = .{ .data = 5 };\n\nlist.prepend(&two.node); // {2}\nlist.prepend(&five.node); // {5, 2}\nlist.prepend(&three.node); // {3, 5, 2}\nlist.prepend(&one.node); // {1, 3, 5, 2}\n\nvar it = list.first;\nwhile (it) |node| : (it = node.next) {\n const l: *NodeU32 = @fieldParentPtr(\n \"node\", node\n );\n try stdout.print(\n \"Current value: {}\", .{l.data}\n );\n}\n```\n:::\n\n\n\n```\nCurrent value: 1\nCurrent value: 3\nCurrent value: 5\nCurrent value: 2\n```\n\n\n\n\n## Multi array structure\n\nZig introduces a new data structure called `MultiArrayList()`. It's a different version of the dynamic array\nthat we have introduced in @sec-dynamic-array. The difference between this structure and the `ArrayList()`\nthat we know from @sec-dynamic-array, is that `MultiArrayList()` creates a separate dynamic array\nfor each field of the struct that you provide as input.\n\nConsider the following code example. We create a new custom struct called `Person`. This\nstruct contains three different data members, or, three different fields. As consequence,\nwhen we provide this `Person` data type as input to `MultiArrayList()`, this\ncreates a \"struct of three different arrays\" called `PersonArray`. In other words,\nthis `PersonArray` is a struct that contains three internal dynamic arrays in it.\nOne array for each field found in the `Person` struct definition.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Person = struct {\n name: []const u8,\n age: u8,\n height: f32,\n};\nconst PersonArray = std.MultiArrayList(Person);\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n var people = PersonArray{};\n defer people.deinit(allocator);\n\n try people.append(allocator, .{\n .name = \"Auguste\", .age = 15, .height = 1.54\n });\n try people.append(allocator, .{\n .name = \"Elena\", .age = 26, .height = 1.65\n });\n try people.append(allocator, .{\n .name = \"Michael\", .age = 64, .height = 1.87\n });\n}\n```\n:::\n\n\n\nIn other words, instead of creating an array of \"persons\", the `MultiArrayList()` function\ncreates a \"struct of arrays\". Each data member of this struct is a different array that stores\nthe values of a specific field from the `Person` values that were added (or, appended) to this \"struct of arrays\".\nOne important detail is that each of these separate internal arrays stored inside `PersonArray`\nare dynamic arrays. This means that these arrays can grow in capacity automatically as needed, to accomodate\nmore values.\n\nThe @fig-multi-array exposed below presents a diagram that describes the `PersonArray` struct\nthat we have created in the previous code example. Notice that the values of the data members\npresent in each of the three `Person` values that we have appended into the `PersonArray` object\n, are scattered across three different internal arrays of the `PersonArray` object.\n\n![A diagram of the `PersonArray` struct.](./../Figures/multi-array.png){#fig-multi-array}\n\nYou can easily access each of these arrays separately, and iterate over the values of each array.\nFor that, you will need to call the `items()` method from the `PersonArray` object, and provide as input\nto this method, the name of the field that you want to iterate over.\nIf you want to iterate through the `.age` array for example, then, you need to call `items(.age)` from\nthe `PersonArray` object, like in the example below:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfor (people.items(.age)) |*age| {\n try stdout.print(\"Age: {d}\\n\", .{age.*});\n}\n```\n:::\n\n\n\n```\nAge: 15\nAge: 26\nAge: 64\n```\n\n\nIn the above example, we are iterating over the values of the `.age` array, or,\nthe internal array of the `PersonArray` object that contains the values of the `age`\ndata member from the `Person` values that were added to the multi array struct.\n\nIn this example we are calling the `items()` method directly from the `PersonArray`\nobject. However, in most situations it's recommened to call this `items()` method\nfrom a \"slice object\", which you can create from the `slice()` method.\nThe reason for this is that calling `items()` multiple times have better performance\nif you use a slice object.\n\nTherefore, if you are planning to access only one of the\ninternal arrays from your \"multi array struct\", it's fine to call `items()` directly\nfrom the multi array object. But if you need to access many of the internal arrays\nfrom your \"multi array struct\", then, you will likely need to call `items()` more\nthan once, and, in such circumstance, is better to call `items()` through a slice object.\nThe example below demonstrates the use of such object:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar slice = people.slice();\nfor (slice.items(.age)) |*age| {\n age.* += 10;\n}\nfor (slice.items(.name), slice.items(.age)) |*n,*a| {\n try stdout.print(\n \"Name: {s}, Age: {d}\\n\", .{n.*, a.*}\n );\n}\n```\n:::\n\n\n\n```\nName: Auguste, Age: 25\nName: Elena, Age: 36\nName: Michael, Age: 74\n```\n\n\n## Conclusion\n\nThere are many other data structures that I haven't presented here.\nBut you can check them out at the official Zig Standard Library documentation page.\nActually, when you get into the [homepage of the documentation](https://ziglang.org/documentation/master/std/#)[^home], the first thing\nthat appears to you in this page, is a list of types and data structures that\nare available in the Zig Standard Library.\nThere are some very specific data structures in this list, like a\n[`BoundedArray` struct](https://ziglang.org/documentation/master/std/#std.bounded_array.BoundedArray)[^bounded]\n, but there is also some more general structures, such as a\n[`PriorityQueue` struct](https://ziglang.org/documentation/master/std/#std.priority_queue.PriorityQueue)[^priority].\n\n\n[^home]: \n[^priority]: .\n[^bounded]: \n", - "supporting": [ - "09-data-structures_files" - ], - "filters": [ - "rmarkdown/pagebreak.lua" - ], - "includes": {}, - "engineDependencies": { - "knitr": [ - "{\"type\":\"list\",\"attributes\":{},\"value\":[]}" - ] - }, - "preserve": null, - "postProcess": false - } -} \ No newline at end of file diff --git a/_freeze/Chapters/09-error-handling/execute-results/epub.json b/_freeze/Chapters/09-error-handling/execute-results/epub.json deleted file mode 100644 index bd4ccc0b..00000000 --- a/_freeze/Chapters/09-error-handling/execute-results/epub.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "hash": "1ef4c69c6b1bfd8553723d38f6a46fb8", - "result": { - "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Error handling and unions {#sec-error-handling}\n\nIn this chapter, I want to discuss how error handling is done in Zig.\nWe already briefly learned about one of the available strategies to handle errors in Zig,\nwhich is the `try` keyword presented in @sec-main-file. But we still haven't learned about\nthe other methods, such as the `catch` keyword.\nI also want to discuss in this chapter how union types are created in Zig.\n\n## Learning more about errors in Zig\n\nBefore we get into how error handling is done, we need to learn more about what errors are in Zig.\nAn error is actually a value in Zig [@zigoverview]. In other words, when an error occurs inside your Zig program,\nit means that somewhere in your Zig codebase, an error value is being generated.\nAn error value is similar to any integer value that you create in your Zig code.\nYou can take an error value and pass it as input to a function,\nand you can also cast (or coerce) it into a different type of an error value.\n\nThis have some similarities with exceptions in C++ and Python.\nBecause in C++ and Python, when an exception happens inside a `try` block,\nyou can use a `catch` block (in C++) or an `except` block (in Python)\nto capture the exception produced in the `try` block,\nand pass it to functions as an input.\n\nHowever, error values in Zig are treated very differently than exceptions.\nFirst, you cannot ignore error values in your Zig code. Meaning that, if an error\nvalue appears somewhere in your source code, this error value must be explicitly handled in some way.\nThis also means that you cannot discard error values by assigning them to an underscore,\nas you could do with normal values and objects.\n\nTake the source code below as an example. Here we are trying to open a file that does not exist\nin my computer, and as a result, an obvious error value of `FileNotFound` is returned from the `openFile()`\nfunction. But because I'm assigning the result of this function to an underscore, I end up\ntrying to discard an error value.\n\nThe `zig` compiler detects this mistake, and raises a compile\nerror telling me that I'm trying to discard an error value.\nIt also adds a note message that suggests the use of `try`,\n`catch` or an if statement to explicitly handle this error value\nThis note is reinforcing that every possible error value must be explicitly handled in Zig.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst dir = std.fs.cwd();\n_ = dir.openFile(\"doesnt_exist.txt\", .{});\n```\n:::\n\n\n\n```\nt.zig:8:17: error: error set is discarded\nt.zig:8:17: note: consider using 'try', 'catch', or 'if'\n```\n\n\n### Returning errors from functions\n\nAs we described in @sec-main-file, when we have a function that might return an error\nvalue, this function normally includes an exclamation mark (`!`) in its return type\nannotation. The presence of this exclamation mark indicates that this function might\nreturn an error value as result, and, the `zig` compiler forces you to always handle explicitly\nthe case of this function returning an error value.\n\nTake a look at the `print_name()` function below. This function might return an error in the `stdout.print()` function call,\nand, as a consequence, its return type (`!void`) includes an exclamation mark in it.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_name() !void {\n const stdout = std.getStdOut().writer();\n try stdout.print(\"My name is Pedro!\", .{});\n}\n```\n:::\n\n\n\nIn the example above, we are using the exclamation mark to tell the `zig` compiler\nthat this function might return some error. But which error exactly is returned from\nthis function? For now, we are not specifying a specific error value. For now,\nwe only know that some error value (whatever it is) might be returned.\n\nBut in fact, you can (if you want to) specify clearly which exact error values\nmight be returned from this function. There are lot of examples of\nthis in the Zig Standard Library. Take this `fill()` function from\nthe `http.Client` module as an example. This function returns\neither a error value of type `ReadError`, or `void`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn fill(conn: *Connection) ReadError!void {\n // The body of this function ...\n}\n```\n:::\n\n\n\nThis idea of specifying the exact error values that you expect to be returned\nfrom the function is interesting. Because they automatically become some sort of documentation\nof your function, and also, this allows the `zig` compiler to perform some extra checks over\nyour code. Because the compiler can check if there is any other type of error value\nthat is being generated inside your function, and, that it's not being accounted\nfor in this return type annotation.\n\nAnyway, you can list the types of errors that can be returned from the function\nby listing them on the left side of the exclamation mark. While the valid values\nstay on the right side of the exclamation mark. So the syntax format become:\n\n```\n!\n```\n\n\n### Error sets\n\nBut what about when we have a single function that might return different types of errors?\nWhen you have such a function, you can list\nall of these different types of errors that can be returned from this function,\nthrough a structure in Zig that we call of an *error set*.\n\nAn error set is a special case of a union type. It's a union that contains error values in it.\nNot all programming languages have a notion of a \"union object\".\nBut in summary, a union is just a set of data types.\nUnions are used to allow an object to have multiple data types.\nFor example, a union of `x`, `y` and `z`, means that\nan object can be either of type `x`, or type `y` or type `z`.\n\nWe are going to talk in more depth about unions in @sec-unions.\nBut you can write an error set by writing the keyword `error` before\na pair of curly braces, then you list the error values that can be\nreturned from the function inside this pair of curly braces.\n\nTake the `resolvePath()` function below as an example, which comes from the\n`introspect.zig` module of the Zig Standard Library. We can see in its return type annotation, that this\nfunction return either: 1) a valid slice of `u8` values (`[]u8`); or, 2) one of the three different\ntypes of error values listed inside the error set (`OutOfMemory`, `Unexpected`, etc.).\nThis is an usage example of an error set.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn resolvePath(\n ally: mem.Allocator,\n p: []const u8,\n) error{\n OutOfMemory,\n CurrentWorkingDirectoryUnlinked,\n Unexpected,\n}![]u8 {\n // The body of the function ...\n}\n```\n:::\n\n\n\n\nThis is a valid way of annotating the return value of a Zig function. But, if you navigate through\nthe modules that composes the Zig Standard Library, you will notice that, for the majority of cases,\nthe programmers prefer to give a descriptive name to this error set, and then, use this name (or this \"label\")\nof the error set in the return type annotation, instead of using the error set directly.\n\nWe can see that in the `ReadError` error set that we showed earlier in the `fill()` function,\nwhich is defined in the `http.Client` module.\nSo yes, I presented the `ReadError` as if it was just a standard and single error value, but in fact,\nit's an error set defined in the `http.Client` module, and therefore, it actually represents\na set of different error values that might happen inside the `fill()` function.\n\n\nTake a look at the `ReadError` definition reproduced below. Notice that we are grouping all of these\ndifferent error values into a single object, and then, we use this object into the return type annotation of the function.\nLike the `fill()` function that we showed earlier, or, the `readvDirect()` function from the same module,\nwhich is reproduced below.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const ReadError = error{\n TlsFailure,\n TlsAlert,\n ConnectionTimedOut,\n ConnectionResetByPeer,\n UnexpectedReadFailure,\n EndOfStream,\n};\n// Some lines of code\npub fn readvDirect(\n conn: *Connection,\n buffers: []std.posix.iovec\n ) ReadError!usize {\n // The body of the function ...\n}\n```\n:::\n\n\n\nSo, an error set is just a convenient way of grouping a set of\npossible error values into a single object, or a single type of an error value.\n\n\n### Casting error values\n\nLet's suppose you have two different error sets, named `A` and `B`.\nIf error set `A` is a superset of error set `B`, then, you can cast (or coerce)\nerror values from `B` into error values of `A`.\n\nError sets are just a set of error values. So, if the error set `A`\ncontains all error values from the error set `B`, then `A`\nbecomes a superset of `B`. You could also say\nthat the error set `B` is a subset of error set `A`.\n\nThe example below demonstrates this idea. Because `A` contains all\nvalues from `B`, `A` is a superset of `B`.\nIn math notation, we would say that $A \\supset B$.\nAs a consequence, we can give an error value from `B` as input to the `cast()`\nfunction, and, implicitly cast this input into the same error value, but from the `A` set.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst A = error{\n ConnectionTimeoutError,\n DatabaseNotFound,\n OutOfMemory,\n InvalidToken,\n};\nconst B = error {\n OutOfMemory,\n};\n\nfn cast(err: B) A {\n return err;\n}\n\ntest \"coerce error value\" {\n const error_value = cast(B.OutOfMemory);\n try std.testing.expect(\n error_value == A.OutOfMemory\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3e2d5fb03d41.test.coerce error value...OKA\n All 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n## How to handle errors\n\nNow that we learned more about what errors are in Zig,\nlet's discuss the available strategies to handle these errors,\nwhich are:\n\n- `try` keyword;\n- `catch` keyword;\n- an if statement;\n- `errdefer` keyword;\n\n\n\n### What `try` means?\n\nAs I described over the previous sections, when we say that an expression might\nreturn an error, we are basically referring to an expression that have\na return type in the format `!T`.\nThe `!` indicates that this expression returns either an error value, or a value of type `T`.\n\nIn @sec-main-file, I presented the `try` keyword and where to use it.\nBut I did not talked about what exactly this keyword does to your code,\nor, in other words, I have not explained yet what `try` means in your code.\n\nIn essence, when you use the `try` keyword in an expression, you are telling\nthe `zig` compiler the following: \"Hey! Execute this expression for me,\nand, if this expression return an error, please, return this error for me\nand stop the execution of my program. But if this expression return a valid\nvalue, then, return this value, and move on\".\n\nIn other words, the `try` keyword is essentially, a strategy to enter in panic mode, and stop\nthe execution of your program in case an error occurs.\nWith the `try` keyword, you are telling the `zig` compiler, that stopping the execution\nof your program is the most reasonable strategy to take if an error occurs\nin that particular expression.\n\n### The `catch` keyword\n\nOk, now that we understand properly what `try` means, let's discuss `catch` now.\nOne important detail here, is that you can use `try` or `catch` to handle your errors,\nbut you **cannot use `try` and `catch` together**. In other words, `try` and `catch`\nare different and completely separate strategies in the Zig language.\n\nThis is uncommon, and different than what happens in other languages. Most\nprogramming languages that adopts the *try catch* pattern (such as C++, R, Python, Javascript, etc.), normally use\nthese two keywords together to form the complete logic to\nproperly handle the errors.\nAnyway, Zig tries a different approach in the *try catch* pattern.\n\nSo, we learned already about what `try` means, and we also known that both\n`try` and `catch` should be used alone, separate from each other. But\nwhat exactly `catch` do in Zig? With `catch`, we can construct a block of\nlogic to handle the error value, in case it happens in the current expression.\n\nLook at the code example below. Once again, we go back to the previous\nexample where we were trying to open a file that doesn't exist in my computer,\nbut this time, I use `catch` to actually implement a logic to handle the error, instead of\njust stopping the execution right away.\n\nMore specifically, in this example, I'm using a logger object to record some logs into\nthe system, before I return the error, and stop the execution of the program. For example,\nthis could be some part of the codebase of a complex system that I do not have full control over,\nand I want to record these logs before the program crashes, so that I can debug it later\n(e.g. maybe I cannot compile the full program, and properly debug it with a debugger. So, these logs might\nbe a valid strategy to surpass this barrier).\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst dir = std.fs.cwd();\nconst file = dir.openFile(\n \"doesnt_exist.txt\", .{}\n) catch |err| {\n logger.record_context();\n logger.log_error(err);\n return err;\n};\n```\n:::\n\n\n\n\nTherefore, we use `catch` to create a block of expressions that will handle the error.\nI can return the error value from this block of expressions, like I did in the above example,\nwhich, will make the program enter in panic mode, and, stop the execution.\nBut I could also, return a valid value from this block of code, which would\nbe stored in the `file` object.\n\nNotice that, instead of writing the keyword before the expression that might return the error,\nlike we do with `try`, we write `catch` after the expression. We can open the pair of pipes (`|`),\nwhich captures the error value returned by the expression, and makes\nthis error value available in the scope of the `catch` block as the object named `err`.\nIn other words, because I wrote `|err|` in the code, I can access the error value\nreturned by the expression, by using the `err` object.\n\nAlthough this being the most common use of `catch`, you can also use this keyword\nto handle the error in a \"default value\" style. That is, if the expression returns\nan error, we use the default value instead. Otherwise, we use the valid value returned\nby the expression.\n\nThe Zig official language reference, provides a great example of this \"default value\"\nstrategy with `catch`. This example is reproduced below. Notice that we are trying to parse\nsome unsigned integer from a string object named `str`. In other words, this function\nis trying to transform an object of type `[]const u8` (i.e., an array of characters, a string, etc.)\ninto an object of type `u64`.\n\nBut this parsing process done by the function `parseU64()` may fail, resulting in a runtime error.\nThe `catch` keyword used in this example provides an alternative value (13) to be used in case\nthis `parseU64()` function raises an error. So, the expression below essentially means:\n\"Hey! Please, parse this string into a `u64` for me, and store the results into the\nobject `number`. But, if an error occurs, then, use the value `13` instead\".\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number = parseU64(str, 10) catch 13;\n```\n:::\n\n\n\nSo, at the end of this process, the object `number` will contain either a `u64` integer\nthat was parsed successfully from the input string `str`, or, if an error occurs in the\nparsing process, it will contain the `u64` value `13` that was provided by the `catch`\nkeyword as the \"default\", or, the \"alternative\" value.\n\n\n\n### Using if statements\n\nNow, you can also use if statements to handle errors in your Zig code.\nIn the example below, I'm reproducing the previous example, where\nwe try to parse an integer value from an input string with a function\nnamed `parseU64()`.\n\nWe execute the expression inside the \"if\". If this expression returns an\nerror value, the \"if branch\" (or, the \"true branch\") of the if statement is not executed.\nBut if this expression returns a valid value instead, then, this value is unwrapped\ninto the `number` object.\n\nThis means that, if the `parseU64()` expression returns a valid value, this value becomes available\ninside the scope of this \"if branch\" (i.e., the \"true branch\") through the object that we listed inside the pair\nof pipe character (`|`), which is the object `number`.\n\nIf an error occurs, we can use an \"else branch\" (or the \"false branch\") of the if statement\nto handle the error. In the example below, we are using the `else` in the if statement\nto unwrap the error value (that was returned by `parseU64()`) into the `err` object,\nand handle the error.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (parseU64(str, 10)) |number| {\n // do something with `number` here\n} else |err| {\n // handle the error value.\n}\n```\n:::\n\n\n\nNow, if the expression that you are executing returns different types of error values,\nand you want to take a different action in each of these types of error values, the\n`try` and `catch` keywords, and the if statement strategy, becomes limited.\n\nFor this type of situation, the official documentation of the language suggests\nthe use of a switch statement together with an if statement [@zigdocs].\nThe basic idea is, to use the if statement to execute the expression, and\nuse the \"else branch\" to pass the error value to a switch statement, where\nyou define a different action for each type of error value that might be\nreturned by the expression executed in the if statement.\n\nThe example below demonstrates this idea. We first try to add (or register) a set of\ntasks to a queue. If this \"registration process\" occurs well, we then try\nto distribute these tasks across the workers of our system. But\nif this \"registration process\" returns an error value, we then use a switch\nstatement in the \"else branch\" to handle each possible error value.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (add_tasks_to_queue(&queue, tasks)) |_| {\n distribute_tasks(&queue);\n} else |err| switch (err) {\n error.InvalidTaskName => {\n // do something\n },\n error.TimeoutTooBig => {\n // do something\n },\n error.QueueNotFound => {\n // do something\n },\n // and all the other error options ...\n}\n```\n:::\n\n\n\n\n### The `errdefer` keyword {#sec-errdefer2}\n\nA common pattern in C programs in general, is to clean resources when an error occurs during\nthe execution of the program. In other words, one common way to handle errors, is to perform\n\"cleanup actions\" before we exit our program. This guarantees that a runtime error does not make\nour program to leak resources of the system.\n\n\nThe `errdefer` keyword is a tool to perform such \"cleanup actions\" in hostile situations.\nThis keyword is commonly used to clean (or to free) allocated resources, before the execution of our program\ngets stopped because of an error value being generated.\n\nThe basic idea is to provide an expression to the `errdefer` keyword. Then,\n`errdefer` executes this expression if, and only if, an error occurs\nduring the execution of the current scope.\nIn the example below, we are using an allocator object (that we have presented in @sec-allocators)\nto create a new `User` object. If we are successful in creating and registering this new user,\nthis `create_user()` function will return this new `User` object as its return value.\n\nHowever, if for some reason, an error value is generated by some expression\nthat is after the `errdefer` line, for example, in the `db.add(user)` expression,\nthe expression registered by `errdefer` gets executed before the error value is returned\nfrom the function, and before the program enters in panic mode and stops the\ncurrent execution.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn create_user(db: Database, allocator: Allocator) !User {\n const user = try allocator.create(User);\n errdefer allocator.destroy(user);\n\n // Register new user in the Database.\n _ = try db.register_user(user);\n return user;\n}\n```\n:::\n\n\n\nBy using `errdefer` to destroy the `user` object that we have just created,\nwe guarantee that the memory allocated for this `user` object\ngets freed, before the execution of the program stops.\nBecause if the expression `try db.add(user)` returns an error value,\nthe execution of our program stops, and we lose all references and control over the memory\nthat we have allocated for the `user` object.\nAs a result, if we do not free the memory associated with the `user` object before the program stops,\nwe cannot free this memory anymore. We simply lose our chance to do the right thing.\nThat is why `errdefer` is essential in this situation.\n\nJust to state clearly the differences between `defer` and `errdefer`\n(which I described in @sec-defer and @sec-errdefer1), it might be worth\nto discuss the subject a bit further. You might still have the question\n\"why use `errdefer` if we can use `defer` instead?\" in your mind.\n\nAlthough being similar, the key difference between `errdefer` and `defer` keyword\nis when the provided expression gets executed.\nThe `defer` keyword always execute the provided expression at the end of the\ncurrent scope, no matter how your code exits this scope.\nIn contrast, `errdefer` executes the provided expression only when an error occurs in the\ncurrent scope.\n\nThis becomes important if a resource that you allocate in the\ncurrent scope gets freed later in your code, in a different scope.\nThe `create_user()` functions is an example of this. If you think\nclosely about this function, you will notice that this function returns\nthe `user` object as the result.\n\nIn other words, the allocated memory for the `user` object does not get\nfreed inside the `create_user()` function, if it returns successfully.\nSo, if an error does not occur inside this function, the `user` object\nis returned from the function, and probably, the code that runs after\nthis `create_user()` function will be responsible for freeing\nthe memory of the `user` object.\n\nBut what if an error occurs inside the `create_user()` function? What happens then?\nThis would mean that the execution of your code would stop in this `create_user()`\nfunction, and, as a consequence, the code that runs after this `create_user()`\nfunction would simply not run, and, as a result, the memory of the `user` object\nwould not be freed before your program stops.\n\nThis is the perfect scenario for `errdefer`. We use this keyword to guarantee\nthat our program will free the allocated memory for the `user` object,\neven if an error occurs inside the `create_user()` function.\n\nIf you allocate and free some memory for an object inside the same scope, then,\njust use `defer` and be happy, i.e., `errdefer` have no use for you in such situation.\nBut if you allocate some memory in a scope A, but you only free this memory\nlater, in a scope B for example, then, `errdefer` becomes useful to avoid leaking memory\nin sketchy situations.\n\n\n\n## Union type in Zig {#sec-unions}\n\nA union type defines a set of types that an object can be. It's like a list of\noptions. Each option is a type that an object can assume. Therefore, unions in Zig\nhave the same meaning, or, the same role as unions in C. They are used for the same purpose.\nYou could also say that unions in Zig produces a similar effect to\n[using `typing.Union` in Python](https://docs.python.org/3/library/typing.html#typing.Union)[^pyunion].\n\n[^pyunion]: \n\nFor example, you might be creating an API that sends data to a data lake, hosted\nin some private cloud infrastructure. Suppose you have created different structs in your codebase,\nto store the necessary information that you need, in order to connect to the services of\neach mainstream data lake service (Amazon S3, Azure Blob, etc.).\n\nNow, suppose you also have a function named `send_event()` that receives an event as input,\nand, a target data lake, and it sends the input event to the data lake specified in the\ntarget data lake argument. But this target data lake could be any of the three mainstream data lakes\nservices (Amazon S3, Azure Blob, etc.). Here is where an union can help you.\n\nThe union `LakeTarget` defined below allows the `lake_target` argument of `send_event()`\nto be either an object of type `AzureBlob`, or type `AmazonS3`, or type `GoogleGCP`.\nThis union allows the `send_event()` function to receive an object of any of these three types\nas input in the `lake_target` argument.\n\nRemember that each of these three types (`AmazonS3`, `GoogleGCP` and `AzureBlob`)\nare separate structs that we have defined in our source code. So, at first glance,\nthey are separate data types in our source code. But is the `union` keyword that\nunifies them into a single data type called `LakeTarget`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst LakeTarget = union {\n azure: AzureBlob,\n amazon: AmazonS3,\n google: GoogleGCP,\n};\n\nfn send_event(\n event: Event,\n lake_target: LakeTarget\n) bool {\n // body of the function ...\n}\n```\n:::\n\n\n\nAn union definition is composed by a list of data members. Each data member is of a specific data type.\nIn the example above, the `LakeTarget` union have three data members (`azure`, `amazon`, `google`).\nWhen you instantiate an object that uses an union type, you can only use one of its data members\nin this instantiation.\n\nYou could also interpret this as: only one data member of an union type can be activated at a time, the other data\nmembers remain deactivated and unaccessible. For example, if you create a `LakeTarget` object that uses\nthe `azure` data member, you can no longer use or access the data members `google` or `amazon`.\nIt's like if these other data members didn't exist at all in the `LakeTarget` type.\n\nYou can see this logic in the example below. Notice that, we first instantiate the union\nobject using the `azure` data member. As a result, this `target` object contains only\nthe `azure` data member inside of it. Only this data member is active in this object.\nThat is why the last line in this code example is invalid. Because we are trying to instantiate the data member\n`google`, which is currently inactive for this `target` object, and as a result, the program\nenters in panic mode warning us about this mistake through a loud error message.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar target = LakeTarget {\n .azure = AzureBlob.init()\n};\n// Only the `azure` data member exist inside\n// the `target` object, and, as a result, this\n// line below is invalid:\ntarget.google = GoogleGCP.init();\n```\n:::\n\n\n\n```\nthread 2177312 panic: access of union field 'google' while\n field 'azure' is active:\n target.google = GoogleGCP.init();\n ^\n```\n\nSo, when you instantiate an union object, you must choose one of the data types (or, one of the data members)\nlisted in the union type. In the example above, I choose to use the `azure` data member, and, as a result,\nall other data members were automatically deactivated,\nand you can no longer use them after you instantiate the object.\n\nYou can activate another data member by completely redefining the entire enum object.\nIn the example below, I initially use the `azure` data member. But then, I redefine the\n`target` object to use a new `LakeTarget` object, which uses the `google` data member.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar target = LakeTarget {\n .azure = AzureBlob.init()\n};\ntarget = LakeTarget {\n .google = GoogleGCP.init()\n};\n```\n:::\n\n\n\nA curious fact about union types, is that, at first, you cannot use them in switch statements (which were presented in @sec-switch).\nIn other words, if you have an object of type `LakeTarget` for example, you cannot give this object\nas input to a switch statement.\n\nBut what if you really need to do so? What if you actually need to\nprovide an \"union object\" to a switch statement? The answer to this question relies on another special type in Zig,\nwhich are the *tagged unions*. To create a tagged union, all you have to do is to add\nan enum type into your union declaration.\n\nAs an example of a tagged union in Zig, take the `Registry` type exposed\nbelow. This type comes from the\n[`grammar.zig` module](https://github.com/ziglang/zig/blob/30b4a87db711c368853b3eff8e214ab681810ef9/tools/spirv/grammar.zig)[^grammar]\nfrom the Zig repository. This union type lists different types of registries.\nBut notice this time, the use of `(enum)` after the `union` keyword. This is what makes\nthis union type a tagged union. By being a tagged union, an object of this `Registry` type\ncan be used as input in a switch statement. This is all you have to do. Just add `(enum)`\nto your `union` declaration, and you can use it in switch statements.\n\n[^grammar]: .\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Registry = union(enum) {\n core: CoreRegistry,\n extension: ExtensionRegistry,\n};\n```\n:::\n", - "supporting": [ - "09-error-handling_files" - ], - "filters": [ - "rmarkdown/pagebreak.lua" - ], - "includes": {}, - "engineDependencies": { - "knitr": [ - "{\"type\":\"list\",\"attributes\":{},\"value\":[]}" - ] - }, - "preserve": null, - "postProcess": false - } -} \ No newline at end of file diff --git a/_freeze/Chapters/09-error-handling/execute-results/html.json b/_freeze/Chapters/09-error-handling/execute-results/html.json index aaffaa3e..9c2d7fed 100644 --- a/_freeze/Chapters/09-error-handling/execute-results/html.json +++ b/_freeze/Chapters/09-error-handling/execute-results/html.json @@ -2,10 +2,8 @@ "hash": "1ef4c69c6b1bfd8553723d38f6a46fb8", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Error handling and unions {#sec-error-handling}\n\nIn this chapter, I want to discuss how error handling is done in Zig.\nWe already briefly learned about one of the available strategies to handle errors in Zig,\nwhich is the `try` keyword presented in @sec-main-file. But we still haven't learned about\nthe other methods, such as the `catch` keyword.\nI also want to discuss in this chapter how union types are created in Zig.\n\n## Learning more about errors in Zig\n\nBefore we get into how error handling is done, we need to learn more about what errors are in Zig.\nAn error is actually a value in Zig [@zigoverview]. In other words, when an error occurs inside your Zig program,\nit means that somewhere in your Zig codebase, an error value is being generated.\nAn error value is similar to any integer value that you create in your Zig code.\nYou can take an error value and pass it as input to a function,\nand you can also cast (or coerce) it into a different type of an error value.\n\nThis have some similarities with exceptions in C++ and Python.\nBecause in C++ and Python, when an exception happens inside a `try` block,\nyou can use a `catch` block (in C++) or an `except` block (in Python)\nto capture the exception produced in the `try` block,\nand pass it to functions as an input.\n\nHowever, error values in Zig are treated very differently than exceptions.\nFirst, you cannot ignore error values in your Zig code. Meaning that, if an error\nvalue appears somewhere in your source code, this error value must be explicitly handled in some way.\nThis also means that you cannot discard error values by assigning them to an underscore,\nas you could do with normal values and objects.\n\nTake the source code below as an example. Here we are trying to open a file that does not exist\nin my computer, and as a result, an obvious error value of `FileNotFound` is returned from the `openFile()`\nfunction. But because I'm assigning the result of this function to an underscore, I end up\ntrying to discard an error value.\n\nThe `zig` compiler detects this mistake, and raises a compile\nerror telling me that I'm trying to discard an error value.\nIt also adds a note message that suggests the use of `try`,\n`catch` or an if statement to explicitly handle this error value\nThis note is reinforcing that every possible error value must be explicitly handled in Zig.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst dir = std.fs.cwd();\n_ = dir.openFile(\"doesnt_exist.txt\", .{});\n```\n:::\n\n\n\n\n```\nt.zig:8:17: error: error set is discarded\nt.zig:8:17: note: consider using 'try', 'catch', or 'if'\n```\n\n\n### Returning errors from functions\n\nAs we described in @sec-main-file, when we have a function that might return an error\nvalue, this function normally includes an exclamation mark (`!`) in its return type\nannotation. The presence of this exclamation mark indicates that this function might\nreturn an error value as result, and, the `zig` compiler forces you to always handle explicitly\nthe case of this function returning an error value.\n\nTake a look at the `print_name()` function below. This function might return an error in the `stdout.print()` function call,\nand, as a consequence, its return type (`!void`) includes an exclamation mark in it.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_name() !void {\n const stdout = std.getStdOut().writer();\n try stdout.print(\"My name is Pedro!\", .{});\n}\n```\n:::\n\n\n\n\nIn the example above, we are using the exclamation mark to tell the `zig` compiler\nthat this function might return some error. But which error exactly is returned from\nthis function? For now, we are not specifying a specific error value. For now,\nwe only know that some error value (whatever it is) might be returned.\n\nBut in fact, you can (if you want to) specify clearly which exact error values\nmight be returned from this function. There are lot of examples of\nthis in the Zig Standard Library. Take this `fill()` function from\nthe `http.Client` module as an example. This function returns\neither a error value of type `ReadError`, or `void`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn fill(conn: *Connection) ReadError!void {\n // The body of this function ...\n}\n```\n:::\n\n\n\n\nThis idea of specifying the exact error values that you expect to be returned\nfrom the function is interesting. Because they automatically become some sort of documentation\nof your function, and also, this allows the `zig` compiler to perform some extra checks over\nyour code. Because the compiler can check if there is any other type of error value\nthat is being generated inside your function, and, that it's not being accounted\nfor in this return type annotation.\n\nAnyway, you can list the types of errors that can be returned from the function\nby listing them on the left side of the exclamation mark. While the valid values\nstay on the right side of the exclamation mark. So the syntax format become:\n\n```\n!\n```\n\n\n### Error sets\n\nBut what about when we have a single function that might return different types of errors?\nWhen you have such a function, you can list\nall of these different types of errors that can be returned from this function,\nthrough a structure in Zig that we call of an *error set*.\n\nAn error set is a special case of a union type. It's a union that contains error values in it.\nNot all programming languages have a notion of a \"union object\".\nBut in summary, a union is just a set of data types.\nUnions are used to allow an object to have multiple data types.\nFor example, a union of `x`, `y` and `z`, means that\nan object can be either of type `x`, or type `y` or type `z`.\n\nWe are going to talk in more depth about unions in @sec-unions.\nBut you can write an error set by writing the keyword `error` before\na pair of curly braces, then you list the error values that can be\nreturned from the function inside this pair of curly braces.\n\nTake the `resolvePath()` function below as an example, which comes from the\n`introspect.zig` module of the Zig Standard Library. We can see in its return type annotation, that this\nfunction return either: 1) a valid slice of `u8` values (`[]u8`); or, 2) one of the three different\ntypes of error values listed inside the error set (`OutOfMemory`, `Unexpected`, etc.).\nThis is an usage example of an error set.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn resolvePath(\n ally: mem.Allocator,\n p: []const u8,\n) error{\n OutOfMemory,\n CurrentWorkingDirectoryUnlinked,\n Unexpected,\n}![]u8 {\n // The body of the function ...\n}\n```\n:::\n\n\n\n\n\nThis is a valid way of annotating the return value of a Zig function. But, if you navigate through\nthe modules that composes the Zig Standard Library, you will notice that, for the majority of cases,\nthe programmers prefer to give a descriptive name to this error set, and then, use this name (or this \"label\")\nof the error set in the return type annotation, instead of using the error set directly.\n\nWe can see that in the `ReadError` error set that we showed earlier in the `fill()` function,\nwhich is defined in the `http.Client` module.\nSo yes, I presented the `ReadError` as if it was just a standard and single error value, but in fact,\nit's an error set defined in the `http.Client` module, and therefore, it actually represents\na set of different error values that might happen inside the `fill()` function.\n\n\nTake a look at the `ReadError` definition reproduced below. Notice that we are grouping all of these\ndifferent error values into a single object, and then, we use this object into the return type annotation of the function.\nLike the `fill()` function that we showed earlier, or, the `readvDirect()` function from the same module,\nwhich is reproduced below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const ReadError = error{\n TlsFailure,\n TlsAlert,\n ConnectionTimedOut,\n ConnectionResetByPeer,\n UnexpectedReadFailure,\n EndOfStream,\n};\n// Some lines of code\npub fn readvDirect(\n conn: *Connection,\n buffers: []std.posix.iovec\n ) ReadError!usize {\n // The body of the function ...\n}\n```\n:::\n\n\n\n\nSo, an error set is just a convenient way of grouping a set of\npossible error values into a single object, or a single type of an error value.\n\n\n### Casting error values\n\nLet's suppose you have two different error sets, named `A` and `B`.\nIf error set `A` is a superset of error set `B`, then, you can cast (or coerce)\nerror values from `B` into error values of `A`.\n\nError sets are just a set of error values. So, if the error set `A`\ncontains all error values from the error set `B`, then `A`\nbecomes a superset of `B`. You could also say\nthat the error set `B` is a subset of error set `A`.\n\nThe example below demonstrates this idea. Because `A` contains all\nvalues from `B`, `A` is a superset of `B`.\nIn math notation, we would say that $A \\supset B$.\nAs a consequence, we can give an error value from `B` as input to the `cast()`\nfunction, and, implicitly cast this input into the same error value, but from the `A` set.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst A = error{\n ConnectionTimeoutError,\n DatabaseNotFound,\n OutOfMemory,\n InvalidToken,\n};\nconst B = error {\n OutOfMemory,\n};\n\nfn cast(err: B) A {\n return err;\n}\n\ntest \"coerce error value\" {\n const error_value = cast(B.OutOfMemory);\n try std.testing.expect(\n error_value == A.OutOfMemory\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file826379a872a1.test.coerce error value...OKA\n All 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n## How to handle errors\n\nNow that we learned more about what errors are in Zig,\nlet's discuss the available strategies to handle these errors,\nwhich are:\n\n- `try` keyword;\n- `catch` keyword;\n- an if statement;\n- `errdefer` keyword;\n\n\n\n### What `try` means?\n\nAs I described over the previous sections, when we say that an expression might\nreturn an error, we are basically referring to an expression that have\na return type in the format `!T`.\nThe `!` indicates that this expression returns either an error value, or a value of type `T`.\n\nIn @sec-main-file, I presented the `try` keyword and where to use it.\nBut I did not talked about what exactly this keyword does to your code,\nor, in other words, I have not explained yet what `try` means in your code.\n\nIn essence, when you use the `try` keyword in an expression, you are telling\nthe `zig` compiler the following: \"Hey! Execute this expression for me,\nand, if this expression return an error, please, return this error for me\nand stop the execution of my program. But if this expression return a valid\nvalue, then, return this value, and move on\".\n\nIn other words, the `try` keyword is essentially, a strategy to enter in panic mode, and stop\nthe execution of your program in case an error occurs.\nWith the `try` keyword, you are telling the `zig` compiler, that stopping the execution\nof your program is the most reasonable strategy to take if an error occurs\nin that particular expression.\n\n### The `catch` keyword\n\nOk, now that we understand properly what `try` means, let's discuss `catch` now.\nOne important detail here, is that you can use `try` or `catch` to handle your errors,\nbut you **cannot use `try` and `catch` together**. In other words, `try` and `catch`\nare different and completely separate strategies in the Zig language.\n\nThis is uncommon, and different than what happens in other languages. Most\nprogramming languages that adopts the *try catch* pattern (such as C++, R, Python, Javascript, etc.), normally use\nthese two keywords together to form the complete logic to\nproperly handle the errors.\nAnyway, Zig tries a different approach in the *try catch* pattern.\n\nSo, we learned already about what `try` means, and we also known that both\n`try` and `catch` should be used alone, separate from each other. But\nwhat exactly `catch` do in Zig? With `catch`, we can construct a block of\nlogic to handle the error value, in case it happens in the current expression.\n\nLook at the code example below. Once again, we go back to the previous\nexample where we were trying to open a file that doesn't exist in my computer,\nbut this time, I use `catch` to actually implement a logic to handle the error, instead of\njust stopping the execution right away.\n\nMore specifically, in this example, I'm using a logger object to record some logs into\nthe system, before I return the error, and stop the execution of the program. For example,\nthis could be some part of the codebase of a complex system that I do not have full control over,\nand I want to record these logs before the program crashes, so that I can debug it later\n(e.g. maybe I cannot compile the full program, and properly debug it with a debugger. So, these logs might\nbe a valid strategy to surpass this barrier).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst dir = std.fs.cwd();\nconst file = dir.openFile(\n \"doesnt_exist.txt\", .{}\n) catch |err| {\n logger.record_context();\n logger.log_error(err);\n return err;\n};\n```\n:::\n\n\n\n\n\nTherefore, we use `catch` to create a block of expressions that will handle the error.\nI can return the error value from this block of expressions, like I did in the above example,\nwhich, will make the program enter in panic mode, and, stop the execution.\nBut I could also, return a valid value from this block of code, which would\nbe stored in the `file` object.\n\nNotice that, instead of writing the keyword before the expression that might return the error,\nlike we do with `try`, we write `catch` after the expression. We can open the pair of pipes (`|`),\nwhich captures the error value returned by the expression, and makes\nthis error value available in the scope of the `catch` block as the object named `err`.\nIn other words, because I wrote `|err|` in the code, I can access the error value\nreturned by the expression, by using the `err` object.\n\nAlthough this being the most common use of `catch`, you can also use this keyword\nto handle the error in a \"default value\" style. That is, if the expression returns\nan error, we use the default value instead. Otherwise, we use the valid value returned\nby the expression.\n\nThe Zig official language reference, provides a great example of this \"default value\"\nstrategy with `catch`. This example is reproduced below. Notice that we are trying to parse\nsome unsigned integer from a string object named `str`. In other words, this function\nis trying to transform an object of type `[]const u8` (i.e., an array of characters, a string, etc.)\ninto an object of type `u64`.\n\nBut this parsing process done by the function `parseU64()` may fail, resulting in a runtime error.\nThe `catch` keyword used in this example provides an alternative value (13) to be used in case\nthis `parseU64()` function raises an error. So, the expression below essentially means:\n\"Hey! Please, parse this string into a `u64` for me, and store the results into the\nobject `number`. But, if an error occurs, then, use the value `13` instead\".\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number = parseU64(str, 10) catch 13;\n```\n:::\n\n\n\n\nSo, at the end of this process, the object `number` will contain either a `u64` integer\nthat was parsed successfully from the input string `str`, or, if an error occurs in the\nparsing process, it will contain the `u64` value `13` that was provided by the `catch`\nkeyword as the \"default\", or, the \"alternative\" value.\n\n\n\n### Using if statements\n\nNow, you can also use if statements to handle errors in your Zig code.\nIn the example below, I'm reproducing the previous example, where\nwe try to parse an integer value from an input string with a function\nnamed `parseU64()`.\n\nWe execute the expression inside the \"if\". If this expression returns an\nerror value, the \"if branch\" (or, the \"true branch\") of the if statement is not executed.\nBut if this expression returns a valid value instead, then, this value is unwrapped\ninto the `number` object.\n\nThis means that, if the `parseU64()` expression returns a valid value, this value becomes available\ninside the scope of this \"if branch\" (i.e., the \"true branch\") through the object that we listed inside the pair\nof pipe character (`|`), which is the object `number`.\n\nIf an error occurs, we can use an \"else branch\" (or the \"false branch\") of the if statement\nto handle the error. In the example below, we are using the `else` in the if statement\nto unwrap the error value (that was returned by `parseU64()`) into the `err` object,\nand handle the error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (parseU64(str, 10)) |number| {\n // do something with `number` here\n} else |err| {\n // handle the error value.\n}\n```\n:::\n\n\n\n\nNow, if the expression that you are executing returns different types of error values,\nand you want to take a different action in each of these types of error values, the\n`try` and `catch` keywords, and the if statement strategy, becomes limited.\n\nFor this type of situation, the official documentation of the language suggests\nthe use of a switch statement together with an if statement [@zigdocs].\nThe basic idea is, to use the if statement to execute the expression, and\nuse the \"else branch\" to pass the error value to a switch statement, where\nyou define a different action for each type of error value that might be\nreturned by the expression executed in the if statement.\n\nThe example below demonstrates this idea. We first try to add (or register) a set of\ntasks to a queue. If this \"registration process\" occurs well, we then try\nto distribute these tasks across the workers of our system. But\nif this \"registration process\" returns an error value, we then use a switch\nstatement in the \"else branch\" to handle each possible error value.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (add_tasks_to_queue(&queue, tasks)) |_| {\n distribute_tasks(&queue);\n} else |err| switch (err) {\n error.InvalidTaskName => {\n // do something\n },\n error.TimeoutTooBig => {\n // do something\n },\n error.QueueNotFound => {\n // do something\n },\n // and all the other error options ...\n}\n```\n:::\n\n\n\n\n\n### The `errdefer` keyword {#sec-errdefer2}\n\nA common pattern in C programs in general, is to clean resources when an error occurs during\nthe execution of the program. In other words, one common way to handle errors, is to perform\n\"cleanup actions\" before we exit our program. This guarantees that a runtime error does not make\nour program to leak resources of the system.\n\n\nThe `errdefer` keyword is a tool to perform such \"cleanup actions\" in hostile situations.\nThis keyword is commonly used to clean (or to free) allocated resources, before the execution of our program\ngets stopped because of an error value being generated.\n\nThe basic idea is to provide an expression to the `errdefer` keyword. Then,\n`errdefer` executes this expression if, and only if, an error occurs\nduring the execution of the current scope.\nIn the example below, we are using an allocator object (that we have presented in @sec-allocators)\nto create a new `User` object. If we are successful in creating and registering this new user,\nthis `create_user()` function will return this new `User` object as its return value.\n\nHowever, if for some reason, an error value is generated by some expression\nthat is after the `errdefer` line, for example, in the `db.add(user)` expression,\nthe expression registered by `errdefer` gets executed before the error value is returned\nfrom the function, and before the program enters in panic mode and stops the\ncurrent execution.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn create_user(db: Database, allocator: Allocator) !User {\n const user = try allocator.create(User);\n errdefer allocator.destroy(user);\n\n // Register new user in the Database.\n _ = try db.register_user(user);\n return user;\n}\n```\n:::\n\n\n\n\nBy using `errdefer` to destroy the `user` object that we have just created,\nwe guarantee that the memory allocated for this `user` object\ngets freed, before the execution of the program stops.\nBecause if the expression `try db.add(user)` returns an error value,\nthe execution of our program stops, and we lose all references and control over the memory\nthat we have allocated for the `user` object.\nAs a result, if we do not free the memory associated with the `user` object before the program stops,\nwe cannot free this memory anymore. We simply lose our chance to do the right thing.\nThat is why `errdefer` is essential in this situation.\n\nJust to state clearly the differences between `defer` and `errdefer`\n(which I described in @sec-defer and @sec-errdefer1), it might be worth\nto discuss the subject a bit further. You might still have the question\n\"why use `errdefer` if we can use `defer` instead?\" in your mind.\n\nAlthough being similar, the key difference between `errdefer` and `defer` keyword\nis when the provided expression gets executed.\nThe `defer` keyword always execute the provided expression at the end of the\ncurrent scope, no matter how your code exits this scope.\nIn contrast, `errdefer` executes the provided expression only when an error occurs in the\ncurrent scope.\n\nThis becomes important if a resource that you allocate in the\ncurrent scope gets freed later in your code, in a different scope.\nThe `create_user()` functions is an example of this. If you think\nclosely about this function, you will notice that this function returns\nthe `user` object as the result.\n\nIn other words, the allocated memory for the `user` object does not get\nfreed inside the `create_user()` function, if it returns successfully.\nSo, if an error does not occur inside this function, the `user` object\nis returned from the function, and probably, the code that runs after\nthis `create_user()` function will be responsible for freeing\nthe memory of the `user` object.\n\nBut what if an error occurs inside the `create_user()` function? What happens then?\nThis would mean that the execution of your code would stop in this `create_user()`\nfunction, and, as a consequence, the code that runs after this `create_user()`\nfunction would simply not run, and, as a result, the memory of the `user` object\nwould not be freed before your program stops.\n\nThis is the perfect scenario for `errdefer`. We use this keyword to guarantee\nthat our program will free the allocated memory for the `user` object,\neven if an error occurs inside the `create_user()` function.\n\nIf you allocate and free some memory for an object inside the same scope, then,\njust use `defer` and be happy, i.e., `errdefer` have no use for you in such situation.\nBut if you allocate some memory in a scope A, but you only free this memory\nlater, in a scope B for example, then, `errdefer` becomes useful to avoid leaking memory\nin sketchy situations.\n\n\n\n## Union type in Zig {#sec-unions}\n\nA union type defines a set of types that an object can be. It's like a list of\noptions. Each option is a type that an object can assume. Therefore, unions in Zig\nhave the same meaning, or, the same role as unions in C. They are used for the same purpose.\nYou could also say that unions in Zig produces a similar effect to\n[using `typing.Union` in Python](https://docs.python.org/3/library/typing.html#typing.Union)[^pyunion].\n\n[^pyunion]: \n\nFor example, you might be creating an API that sends data to a data lake, hosted\nin some private cloud infrastructure. Suppose you have created different structs in your codebase,\nto store the necessary information that you need, in order to connect to the services of\neach mainstream data lake service (Amazon S3, Azure Blob, etc.).\n\nNow, suppose you also have a function named `send_event()` that receives an event as input,\nand, a target data lake, and it sends the input event to the data lake specified in the\ntarget data lake argument. But this target data lake could be any of the three mainstream data lakes\nservices (Amazon S3, Azure Blob, etc.). Here is where an union can help you.\n\nThe union `LakeTarget` defined below allows the `lake_target` argument of `send_event()`\nto be either an object of type `AzureBlob`, or type `AmazonS3`, or type `GoogleGCP`.\nThis union allows the `send_event()` function to receive an object of any of these three types\nas input in the `lake_target` argument.\n\nRemember that each of these three types (`AmazonS3`, `GoogleGCP` and `AzureBlob`)\nare separate structs that we have defined in our source code. So, at first glance,\nthey are separate data types in our source code. But is the `union` keyword that\nunifies them into a single data type called `LakeTarget`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst LakeTarget = union {\n azure: AzureBlob,\n amazon: AmazonS3,\n google: GoogleGCP,\n};\n\nfn send_event(\n event: Event,\n lake_target: LakeTarget\n) bool {\n // body of the function ...\n}\n```\n:::\n\n\n\n\nAn union definition is composed by a list of data members. Each data member is of a specific data type.\nIn the example above, the `LakeTarget` union have three data members (`azure`, `amazon`, `google`).\nWhen you instantiate an object that uses an union type, you can only use one of its data members\nin this instantiation.\n\nYou could also interpret this as: only one data member of an union type can be activated at a time, the other data\nmembers remain deactivated and unaccessible. For example, if you create a `LakeTarget` object that uses\nthe `azure` data member, you can no longer use or access the data members `google` or `amazon`.\nIt's like if these other data members didn't exist at all in the `LakeTarget` type.\n\nYou can see this logic in the example below. Notice that, we first instantiate the union\nobject using the `azure` data member. As a result, this `target` object contains only\nthe `azure` data member inside of it. Only this data member is active in this object.\nThat is why the last line in this code example is invalid. Because we are trying to instantiate the data member\n`google`, which is currently inactive for this `target` object, and as a result, the program\nenters in panic mode warning us about this mistake through a loud error message.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar target = LakeTarget {\n .azure = AzureBlob.init()\n};\n// Only the `azure` data member exist inside\n// the `target` object, and, as a result, this\n// line below is invalid:\ntarget.google = GoogleGCP.init();\n```\n:::\n\n\n\n\n```\nthread 2177312 panic: access of union field 'google' while\n field 'azure' is active:\n target.google = GoogleGCP.init();\n ^\n```\n\nSo, when you instantiate an union object, you must choose one of the data types (or, one of the data members)\nlisted in the union type. In the example above, I choose to use the `azure` data member, and, as a result,\nall other data members were automatically deactivated,\nand you can no longer use them after you instantiate the object.\n\nYou can activate another data member by completely redefining the entire enum object.\nIn the example below, I initially use the `azure` data member. But then, I redefine the\n`target` object to use a new `LakeTarget` object, which uses the `google` data member.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar target = LakeTarget {\n .azure = AzureBlob.init()\n};\ntarget = LakeTarget {\n .google = GoogleGCP.init()\n};\n```\n:::\n\n\n\n\nA curious fact about union types, is that, at first, you cannot use them in switch statements (which were presented in @sec-switch).\nIn other words, if you have an object of type `LakeTarget` for example, you cannot give this object\nas input to a switch statement.\n\nBut what if you really need to do so? What if you actually need to\nprovide an \"union object\" to a switch statement? The answer to this question relies on another special type in Zig,\nwhich are the *tagged unions*. To create a tagged union, all you have to do is to add\nan enum type into your union declaration.\n\nAs an example of a tagged union in Zig, take the `Registry` type exposed\nbelow. This type comes from the\n[`grammar.zig` module](https://github.com/ziglang/zig/blob/30b4a87db711c368853b3eff8e214ab681810ef9/tools/spirv/grammar.zig)[^grammar]\nfrom the Zig repository. This union type lists different types of registries.\nBut notice this time, the use of `(enum)` after the `union` keyword. This is what makes\nthis union type a tagged union. By being a tagged union, an object of this `Registry` type\ncan be used as input in a switch statement. This is all you have to do. Just add `(enum)`\nto your `union` declaration, and you can use it in switch statements.\n\n[^grammar]: .\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Registry = union(enum) {\n core: CoreRegistry,\n extension: ExtensionRegistry,\n};\n```\n:::\n", - "supporting": [ - "09-error-handling_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n# Error handling and unions {#sec-error-handling}\n\nIn this chapter, I want to discuss how error handling is done in Zig.\nWe already briefly learned about one of the available strategies to handle errors in Zig,\nwhich is the `try` keyword presented in @sec-main-file. But we still haven't learned about\nthe other methods, such as the `catch` keyword.\nI also want to discuss in this chapter how union types are created in Zig.\n\n## Learning more about errors in Zig\n\nBefore we get into how error handling is done, we need to learn more about what errors are in Zig.\nAn error is actually a value in Zig [@zigoverview]. In other words, when an error occurs inside your Zig program,\nit means that somewhere in your Zig codebase, an error value is being generated.\nAn error value is similar to any integer value that you create in your Zig code.\nYou can take an error value and pass it as input to a function,\nand you can also cast (or coerce) it into a different type of an error value.\n\nThis have some similarities with exceptions in C++ and Python.\nBecause in C++ and Python, when an exception happens inside a `try` block,\nyou can use a `catch` block (in C++) or an `except` block (in Python)\nto capture the exception produced in the `try` block,\nand pass it to functions as an input.\n\nHowever, error values in Zig are treated very differently than exceptions.\nFirst, you cannot ignore error values in your Zig code. Meaning that, if an error\nvalue appears somewhere in your source code, this error value must be explicitly handled in some way.\nThis also means that you cannot discard error values by assigning them to an underscore,\nas you could do with normal values and objects.\n\nTake the source code below as an example. Here we are trying to open a file that does not exist\nin my computer, and as a result, an obvious error value of `FileNotFound` is returned from the `openFile()`\nfunction. But because I'm assigning the result of this function to an underscore, I end up\ntrying to discard an error value.\n\nThe `zig` compiler detects this mistake, and raises a compile\nerror telling me that I'm trying to discard an error value.\nIt also adds a note message that suggests the use of `try`,\n`catch` or an if statement to explicitly handle this error value\nThis note is reinforcing that every possible error value must be explicitly handled in Zig.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst dir = std.fs.cwd();\n_ = dir.openFile(\"doesnt_exist.txt\", .{});\n```\n:::\n\n\n```\nt.zig:8:17: error: error set is discarded\nt.zig:8:17: note: consider using 'try', 'catch', or 'if'\n```\n\n\n### Returning errors from functions\n\nAs we described in @sec-main-file, when we have a function that might return an error\nvalue, this function normally includes an exclamation mark (`!`) in its return type\nannotation. The presence of this exclamation mark indicates that this function might\nreturn an error value as result, and, the `zig` compiler forces you to always handle explicitly\nthe case of this function returning an error value.\n\nTake a look at the `print_name()` function below. This function might return an error in the `stdout.print()` function call,\nand, as a consequence, its return type (`!void`) includes an exclamation mark in it.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_name() !void {\n const stdout = std.getStdOut().writer();\n try stdout.print(\"My name is Pedro!\", .{});\n}\n```\n:::\n\n\nIn the example above, we are using the exclamation mark to tell the `zig` compiler\nthat this function might return some error. But which error exactly is returned from\nthis function? For now, we are not specifying a specific error value. For now,\nwe only know that some error value (whatever it is) might be returned.\n\nBut in fact, you can (if you want to) specify clearly which exact error values\nmight be returned from this function. There are lot of examples of\nthis in the Zig Standard Library. Take this `fill()` function from\nthe `http.Client` module as an example. This function returns\neither a error value of type `ReadError`, or `void`.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn fill(conn: *Connection) ReadError!void {\n // The body of this function ...\n}\n```\n:::\n\n\nThis idea of specifying the exact error values that you expect to be returned\nfrom the function is interesting. Because they automatically become some sort of documentation\nof your function, and also, this allows the `zig` compiler to perform some extra checks over\nyour code. Because the compiler can check if there is any other type of error value\nthat is being generated inside your function, and, that it's not being accounted\nfor in this return type annotation.\n\nAnyway, you can list the types of errors that can be returned from the function\nby listing them on the left side of the exclamation mark. While the valid values\nstay on the right side of the exclamation mark. So the syntax format become:\n\n```\n!\n```\n\n\n### Error sets\n\nBut what about when we have a single function that might return different types of errors?\nWhen you have such a function, you can list\nall of these different types of errors that can be returned from this function,\nthrough a structure in Zig that we call of an *error set*.\n\nAn error set is a special case of a union type. It's a union that contains error values in it.\nNot all programming languages have a notion of a \"union object\".\nBut in summary, a union is just a set of data types.\nUnions are used to allow an object to have multiple data types.\nFor example, a union of `x`, `y` and `z`, means that\nan object can be either of type `x`, or type `y` or type `z`.\n\nWe are going to talk in more depth about unions in @sec-unions.\nBut you can write an error set by writing the keyword `error` before\na pair of curly braces, then you list the error values that can be\nreturned from the function inside this pair of curly braces.\n\nTake the `resolvePath()` function below as an example, which comes from the\n`introspect.zig` module of the Zig Standard Library. We can see in its return type annotation, that this\nfunction return either: 1) a valid slice of `u8` values (`[]u8`); or, 2) one of the three different\ntypes of error values listed inside the error set (`OutOfMemory`, `Unexpected`, etc.).\nThis is an usage example of an error set.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn resolvePath(\n ally: mem.Allocator,\n p: []const u8,\n) error{\n OutOfMemory,\n CurrentWorkingDirectoryUnlinked,\n Unexpected,\n}![]u8 {\n // The body of the function ...\n}\n```\n:::\n\n\n\nThis is a valid way of annotating the return value of a Zig function. But, if you navigate through\nthe modules that composes the Zig Standard Library, you will notice that, for the majority of cases,\nthe programmers prefer to give a descriptive name to this error set, and then, use this name (or this \"label\")\nof the error set in the return type annotation, instead of using the error set directly.\n\nWe can see that in the `ReadError` error set that we showed earlier in the `fill()` function,\nwhich is defined in the `http.Client` module.\nSo yes, I presented the `ReadError` as if it was just a standard and single error value, but in fact,\nit's an error set defined in the `http.Client` module, and therefore, it actually represents\na set of different error values that might happen inside the `fill()` function.\n\n\nTake a look at the `ReadError` definition reproduced below. Notice that we are grouping all of these\ndifferent error values into a single object, and then, we use this object into the return type annotation of the function.\nLike the `fill()` function that we showed earlier, or, the `readvDirect()` function from the same module,\nwhich is reproduced below.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const ReadError = error{\n TlsFailure,\n TlsAlert,\n ConnectionTimedOut,\n ConnectionResetByPeer,\n UnexpectedReadFailure,\n EndOfStream,\n};\n// Some lines of code\npub fn readvDirect(\n conn: *Connection,\n buffers: []std.posix.iovec\n ) ReadError!usize {\n // The body of the function ...\n}\n```\n:::\n\n\nSo, an error set is just a convenient way of grouping a set of\npossible error values into a single object, or a single type of an error value.\n\n\n### Casting error values\n\nLet's suppose you have two different error sets, named `A` and `B`.\nIf error set `A` is a superset of error set `B`, then, you can cast (or coerce)\nerror values from `B` into error values of `A`.\n\nError sets are just a set of error values. So, if the error set `A`\ncontains all error values from the error set `B`, then `A`\nbecomes a superset of `B`. You could also say\nthat the error set `B` is a subset of error set `A`.\n\nThe example below demonstrates this idea. Because `A` contains all\nvalues from `B`, `A` is a superset of `B`.\nIn math notation, we would say that $A \\supset B$.\nAs a consequence, we can give an error value from `B` as input to the `cast()`\nfunction, and, implicitly cast this input into the same error value, but from the `A` set.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst A = error{\n ConnectionTimeoutError,\n DatabaseNotFound,\n OutOfMemory,\n InvalidToken,\n};\nconst B = error {\n OutOfMemory,\n};\n\nfn cast(err: B) A {\n return err;\n}\n\ntest \"coerce error value\" {\n const error_value = cast(B.OutOfMemory);\n try std.testing.expect(\n error_value == A.OutOfMemory\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file1f7f62fdbe33.test.coerce error value...OKA\n All 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n## How to handle errors\n\nNow that we learned more about what errors are in Zig,\nlet's discuss the available strategies to handle these errors,\nwhich are:\n\n- `try` keyword;\n- `catch` keyword;\n- an if statement;\n- `errdefer` keyword;\n\n\n\n### What `try` means?\n\nAs I described over the previous sections, when we say that an expression might\nreturn an error, we are basically referring to an expression that have\na return type in the format `!T`.\nThe `!` indicates that this expression returns either an error value, or a value of type `T`.\n\nIn @sec-main-file, I presented the `try` keyword and where to use it.\nBut I did not talked about what exactly this keyword does to your code,\nor, in other words, I have not explained yet what `try` means in your code.\n\nIn essence, when you use the `try` keyword in an expression, you are telling\nthe `zig` compiler the following: \"Hey! Execute this expression for me,\nand, if this expression return an error, please, return this error for me\nand stop the execution of my program. But if this expression return a valid\nvalue, then, return this value, and move on\".\n\nIn other words, the `try` keyword is essentially, a strategy to enter in panic mode, and stop\nthe execution of your program in case an error occurs.\nWith the `try` keyword, you are telling the `zig` compiler, that stopping the execution\nof your program is the most reasonable strategy to take if an error occurs\nin that particular expression.\n\n### The `catch` keyword\n\nOk, now that we understand properly what `try` means, let's discuss `catch` now.\nOne important detail here, is that you can use `try` or `catch` to handle your errors,\nbut you **cannot use `try` and `catch` together**. In other words, `try` and `catch`\nare different and completely separate strategies in the Zig language.\n\nThis is uncommon, and different than what happens in other languages. Most\nprogramming languages that adopts the *try catch* pattern (such as C++, R, Python, Javascript, etc.), normally use\nthese two keywords together to form the complete logic to\nproperly handle the errors.\nAnyway, Zig tries a different approach in the *try catch* pattern.\n\nSo, we learned already about what `try` means, and we also known that both\n`try` and `catch` should be used alone, separate from each other. But\nwhat exactly `catch` do in Zig? With `catch`, we can construct a block of\nlogic to handle the error value, in case it happens in the current expression.\n\nLook at the code example below. Once again, we go back to the previous\nexample where we were trying to open a file that doesn't exist in my computer,\nbut this time, I use `catch` to actually implement a logic to handle the error, instead of\njust stopping the execution right away.\n\nMore specifically, in this example, I'm using a logger object to record some logs into\nthe system, before I return the error, and stop the execution of the program. For example,\nthis could be some part of the codebase of a complex system that I do not have full control over,\nand I want to record these logs before the program crashes, so that I can debug it later\n(e.g. maybe I cannot compile the full program, and properly debug it with a debugger. So, these logs might\nbe a valid strategy to surpass this barrier).\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst dir = std.fs.cwd();\nconst file = dir.openFile(\n \"doesnt_exist.txt\", .{}\n) catch |err| {\n logger.record_context();\n logger.log_error(err);\n return err;\n};\n```\n:::\n\n\n\nTherefore, we use `catch` to create a block of expressions that will handle the error.\nI can return the error value from this block of expressions, like I did in the above example,\nwhich, will make the program enter in panic mode, and, stop the execution.\nBut I could also, return a valid value from this block of code, which would\nbe stored in the `file` object.\n\nNotice that, instead of writing the keyword before the expression that might return the error,\nlike we do with `try`, we write `catch` after the expression. We can open the pair of pipes (`|`),\nwhich captures the error value returned by the expression, and makes\nthis error value available in the scope of the `catch` block as the object named `err`.\nIn other words, because I wrote `|err|` in the code, I can access the error value\nreturned by the expression, by using the `err` object.\n\nAlthough this being the most common use of `catch`, you can also use this keyword\nto handle the error in a \"default value\" style. That is, if the expression returns\nan error, we use the default value instead. Otherwise, we use the valid value returned\nby the expression.\n\nThe Zig official language reference, provides a great example of this \"default value\"\nstrategy with `catch`. This example is reproduced below. Notice that we are trying to parse\nsome unsigned integer from a string object named `str`. In other words, this function\nis trying to transform an object of type `[]const u8` (i.e., an array of characters, a string, etc.)\ninto an object of type `u64`.\n\nBut this parsing process done by the function `parseU64()` may fail, resulting in a runtime error.\nThe `catch` keyword used in this example provides an alternative value (13) to be used in case\nthis `parseU64()` function raises an error. So, the expression below essentially means:\n\"Hey! Please, parse this string into a `u64` for me, and store the results into the\nobject `number`. But, if an error occurs, then, use the value `13` instead\".\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst number = parseU64(str, 10) catch 13;\n```\n:::\n\n\nSo, at the end of this process, the object `number` will contain either a `u64` integer\nthat was parsed successfully from the input string `str`, or, if an error occurs in the\nparsing process, it will contain the `u64` value `13` that was provided by the `catch`\nkeyword as the \"default\", or, the \"alternative\" value.\n\n\n\n### Using if statements\n\nNow, you can also use if statements to handle errors in your Zig code.\nIn the example below, I'm reproducing the previous example, where\nwe try to parse an integer value from an input string with a function\nnamed `parseU64()`.\n\nWe execute the expression inside the \"if\". If this expression returns an\nerror value, the \"if branch\" (or, the \"true branch\") of the if statement is not executed.\nBut if this expression returns a valid value instead, then, this value is unwrapped\ninto the `number` object.\n\nThis means that, if the `parseU64()` expression returns a valid value, this value becomes available\ninside the scope of this \"if branch\" (i.e., the \"true branch\") through the object that we listed inside the pair\nof pipe character (`|`), which is the object `number`.\n\nIf an error occurs, we can use an \"else branch\" (or the \"false branch\") of the if statement\nto handle the error. In the example below, we are using the `else` in the if statement\nto unwrap the error value (that was returned by `parseU64()`) into the `err` object,\nand handle the error.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (parseU64(str, 10)) |number| {\n // do something with `number` here\n} else |err| {\n // handle the error value.\n}\n```\n:::\n\n\nNow, if the expression that you are executing returns different types of error values,\nand you want to take a different action in each of these types of error values, the\n`try` and `catch` keywords, and the if statement strategy, becomes limited.\n\nFor this type of situation, the official documentation of the language suggests\nthe use of a switch statement together with an if statement [@zigdocs].\nThe basic idea is, to use the if statement to execute the expression, and\nuse the \"else branch\" to pass the error value to a switch statement, where\nyou define a different action for each type of error value that might be\nreturned by the expression executed in the if statement.\n\nThe example below demonstrates this idea. We first try to add (or register) a set of\ntasks to a queue. If this \"registration process\" occurs well, we then try\nto distribute these tasks across the workers of our system. But\nif this \"registration process\" returns an error value, we then use a switch\nstatement in the \"else branch\" to handle each possible error value.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (add_tasks_to_queue(&queue, tasks)) |_| {\n distribute_tasks(&queue);\n} else |err| switch (err) {\n error.InvalidTaskName => {\n // do something\n },\n error.TimeoutTooBig => {\n // do something\n },\n error.QueueNotFound => {\n // do something\n },\n // and all the other error options ...\n}\n```\n:::\n\n\n\n### The `errdefer` keyword {#sec-errdefer2}\n\nA common pattern in C programs in general, is to clean resources when an error occurs during\nthe execution of the program. In other words, one common way to handle errors, is to perform\n\"cleanup actions\" before we exit our program. This guarantees that a runtime error does not make\nour program to leak resources of the system.\n\n\nThe `errdefer` keyword is a tool to perform such \"cleanup actions\" in hostile situations.\nThis keyword is commonly used to clean (or to free) allocated resources, before the execution of our program\ngets stopped because of an error value being generated.\n\nThe basic idea is to provide an expression to the `errdefer` keyword. Then,\n`errdefer` executes this expression if, and only if, an error occurs\nduring the execution of the current scope.\nIn the example below, we are using an allocator object (that we have presented in @sec-allocators)\nto create a new `User` object. If we are successful in creating and registering this new user,\nthis `create_user()` function will return this new `User` object as its return value.\n\nHowever, if for some reason, an error value is generated by some expression\nthat is after the `errdefer` line, for example, in the `db.add(user)` expression,\nthe expression registered by `errdefer` gets executed before the error value is returned\nfrom the function, and before the program enters in panic mode and stops the\ncurrent execution.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn create_user(db: Database, allocator: Allocator) !User {\n const user = try allocator.create(User);\n errdefer allocator.destroy(user);\n\n // Register new user in the Database.\n _ = try db.register_user(user);\n return user;\n}\n```\n:::\n\n\nBy using `errdefer` to destroy the `user` object that we have just created,\nwe guarantee that the memory allocated for this `user` object\ngets freed, before the execution of the program stops.\nBecause if the expression `try db.add(user)` returns an error value,\nthe execution of our program stops, and we lose all references and control over the memory\nthat we have allocated for the `user` object.\nAs a result, if we do not free the memory associated with the `user` object before the program stops,\nwe cannot free this memory anymore. We simply lose our chance to do the right thing.\nThat is why `errdefer` is essential in this situation.\n\nJust to state clearly the differences between `defer` and `errdefer`\n(which I described in @sec-defer and @sec-errdefer1), it might be worth\nto discuss the subject a bit further. You might still have the question\n\"why use `errdefer` if we can use `defer` instead?\" in your mind.\n\nAlthough being similar, the key difference between `errdefer` and `defer` keyword\nis when the provided expression gets executed.\nThe `defer` keyword always execute the provided expression at the end of the\ncurrent scope, no matter how your code exits this scope.\nIn contrast, `errdefer` executes the provided expression only when an error occurs in the\ncurrent scope.\n\nThis becomes important if a resource that you allocate in the\ncurrent scope gets freed later in your code, in a different scope.\nThe `create_user()` functions is an example of this. If you think\nclosely about this function, you will notice that this function returns\nthe `user` object as the result.\n\nIn other words, the allocated memory for the `user` object does not get\nfreed inside the `create_user()` function, if it returns successfully.\nSo, if an error does not occur inside this function, the `user` object\nis returned from the function, and probably, the code that runs after\nthis `create_user()` function will be responsible for freeing\nthe memory of the `user` object.\n\nBut what if an error occurs inside the `create_user()` function? What happens then?\nThis would mean that the execution of your code would stop in this `create_user()`\nfunction, and, as a consequence, the code that runs after this `create_user()`\nfunction would simply not run, and, as a result, the memory of the `user` object\nwould not be freed before your program stops.\n\nThis is the perfect scenario for `errdefer`. We use this keyword to guarantee\nthat our program will free the allocated memory for the `user` object,\neven if an error occurs inside the `create_user()` function.\n\nIf you allocate and free some memory for an object inside the same scope, then,\njust use `defer` and be happy, i.e., `errdefer` have no use for you in such situation.\nBut if you allocate some memory in a scope A, but you only free this memory\nlater, in a scope B for example, then, `errdefer` becomes useful to avoid leaking memory\nin sketchy situations.\n\n\n\n## Union type in Zig {#sec-unions}\n\nA union type defines a set of types that an object can be. It's like a list of\noptions. Each option is a type that an object can assume. Therefore, unions in Zig\nhave the same meaning, or, the same role as unions in C. They are used for the same purpose.\nYou could also say that unions in Zig produces a similar effect to\n[using `typing.Union` in Python](https://docs.python.org/3/library/typing.html#typing.Union)[^pyunion].\n\n[^pyunion]: \n\nFor example, you might be creating an API that sends data to a data lake, hosted\nin some private cloud infrastructure. Suppose you have created different structs in your codebase,\nto store the necessary information that you need, in order to connect to the services of\neach mainstream data lake service (Amazon S3, Azure Blob, etc.).\n\nNow, suppose you also have a function named `send_event()` that receives an event as input,\nand, a target data lake, and it sends the input event to the data lake specified in the\ntarget data lake argument. But this target data lake could be any of the three mainstream data lakes\nservices (Amazon S3, Azure Blob, etc.). Here is where an union can help you.\n\nThe union `LakeTarget` defined below allows the `lake_target` argument of `send_event()`\nto be either an object of type `AzureBlob`, or type `AmazonS3`, or type `GoogleGCP`.\nThis union allows the `send_event()` function to receive an object of any of these three types\nas input in the `lake_target` argument.\n\nRemember that each of these three types (`AmazonS3`, `GoogleGCP` and `AzureBlob`)\nare separate structs that we have defined in our source code. So, at first glance,\nthey are separate data types in our source code. But is the `union` keyword that\nunifies them into a single data type called `LakeTarget`.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst LakeTarget = union {\n azure: AzureBlob,\n amazon: AmazonS3,\n google: GoogleGCP,\n};\n\nfn send_event(\n event: Event,\n lake_target: LakeTarget\n) bool {\n // body of the function ...\n}\n```\n:::\n\n\nAn union definition is composed by a list of data members. Each data member is of a specific data type.\nIn the example above, the `LakeTarget` union have three data members (`azure`, `amazon`, `google`).\nWhen you instantiate an object that uses an union type, you can only use one of its data members\nin this instantiation.\n\nYou could also interpret this as: only one data member of an union type can be activated at a time, the other data\nmembers remain deactivated and unaccessible. For example, if you create a `LakeTarget` object that uses\nthe `azure` data member, you can no longer use or access the data members `google` or `amazon`.\nIt's like if these other data members didn't exist at all in the `LakeTarget` type.\n\nYou can see this logic in the example below. Notice that, we first instantiate the union\nobject using the `azure` data member. As a result, this `target` object contains only\nthe `azure` data member inside of it. Only this data member is active in this object.\nThat is why the last line in this code example is invalid. Because we are trying to instantiate the data member\n`google`, which is currently inactive for this `target` object, and as a result, the program\nenters in panic mode warning us about this mistake through a loud error message.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar target = LakeTarget {\n .azure = AzureBlob.init()\n};\n// Only the `azure` data member exist inside\n// the `target` object, and, as a result, this\n// line below is invalid:\ntarget.google = GoogleGCP.init();\n```\n:::\n\n\n```\nthread 2177312 panic: access of union field 'google' while\n field 'azure' is active:\n target.google = GoogleGCP.init();\n ^\n```\n\nSo, when you instantiate an union object, you must choose one of the data types (or, one of the data members)\nlisted in the union type. In the example above, I choose to use the `azure` data member, and, as a result,\nall other data members were automatically deactivated,\nand you can no longer use them after you instantiate the object.\n\nYou can activate another data member by completely redefining the entire enum object.\nIn the example below, I initially use the `azure` data member. But then, I redefine the\n`target` object to use a new `LakeTarget` object, which uses the `google` data member.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar target = LakeTarget {\n .azure = AzureBlob.init()\n};\ntarget = LakeTarget {\n .google = GoogleGCP.init()\n};\n```\n:::\n\n\nA curious fact about union types, is that, at first, you cannot use them in switch statements (which were presented in @sec-switch).\nIn other words, if you have an object of type `LakeTarget` for example, you cannot give this object\nas input to a switch statement.\n\nBut what if you really need to do so? What if you actually need to\nprovide an \"union object\" to a switch statement? The answer to this question relies on another special type in Zig,\nwhich are the *tagged unions*. To create a tagged union, all you have to do is to add\nan enum type into your union declaration.\n\nAs an example of a tagged union in Zig, take the `Registry` type exposed\nbelow. This type comes from the\n[`grammar.zig` module](https://github.com/ziglang/zig/blob/30b4a87db711c368853b3eff8e214ab681810ef9/tools/spirv/grammar.zig)[^grammar]\nfrom the Zig repository. This union type lists different types of registries.\nBut notice this time, the use of `(enum)` after the `union` keyword. This is what makes\nthis union type a tagged union. By being a tagged union, an object of this `Registry` type\ncan be used as input in a switch statement. This is all you have to do. Just add `(enum)`\nto your `union` declaration, and you can use it in switch statements.\n\n[^grammar]: .\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub const Registry = union(enum) {\n core: CoreRegistry,\n extension: ExtensionRegistry,\n};\n```\n:::\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/10-stack-project/execute-results/epub.json b/_freeze/Chapters/10-stack-project/execute-results/epub.json deleted file mode 100644 index 8c071b38..00000000 --- a/_freeze/Chapters/10-stack-project/execute-results/epub.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "hash": "801c378f39cbcf646c40a137880aa3b8", - "result": { - "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n# Project 3 - Building a stack data structure\n\nIn this chapter we are going to implement a stack data structure as our next small project\nin this book. Implementing basic data structures in any language is kind of a\n\"kindergarten task\" (if this term even exist) in computer science (CS), because\nwe normally learn and implement them in the first semesters of CS.\n\nBut this is actually good! Since this should be a very easy task, we don't need much to explain\nwhat a stack is, then, we can concentrate on what is really important here, which is learning\nhow the concept of \"generics\" is implemented in the Zig language, and how one of the key\nfeatures of Zig, which is comptime, works, and use the stack data structure to demonstrate\nthese concepts on the fly.\n\nBut before we get into building the stack data structure, we first need to understand\nwhat the `comptime` keyword does to your code, and after that, we also need to learn about\nhow generics work in Zig.\n\n\n## Understanding `comptime` in Zig {#sec-comptime}\n\nOne of the key features of Zig is `comptime`. This keyword introduces a whole\nnew concept and paradigm, that is tightly connected with the compilation process.\nIn @sec-compile-time we have described the importance and the role that \"compile-time versus runtime\"\nplays into Zig. In that section, we learned that the rules applied to a value/object change\na lot depending on whether this value is known at compile-time, or just at runtime.\n\nThe `comptime` keyword is strongly related to these two spaces in time (compile-time and runtime).\nLet's quickly recap the differences. Compile-time is the period of time when your\nZig source code is being compiled by the `zig` compiler, while the runtime is\nthe period of time when your Zig program is being executed, i.e., when we execute\nthe binary files that were generated by the `zig` compiler.\n\nThere are three ways in which you can apply the `comptime` keyword, which are:\n\n- apply `comptime` on a function argument.\n- apply `comptime` on an object.\n- apply `comptime` on a block of expressions.\n\n\n\n### Applying over a function argument\n\nWhen you apply the `comptime` keyword on a function argument, you are saying to the `zig` compiler\nthat the value assigned to that particular function argument must be known at compile-time.\nWe explained in detail in @sec-compile-time what exactly \"value known at compile-time\" means. So\nif you have any doubts about this idea, refer back to that section.\n\nNow let's think about the consequences of this idea. First of all, we are imposing a limit, or, a requirement\nto that particular function argument. If the programmer accidentally tries to give a value to this\nfunction argument that is not known at compile time, the `zig` compiler will notice this problem, and\nas a consequence, it will raise a compilation error saying that it cannot compile your program. Because\nyou are providing a value that is \"runtime known\" to a function argument that must be \"compile-time known\".\n\nTake a look at this very simple example below, where we define a `twice()` function, that simply\ndoubles the input value named `num`. Notice that we use the `comptime` keyword before the name\nof the function argument. This keyword is marking the function argument `num` as a \"comptime argument\".\n\nThat is a function argument whose value must be compile-time known. This is why the expression\n`twice(5678)` is valid, and no compilation errors are raised. Because the value `5678`\nis compile-time known, so this is the expected behaviour for this function.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\ntest \"test comptime\" {\n _ = twice(5678);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3f5922d93418.test.test comptime...OKAll 1 \n tests passed.\n```\n\n\n:::\n:::\n\n\n\nBut what if we provide a number that is not compile-time known to this function?\nFor example, your program might receive some input from the user through the `stdin`\nchannel of your system. This input from the user might be many different things,\nand cannot be predicted at compile-time. These circumstances make this \"input\nfrom the user\" a value that is runtime-known only.\n\nIn the example below, this \"input from the user\" is initially received as a string,\nwhich is then parsed and transformed into a integer value, and the result of this operation\nis stored inside the `n` object.\n\nBecause the \"input of the user\" is known only at runtime, the value of the object `n` is determined only at runtime.\nAs consequence, we cannot provide this object as input to the `twice()` function.\nThe `zig` compiler will not allow it, because we marked\nthe `num` argument as a \"comptime argument\". That is why the `zig` compiler raises\nthe compile-time error exposed below:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\n\npub fn main() !void {\n var buffer: [5]u8 = .{ 0, 0, 0, 0, 0 };\n const stdout = std.io.getStdOut().writer();\n const stdin = std.io.getStdIn().reader();\n _ = try stdout.write(\"Please write a 4-digit integer number\\n\");\n _ = try stdin.readUntilDelimiter(&buffer, '\\n');\n\n try stdout.print(\"Input: {s}\", .{buffer});\n const n: u32 = try std.fmt.parseInt(\n u32, buffer[0 .. buffer.len - 1], 10\n );\n const twice_result = twice(n);\n try stdout.print(\"Result: {d}\\n\", .{twice_result});\n}\n```\n:::\n\n\n\n```\nt.zig:12:16: error: unable to resolve comptime value\n const twice_result = twice(n);\n ^\n```\n\nComptime arguments are frequently used on functions that return some sort\nof generic structure. In fact, `comptime` is the essence (or the basis) to make generics in Zig.\nWe are going to talk more about generics in @sec-generics.\n\nFor now, let's take a look at this code example from @karlseguin_generics. You\ncan see that this `IntArray()` function has one argument named `length`.\nThis argument is marked as comptime, and receives a value of type `usize` as input. So the value given to this argument\nmust be compile-time known.\nWe can also see that this function returns an array of `i64` values as output.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn IntArray(comptime length: usize) type {\n return [length]i64;\n}\n```\n:::\n\n\n\nNow, the key component of this function is the `length` argument. This argument\nis used to determine the size of the array that is produced by the function. Let's\nthink about the consequences of that. If the size of the array is dependent on\nthe value assigned to the `length` argument, this means that the data type of the\noutput of the function depends on the value of this `length` argument.\n\nLet this statement sink for a bit in your mind. As I described in @sec-root-file,\nZig is a strongly-typed language, especially on function declarations.\nSo every time we write a function in Zig, we have to annotate the data type of\nthe value returned by the function. But how can we do that, if this data type\ndepends on the value given to the argument of the function?\n\nThink about this for a second. If `length` is equal to 3 for example, then, the\nreturn type of the function is `[3]i64`. But if `length` is equal to 40, then,\nthe return type becomes `[40]i64`. At this point the `zig` compiler would be confused,\nand raise a compilation error, saying something like this:\n\n> Hey! You have annotated that this function should return a `[3]i64` value, but I got a `[40]i64` value instead! This doesn't look right!\n\nSo how can you solve this problem? How do we overcome this barrier? This is when\nthe `type` keyword comes in. This `type` keyword is basically saying to the\n`zig` compiler that this function will return some data type as output, but it doesn't know yet\nwhat exactly data type that is. We will talk more about this in @sec-generics.\n\n\n\n### Applying over an expression\n\nWhen you apply the `comptime` keyword over an expression, then, it is guaranteed that the `zig` compiler will\nexecute this expression at compile-time. If for some reason, this expression cannot be executed at compile-time\n(e.g. for example, maybe this expression depends on a value that is only known at runtime), then, the `zig` compiler\nwill raise a compilation error.\n\nTake this example from the official documentation of Zig [@zigdocs]. We\nare executing the same `fibonacci()` function both at runtime, and, at compile-time.\nThe function is executed by default at runtime, but because we use the `comptime`\nkeyword in the second \"try expression\", this expression is executed at compile-time.\n\nThis might be a bit confusing for some people. Yes! When I say that this expression\nis executed at compile-time, I mean that this expression is compiled and executed\nwhile the `zig` compiler is compiling your Zig source code.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci\" {\n // test fibonacci at run-time\n try expect(fibonacci(7) == 13);\n // test fibonacci at compile-time\n try comptime expect(fibonacci(7) == 13);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3f596129a9ee.test.fibonacci...OKAll 1 test\n ts passed.\n```\n\n\n:::\n:::\n\n\n\nA lot of your Zig source code might be potentially executed at compile-time,\nbecause the `zig` compiler can figure out the output of some expressions.\nEspecially if these expressions depend only on compile-time known values.\nWe have talked about this in @sec-compile-time.\n\nBut when you use the `comptime` keyword on an expression, there is no \"it might be executed\nat compile-time\" anymore. With the `comptime` keyword you are ordering the `zig` compiler\nto execute this expression at compile-time. You are imposing this rule, it is guaranteed\nthat the compiler will always execute it at compile-time. Or, at least, the compiler\nwill try to execute it. If the compiler cannot execute the expression for whatever reason,\nthe compiler will raise a compilation error.\n\n\n### Applying over a block\n\nBlocks were described in @sec-blocks. When you apply the `comptime` keyword to a\nblock of expressions, you get essentially the same effect as when you apply this keyword to\na single expression. That is, the entire block of expressions is executed at\ncompile-time by the `zig` compiler.\n\nIn the example below, we mark the block labeled of `blk` as a comptime block,\nand, therefore, the expressions inside this block are executed at compile-time.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci in a block\" {\n const x = comptime blk: {\n const n1 = 5;\n const n2 = 2;\n const n3 = n1 + n2;\n try expect(fibonacci(n3) == 13);\n break :blk n3;\n };\n _ = x;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file3f5947d42e1f.test.fibonacci in a block...O\n OKAll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## Introducing Generics {#sec-generics}\n\nFirst of all, what is a generic? Generic is the idea to allow a type\n(`f64`, `u8`, `u32`, `bool`, and also, user-defined types, like the `User` struct\nthat we defined in @sec-structs-and-oop) to be a parameter to methods, classes and\ninterfaces [@geeks_generics]. In other words, a \"generic\" is a class (or a method) that can work\nwith multiple data types.\n\nFor example, in Java, generics are created through the operator `<>`. With this operator,\na Java class is capable of receiving a data type as input, and therefore, the class can fit\nits features according to this input data type.\nAs another example, generics in C++ are supported through the concept of templates.\nClass templates in C++ are generics.\n\nIn Zig, generics are implemented through `comptime`. The `comptime` keyword\nallows us to collect a data type at compile time, and pass this data type as\ninput to a piece of code.\n\n\n### A generic function {#sec-generic-fun}\n\nTake the `max()` function exposed below as a first example.\nThis function is essentially a \"generic function\".\nIn this function, we have a comptime function argument named `T`.\nNotice that this `T` argument has a data type of `type`. Weird right? This `type` keyword is the\n\"father of all types\", or, \"the type of types\" in Zig.\n\nBecause we have used this `type` keyword in the `T` argument, we are telling\nthe `zig` compiler that this `T` argument will receive some data type as input.\nAlso notice the use of the `comptime` keyword in this argument.\nAs I described in @sec-comptime, every time you use this keyword in a function argument,\nthis means that the value of this argument must be known at compile-time.\nThis makes sense, right? Because there is no data type that is not known at compile-time.\n\nThink about this. Every data type that you will ever write is always\nknown at compile-time. Especially because data types are an essential\ninformation for the compiler to actually compile your source code.\nHaving this in mind, makes sense to mark this argument as a comptime argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn max(comptime T: type, a: T, b: T) T {\n return if (a > b) a else b;\n}\n```\n:::\n\n\n\nAlso notice that the value of the `T` argument is actually used\nto define the data type of the other arguments in the function, `a` and `b`, and also at the\nreturn type annotation of the function.\nThat is, the data type of these arguments (`a` and `b`), and, the return data type of the function itself,\nare determined by the input value given to the `T` argument.\n\nAs a result, we have a generic function that works with different data types.\nFor example, I can provide `u8` values to this `max()` function, and it will work as expected.\nBut if I provide `f64` values instead, it will also work as expected.\nWithout a generic function, I would have to write a different `max()` function\nfor each data type I wanted to use.\nThis generic function provides a very useful shortcut for us.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn max(comptime T: type, a: T, b: T) T {\n return if (a > b) a else b;\n}\ntest \"test max\" {\n const n1 = max(u8, 4, 10);\n std.debug.print(\"Max n1: {d}\\n\", .{n1});\n const n2 = max(f64, 89.24, 64.001);\n std.debug.print(\"Max n2: {d}\\n\", .{n2});\n}\n```\n:::\n\n\n\n```\nMax n1: 10\nMax n2: 89.24\n```\n\n\n### A generic data structure {#sec-generic-struct}\n\nEvery data structure that you find in the Zig Standard Library (e.g. `ArrayList`, `HashMap`, etc.)\nis essentially a generic data structure.\nThese data structures are generic in the sense that they work with any data type you want.\nYou just say which is the data type of the values that are going to be stored in this data\nstructure, and they just work as expected.\n\nA generic data structure in Zig is how you replicate a generic class from Java,\nor, a class template from C++. But you may ask yourself: how do we build a\ngeneric data structure in Zig?\n\nThe basic idea is to write a generic function that creates the data structure definition\nfor the specific type we want. In other words, this generic function behaves as a \"factory of data structures\".\nThe generic function outputs the `struct` definition that defines this data structure for a\nspecific data type.\n\nTo create such function, we need to add a comptime argument to this function that receives a data type\nas input. We already learned how to do this in the previous section (@sec-generic-fun).\nI think the best way to demonstrate how to create a generic data structure is to actually write one.\nThis where we go into our next small project in this book. This one is a very small project,\nwhich is to write a generic stack data structure.\n\n\n\n\n## What is a stack? {#sec-what-stack}\n\nA stack data structure is a structure that follows a LIFO (*last in, first out*) principle.\nOnly two operations are normally supported in a stack data structure, which are `push` and `pop`.\nThe `push` operation is used to add new values to the stack, while `pop` is used to remove\nvalues from the stack.\n\nWhen people try to explain how the stack data structure works, the most common analogy\nthat they use is a stack of plates. Imagine that you have a stack of plates,\nfor example, a stack of 10 plates in your table. Each plate represents a value that\nis currently stored in this stack.\n\nWe begin with a stack of 10 different values, or 10 different plates. Now, imagine that you want to\nadd a new plate (or a new value) to this stack, which translates to the `push` operation.\nYou would add this plate (or this value) by just putting the new plate\non the top of the stack. Then, you would increase the stack to 11 plates.\n\nBut how would you remove plates (or remove values) from this stack (a.k.a. the `pop` operation) ?\nTo do that, we would have to remove the plate on the top of the stack, and, as a result, we would\nhave, once again, 10 plates in the stack.\n\nThis demonstrates the LIFO concept, because the first plate in the stack, which is the plate\nin the bottom of the stack, is always the last plate to get out of the stack. Think about it. In order\nto remove this specific plate from the stack, we have to remove all plates in the\nstack. So every operation in the stack, either insertion or deletion, is always made at the top of the stack.\nThe @fig-stack below exposes this logic visually:\n\n![A diagram of a stack structure. Source: Wikipedia, the free encyclopedia.](./../Figures/lifo-stack.svg){#fig-stack}\n\n\n\n## Writing the stack data structure\n\nWe are going to write the stack data structure in two steps. First, we are going\nto implement a stack that can only store `u32` values. Then, after that, we are going\nto extend our implementation to make it generic, so that it works with any data type\nwe want.\n\nFirst, we need to decide how the values will be stored inside the stack. There are multiple\nways to implement the storage behind a stack structure. Some people prefer to use a doubly linked list,\nothers prefer to use a dynamic array, etc. In this example we are going to use an array behind the hood,\nto store the values in the stack, which is the `items` data member of our `Stack` struct definition.\n\nAlso notice in our `Stack` struct that we have three other data members: `capacity`, `length` and `allocator`.\nThe `capacity` member contains the capacity of the underlying array that stores the values in the stack.\nThe `length` contains the number of values that are currently being stored in the stack.\nAnd the `allocator` contains the allocator object that will be used by the stack structure whenever it\nneeds to allocate more space for the values that are being stored.\n\nWe begin by defining an `init()` method of this struct, which is going to be\nresponsible for instantiating a `Stack` object. Notice that, inside this\n`init()` method, we start by allocating an array with the capacity specified\nin the `capacity` argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst Stack = struct {\n items: []u32,\n capacity: usize,\n length: usize,\n allocator: Allocator,\n\n pub fn init(allocator: Allocator, capacity: usize) !Stack {\n var buf = try allocator.alloc(u32, capacity);\n return .{\n .items = buf[0..],\n .capacity = capacity,\n .length = 0,\n .allocator = allocator,\n };\n }\n};\n```\n:::\n\n\n\n\n### Implementing the `push` operation\n\nNow that we have written the basic logic to create a new `Stack` object,\nwe can start writing the logic responsible for performing a push operation.\nRemember, a push operation in a stack data structure is the operation\nresponsible for adding a new value to the stack.\n\nSo how can we add a new value to the `Stack` object that we have?\nThe `push()` function exposed below is a possible answer to this question.\nRemember from what we discussed in @sec-what-stack that values are always added to the top of the stack.\nThis means that this `push()` function must always find the element in the underlying array\nthat currently represents the top position of the stack, and then, add the input value there.\n\nFirst, we have an if statement in this function. This if statement is\nchecking whether we need to expand the underlying array to store\nthis new value that we are adding to the stack. In other words, maybe\nthe underlying array does not have enough capacity to store this new\nvalue, and, in this case, we need to expand our array to get the capacity that we need.\n\nSo, if the logical test in this if statement returns true, it means that the array\ndoes not have enough capacity, and we need to expand it before we store this new value.\nSo inside this if statement we are executing the necessary expressions to expand the underlying array.\nNotice that we use the allocator object to allocate a new array that is twice as bigger\nthan the current array (`self.capacity * 2`).\n\nAfter that, we use a different built-in function named `@memcpy()`. This built-in function\nis equivalent to the `memcpy()` function from the C Standard Library[^cmemcpy]. It's used to\ncopy the values from one block of memory to another block of memory. In other words,\nyou can use this function to copy the values from one array into another array.\n\n[^cmemcpy]: \n\nWe are using this `@memcpy()` built-in function to copy the values that are currently stored\nin the underlying array of the stack object (`self.items`) into our new and bigger array that\nwe have allocated (`new_buf`). After we execute this function, the `new_buf` contains a copy\nof the values that are present at `self.items`.\n\nNow that we have secured a copy of our current values in the `new_buf` object, we\ncan now free the memory currently allocated at `self.items`. After that, we just need\nto assign our new and bigger array to `self.items`. This is the sequence\nof steps necessary to expand our array.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn push(self: *Stack, val: u32) !void {\n if ((self.length + 1) > self.capacity) {\n var new_buf = try self.allocator.alloc(\n u32, self.capacity * 2\n );\n @memcpy(\n new_buf[0..self.capacity], self.items\n );\n self.allocator.free(self.items);\n self.items = new_buf;\n self.capacity = self.capacity * 2;\n }\n\n self.items[self.length] = val;\n self.length += 1;\n}\n```\n:::\n\n\n\nAfter we make sure that we have enough room to store this new value\nthat we are adding to the stack, all we have to do is to assign\nthis value to the top element in this stack, and, increase the\nvalue of the `length` attribute by one. We find the top element\nin the stack by using the `length` attribute.\n\n\n\n### Implementing the `pop` operation\n\nNow we can implement the pop operation of our stack object.\nThis is a much easier operation to implement, and the `pop()` method below summarises\nall the logic that is needed.\n\nWe just have to find the element in the underlying array that currently represents the top\nof the stack, and set this element to \"undefined\", to indicate that\nthis element is \"empty\". After that, we also need to decrease\nthe `length` attribute of the stack by one.\n\nIf the current length of the stack is zero, it means that there is\nno values being stored in the stack currently. So, in this case,\nwe could just return from the function and do nothing really.\nThis is what the if statement inside this function is checking for.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn pop(self: *Stack) void {\n if (self.length == 0) return;\n\n self.items[self.length - 1] = undefined;\n self.length -= 1;\n}\n```\n:::\n\n\n\n\n\n### Implementing the `deinit` method\n\nWe have implemented the methods responsible for the two main operations\nassociated with the stack data structure, which is `pop()` and `push()`,\nand we also have implemented the method responsible for instantiating\na new `Stack` object, which is the `init()` method.\n\nBut now, we need to implement also the method responsible for destroying\na `Stack` object. In Zig, this task is commonly associated with the method\nnamed `deinit()`. Most struct objects in Zig have such method, and it\nis commonly nicknamed \"the destructor method\".\n\nIn theory, all we have to do to destroy the `Stack` object is to make\nsure that we free the allocated memory for the underlying array, using\nthe allocator object that is stored inside the `Stack` object.\nThis is what the `deinit()` method below is doing.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn deinit(self: *Stack) void {\n self.allocator.free(self.items);\n}\n```\n:::\n\n\n\n\n\n\n## Making it generic\n\nNow that we have implemented the basic skeleton of our stack data structure,\nwe can now focus on discussing how we can make it generic. How can we make\nthis basic skeleton to work not only with `u32` values, but also with any other\ndata type we want?\nFor example, we might need to create a stack object to store `User` values\nin it. How can we make this possible? The answer lies in the use of generics\nand `comptime`.\n\nAs I described in @sec-generic-struct, the basic idea is to write a generic\nfunction that returns a struct definition as output.\nIn theory, we do not need much to transform our `Stack` struct into a generic\ndata structure. All that we need to do is to transform the underlying array\nof the stack into a generic array.\n\nIn other words, this underlying array needs to be a \"chameleon\". It needs to adapt,\nand transform it into an array of any data type that we want. For example, if we need to create\na stack that will store `u8` values, then this underlying array needs to be\na `u8` array (i.e., `[]u8`). But if we need to store `User` values instead, then,\nthis array needs to be a `User` array (i.e., `[]User`). Etc.\n\nWe do that by using a generic function. Because a generic function can receive a data type\nas input, and we can pass this data type to the struct definition of our `Stack` object.\nTherefore, we can use the generic function to create a `Stack` object that can store\nthe data type we want. If we want to create a stack structure that stores `User` values,\nwe pass the `User` data type to this generic function, and it will create for us\nthe struct definition that describes a `Stack` object that can store `User` values in it.\n\nLook at the code example below. I have omitted some parts of the `Stack` struct definition\nfor brevity. However, if a specific part of our `Stack` struct is not exposed here\nin this example, then it's because this part did not change from the previous example.\nIt remains the same.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn Stack(comptime T: type) type {\n return struct {\n items: []T,\n capacity: usize,\n length: usize,\n allocator: Allocator,\n const Self = @This();\n\n pub fn init(allocator: Allocator,\n capacity: usize) !Stack(T) {\n var buf = try allocator.alloc(T, capacity);\n return .{\n .items = buf[0..],\n .capacity = capacity,\n .length = 0,\n .allocator = allocator,\n };\n }\n\n pub fn push(self: *Self, val: T) !void {\n // Truncate the rest of the struct\n };\n}\n```\n:::\n\n\n\nNotice that we have created a function in this example named `Stack()`. This function\ntakes a type as input, and passes this type to the struct definition of our\n`Stack` object. The data member `items` is now, an array of type `T`, which is the\ndata type that we have provided as input to the function. The function argument\n`val` in the `push()` function is now a value of type `T` too.\n\nWe can just provide a data type to this function, and it will create a definition of a\n`Stack` object that can store values of the data type that we have provided. In the example below, we are creating\nthe definition of a\n`Stack` object that can store `u8` values in it. This definition is stored at the `Stacku8` object.\nThis `Stacku8` object becomes our new struct, that we are going to use\nto create our `Stack` object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nconst Stacku8 = Stack(u8);\nvar stack = try Stacku8.init(allocator, 10);\ndefer stack.deinit();\ntry stack.push(1);\ntry stack.push(2);\ntry stack.push(3);\ntry stack.push(4);\ntry stack.push(5);\ntry stack.push(6);\n\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstd.debug.print(\"Stack capacity: {d}\\n\", .{stack.capacity});\n\nstack.pop();\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstack.pop();\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstd.debug.print(\n \"Stack state: {any}\\n\",\n .{stack.items[0..stack.length]}\n);\n```\n:::\n\n\n\n```\nStack len: 6\nStack capacity: 10\nStack len: 5\nStack len: 4\nStack state: { 1, 2, 3, 4, 0, 0, 0, 0, 0, 0 }\n```\n\nEvery generic data structure in the Zig Standard Library (`ArrayList`, `HashMap`, `SinlyLinkedList`, etc.)\nis implemented through this logic. They use a generic function to create the struct definition that can work\nwith the data type that you provided as input.\n\n\n\n\n## Conclusion\n\nThe full source code of the stack structure discussed in this chapter is freely available in the official\nrepository of this book. Just checkout the [`stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/stack.zig)[^zig-stack]\nfor the `u32` version of our stack,\nand the [`generic_stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/generic_stack.zig)[^zig-stack2]\nfor the generic version, available inside the `ZigExamples` folder of the repository.\n\n\n[^zig-stack]: \n[^zig-stack2]: \n", - "supporting": [ - "10-stack-project_files" - ], - "filters": [ - "rmarkdown/pagebreak.lua" - ], - "includes": {}, - "engineDependencies": { - "knitr": [ - "{\"type\":\"list\",\"attributes\":{},\"value\":[]}" - ] - }, - "preserve": null, - "postProcess": false - } -} \ No newline at end of file diff --git a/_freeze/Chapters/10-stack-project/execute-results/html.json b/_freeze/Chapters/10-stack-project/execute-results/html.json index 4afe632d..3ce0dd6d 100644 --- a/_freeze/Chapters/10-stack-project/execute-results/html.json +++ b/_freeze/Chapters/10-stack-project/execute-results/html.json @@ -2,7 +2,7 @@ "hash": "801c378f39cbcf646c40a137880aa3b8", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 3 - Building a stack data structure\n\nIn this chapter we are going to implement a stack data structure as our next small project\nin this book. Implementing basic data structures in any language is kind of a\n\"kindergarten task\" (if this term even exist) in computer science (CS), because\nwe normally learn and implement them in the first semesters of CS.\n\nBut this is actually good! Since this should be a very easy task, we don't need much to explain\nwhat a stack is, then, we can concentrate on what is really important here, which is learning\nhow the concept of \"generics\" is implemented in the Zig language, and how one of the key\nfeatures of Zig, which is comptime, works, and use the stack data structure to demonstrate\nthese concepts on the fly.\n\nBut before we get into building the stack data structure, we first need to understand\nwhat the `comptime` keyword does to your code, and after that, we also need to learn about\nhow generics work in Zig.\n\n\n## Understanding `comptime` in Zig {#sec-comptime}\n\nOne of the key features of Zig is `comptime`. This keyword introduces a whole\nnew concept and paradigm, that is tightly connected with the compilation process.\nIn @sec-compile-time we have described the importance and the role that \"compile-time versus runtime\"\nplays into Zig. In that section, we learned that the rules applied to a value/object change\na lot depending on whether this value is known at compile-time, or just at runtime.\n\nThe `comptime` keyword is strongly related to these two spaces in time (compile-time and runtime).\nLet's quickly recap the differences. Compile-time is the period of time when your\nZig source code is being compiled by the `zig` compiler, while the runtime is\nthe period of time when your Zig program is being executed, i.e., when we execute\nthe binary files that were generated by the `zig` compiler.\n\nThere are three ways in which you can apply the `comptime` keyword, which are:\n\n- apply `comptime` on a function argument.\n- apply `comptime` on an object.\n- apply `comptime` on a block of expressions.\n\n\n\n### Applying over a function argument\n\nWhen you apply the `comptime` keyword on a function argument, you are saying to the `zig` compiler\nthat the value assigned to that particular function argument must be known at compile-time.\nWe explained in detail in @sec-compile-time what exactly \"value known at compile-time\" means. So\nif you have any doubts about this idea, refer back to that section.\n\nNow let's think about the consequences of this idea. First of all, we are imposing a limit, or, a requirement\nto that particular function argument. If the programmer accidentally tries to give a value to this\nfunction argument that is not known at compile time, the `zig` compiler will notice this problem, and\nas a consequence, it will raise a compilation error saying that it cannot compile your program. Because\nyou are providing a value that is \"runtime known\" to a function argument that must be \"compile-time known\".\n\nTake a look at this very simple example below, where we define a `twice()` function, that simply\ndoubles the input value named `num`. Notice that we use the `comptime` keyword before the name\nof the function argument. This keyword is marking the function argument `num` as a \"comptime argument\".\n\nThat is a function argument whose value must be compile-time known. This is why the expression\n`twice(5678)` is valid, and no compilation errors are raised. Because the value `5678`\nis compile-time known, so this is the expected behaviour for this function.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\ntest \"test comptime\" {\n _ = twice(5678);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filef044375a1f16.test.test comptime...OKAll 1 \n tests passed.\n```\n\n\n:::\n:::\n\n\n\n\nBut what if we provide a number that is not compile-time known to this function?\nFor example, your program might receive some input from the user through the `stdin`\nchannel of your system. This input from the user might be many different things,\nand cannot be predicted at compile-time. These circumstances make this \"input\nfrom the user\" a value that is runtime-known only.\n\nIn the example below, this \"input from the user\" is initially received as a string,\nwhich is then parsed and transformed into a integer value, and the result of this operation\nis stored inside the `n` object.\n\nBecause the \"input of the user\" is known only at runtime, the value of the object `n` is determined only at runtime.\nAs consequence, we cannot provide this object as input to the `twice()` function.\nThe `zig` compiler will not allow it, because we marked\nthe `num` argument as a \"comptime argument\". That is why the `zig` compiler raises\nthe compile-time error exposed below:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\n\npub fn main() !void {\n var buffer: [5]u8 = .{ 0, 0, 0, 0, 0 };\n const stdout = std.io.getStdOut().writer();\n const stdin = std.io.getStdIn().reader();\n _ = try stdout.write(\"Please write a 4-digit integer number\\n\");\n _ = try stdin.readUntilDelimiter(&buffer, '\\n');\n\n try stdout.print(\"Input: {s}\", .{buffer});\n const n: u32 = try std.fmt.parseInt(\n u32, buffer[0 .. buffer.len - 1], 10\n );\n const twice_result = twice(n);\n try stdout.print(\"Result: {d}\\n\", .{twice_result});\n}\n```\n:::\n\n\n\n\n```\nt.zig:12:16: error: unable to resolve comptime value\n const twice_result = twice(n);\n ^\n```\n\nComptime arguments are frequently used on functions that return some sort\nof generic structure. In fact, `comptime` is the essence (or the basis) to make generics in Zig.\nWe are going to talk more about generics in @sec-generics.\n\nFor now, let's take a look at this code example from @karlseguin_generics. You\ncan see that this `IntArray()` function has one argument named `length`.\nThis argument is marked as comptime, and receives a value of type `usize` as input. So the value given to this argument\nmust be compile-time known.\nWe can also see that this function returns an array of `i64` values as output.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn IntArray(comptime length: usize) type {\n return [length]i64;\n}\n```\n:::\n\n\n\n\nNow, the key component of this function is the `length` argument. This argument\nis used to determine the size of the array that is produced by the function. Let's\nthink about the consequences of that. If the size of the array is dependent on\nthe value assigned to the `length` argument, this means that the data type of the\noutput of the function depends on the value of this `length` argument.\n\nLet this statement sink for a bit in your mind. As I described in @sec-root-file,\nZig is a strongly-typed language, especially on function declarations.\nSo every time we write a function in Zig, we have to annotate the data type of\nthe value returned by the function. But how can we do that, if this data type\ndepends on the value given to the argument of the function?\n\nThink about this for a second. If `length` is equal to 3 for example, then, the\nreturn type of the function is `[3]i64`. But if `length` is equal to 40, then,\nthe return type becomes `[40]i64`. At this point the `zig` compiler would be confused,\nand raise a compilation error, saying something like this:\n\n> Hey! You have annotated that this function should return a `[3]i64` value, but I got a `[40]i64` value instead! This doesn't look right!\n\nSo how can you solve this problem? How do we overcome this barrier? This is when\nthe `type` keyword comes in. This `type` keyword is basically saying to the\n`zig` compiler that this function will return some data type as output, but it doesn't know yet\nwhat exactly data type that is. We will talk more about this in @sec-generics.\n\n\n\n### Applying over an expression\n\nWhen you apply the `comptime` keyword over an expression, then, it is guaranteed that the `zig` compiler will\nexecute this expression at compile-time. If for some reason, this expression cannot be executed at compile-time\n(e.g. for example, maybe this expression depends on a value that is only known at runtime), then, the `zig` compiler\nwill raise a compilation error.\n\nTake this example from the official documentation of Zig [@zigdocs]. We\nare executing the same `fibonacci()` function both at runtime, and, at compile-time.\nThe function is executed by default at runtime, but because we use the `comptime`\nkeyword in the second \"try expression\", this expression is executed at compile-time.\n\nThis might be a bit confusing for some people. Yes! When I say that this expression\nis executed at compile-time, I mean that this expression is compiled and executed\nwhile the `zig` compiler is compiling your Zig source code.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci\" {\n // test fibonacci at run-time\n try expect(fibonacci(7) == 13);\n // test fibonacci at compile-time\n try comptime expect(fibonacci(7) == 13);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filef0447cb16f4d.test.fibonacci...OKAll 1 test\n ts passed.\n```\n\n\n:::\n:::\n\n\n\n\nA lot of your Zig source code might be potentially executed at compile-time,\nbecause the `zig` compiler can figure out the output of some expressions.\nEspecially if these expressions depend only on compile-time known values.\nWe have talked about this in @sec-compile-time.\n\nBut when you use the `comptime` keyword on an expression, there is no \"it might be executed\nat compile-time\" anymore. With the `comptime` keyword you are ordering the `zig` compiler\nto execute this expression at compile-time. You are imposing this rule, it is guaranteed\nthat the compiler will always execute it at compile-time. Or, at least, the compiler\nwill try to execute it. If the compiler cannot execute the expression for whatever reason,\nthe compiler will raise a compilation error.\n\n\n### Applying over a block\n\nBlocks were described in @sec-blocks. When you apply the `comptime` keyword to a\nblock of expressions, you get essentially the same effect as when you apply this keyword to\na single expression. That is, the entire block of expressions is executed at\ncompile-time by the `zig` compiler.\n\nIn the example below, we mark the block labeled of `blk` as a comptime block,\nand, therefore, the expressions inside this block are executed at compile-time.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci in a block\" {\n const x = comptime blk: {\n const n1 = 5;\n const n2 = 2;\n const n3 = n1 + n2;\n try expect(fibonacci(n3) == 13);\n break :blk n3;\n };\n _ = x;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 filef044524d5e27.test.fibonacci in a block...O\n OKAll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n\n## Introducing Generics {#sec-generics}\n\nFirst of all, what is a generic? Generic is the idea to allow a type\n(`f64`, `u8`, `u32`, `bool`, and also, user-defined types, like the `User` struct\nthat we defined in @sec-structs-and-oop) to be a parameter to methods, classes and\ninterfaces [@geeks_generics]. In other words, a \"generic\" is a class (or a method) that can work\nwith multiple data types.\n\nFor example, in Java, generics are created through the operator `<>`. With this operator,\na Java class is capable of receiving a data type as input, and therefore, the class can fit\nits features according to this input data type.\nAs another example, generics in C++ are supported through the concept of templates.\nClass templates in C++ are generics.\n\nIn Zig, generics are implemented through `comptime`. The `comptime` keyword\nallows us to collect a data type at compile time, and pass this data type as\ninput to a piece of code.\n\n\n### A generic function {#sec-generic-fun}\n\nTake the `max()` function exposed below as a first example.\nThis function is essentially a \"generic function\".\nIn this function, we have a comptime function argument named `T`.\nNotice that this `T` argument has a data type of `type`. Weird right? This `type` keyword is the\n\"father of all types\", or, \"the type of types\" in Zig.\n\nBecause we have used this `type` keyword in the `T` argument, we are telling\nthe `zig` compiler that this `T` argument will receive some data type as input.\nAlso notice the use of the `comptime` keyword in this argument.\nAs I described in @sec-comptime, every time you use this keyword in a function argument,\nthis means that the value of this argument must be known at compile-time.\nThis makes sense, right? Because there is no data type that is not known at compile-time.\n\nThink about this. Every data type that you will ever write is always\nknown at compile-time. Especially because data types are an essential\ninformation for the compiler to actually compile your source code.\nHaving this in mind, makes sense to mark this argument as a comptime argument.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn max(comptime T: type, a: T, b: T) T {\n return if (a > b) a else b;\n}\n```\n:::\n\n\n\n\nAlso notice that the value of the `T` argument is actually used\nto define the data type of the other arguments in the function, `a` and `b`, and also at the\nreturn type annotation of the function.\nThat is, the data type of these arguments (`a` and `b`), and, the return data type of the function itself,\nare determined by the input value given to the `T` argument.\n\nAs a result, we have a generic function that works with different data types.\nFor example, I can provide `u8` values to this `max()` function, and it will work as expected.\nBut if I provide `f64` values instead, it will also work as expected.\nWithout a generic function, I would have to write a different `max()` function\nfor each data type I wanted to use.\nThis generic function provides a very useful shortcut for us.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn max(comptime T: type, a: T, b: T) T {\n return if (a > b) a else b;\n}\ntest \"test max\" {\n const n1 = max(u8, 4, 10);\n std.debug.print(\"Max n1: {d}\\n\", .{n1});\n const n2 = max(f64, 89.24, 64.001);\n std.debug.print(\"Max n2: {d}\\n\", .{n2});\n}\n```\n:::\n\n\n\n\n```\nMax n1: 10\nMax n2: 89.24\n```\n\n\n### A generic data structure {#sec-generic-struct}\n\nEvery data structure that you find in the Zig Standard Library (e.g. `ArrayList`, `HashMap`, etc.)\nis essentially a generic data structure.\nThese data structures are generic in the sense that they work with any data type you want.\nYou just say which is the data type of the values that are going to be stored in this data\nstructure, and they just work as expected.\n\nA generic data structure in Zig is how you replicate a generic class from Java,\nor, a class template from C++. But you may ask yourself: how do we build a\ngeneric data structure in Zig?\n\nThe basic idea is to write a generic function that creates the data structure definition\nfor the specific type we want. In other words, this generic function behaves as a \"factory of data structures\".\nThe generic function outputs the `struct` definition that defines this data structure for a\nspecific data type.\n\nTo create such function, we need to add a comptime argument to this function that receives a data type\nas input. We already learned how to do this in the previous section (@sec-generic-fun).\nI think the best way to demonstrate how to create a generic data structure is to actually write one.\nThis where we go into our next small project in this book. This one is a very small project,\nwhich is to write a generic stack data structure.\n\n\n\n\n## What is a stack? {#sec-what-stack}\n\nA stack data structure is a structure that follows a LIFO (*last in, first out*) principle.\nOnly two operations are normally supported in a stack data structure, which are `push` and `pop`.\nThe `push` operation is used to add new values to the stack, while `pop` is used to remove\nvalues from the stack.\n\nWhen people try to explain how the stack data structure works, the most common analogy\nthat they use is a stack of plates. Imagine that you have a stack of plates,\nfor example, a stack of 10 plates in your table. Each plate represents a value that\nis currently stored in this stack.\n\nWe begin with a stack of 10 different values, or 10 different plates. Now, imagine that you want to\nadd a new plate (or a new value) to this stack, which translates to the `push` operation.\nYou would add this plate (or this value) by just putting the new plate\non the top of the stack. Then, you would increase the stack to 11 plates.\n\nBut how would you remove plates (or remove values) from this stack (a.k.a. the `pop` operation) ?\nTo do that, we would have to remove the plate on the top of the stack, and, as a result, we would\nhave, once again, 10 plates in the stack.\n\nThis demonstrates the LIFO concept, because the first plate in the stack, which is the plate\nin the bottom of the stack, is always the last plate to get out of the stack. Think about it. In order\nto remove this specific plate from the stack, we have to remove all plates in the\nstack. So every operation in the stack, either insertion or deletion, is always made at the top of the stack.\nThe @fig-stack below exposes this logic visually:\n\n![A diagram of a stack structure. Source: Wikipedia, the free encyclopedia.](./../Figures/lifo-stack.svg){#fig-stack}\n\n\n\n## Writing the stack data structure\n\nWe are going to write the stack data structure in two steps. First, we are going\nto implement a stack that can only store `u32` values. Then, after that, we are going\nto extend our implementation to make it generic, so that it works with any data type\nwe want.\n\nFirst, we need to decide how the values will be stored inside the stack. There are multiple\nways to implement the storage behind a stack structure. Some people prefer to use a doubly linked list,\nothers prefer to use a dynamic array, etc. In this example we are going to use an array behind the hood,\nto store the values in the stack, which is the `items` data member of our `Stack` struct definition.\n\nAlso notice in our `Stack` struct that we have three other data members: `capacity`, `length` and `allocator`.\nThe `capacity` member contains the capacity of the underlying array that stores the values in the stack.\nThe `length` contains the number of values that are currently being stored in the stack.\nAnd the `allocator` contains the allocator object that will be used by the stack structure whenever it\nneeds to allocate more space for the values that are being stored.\n\nWe begin by defining an `init()` method of this struct, which is going to be\nresponsible for instantiating a `Stack` object. Notice that, inside this\n`init()` method, we start by allocating an array with the capacity specified\nin the `capacity` argument.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst Stack = struct {\n items: []u32,\n capacity: usize,\n length: usize,\n allocator: Allocator,\n\n pub fn init(allocator: Allocator, capacity: usize) !Stack {\n var buf = try allocator.alloc(u32, capacity);\n return .{\n .items = buf[0..],\n .capacity = capacity,\n .length = 0,\n .allocator = allocator,\n };\n }\n};\n```\n:::\n\n\n\n\n\n### Implementing the `push` operation\n\nNow that we have written the basic logic to create a new `Stack` object,\nwe can start writing the logic responsible for performing a push operation.\nRemember, a push operation in a stack data structure is the operation\nresponsible for adding a new value to the stack.\n\nSo how can we add a new value to the `Stack` object that we have?\nThe `push()` function exposed below is a possible answer to this question.\nRemember from what we discussed in @sec-what-stack that values are always added to the top of the stack.\nThis means that this `push()` function must always find the element in the underlying array\nthat currently represents the top position of the stack, and then, add the input value there.\n\nFirst, we have an if statement in this function. This if statement is\nchecking whether we need to expand the underlying array to store\nthis new value that we are adding to the stack. In other words, maybe\nthe underlying array does not have enough capacity to store this new\nvalue, and, in this case, we need to expand our array to get the capacity that we need.\n\nSo, if the logical test in this if statement returns true, it means that the array\ndoes not have enough capacity, and we need to expand it before we store this new value.\nSo inside this if statement we are executing the necessary expressions to expand the underlying array.\nNotice that we use the allocator object to allocate a new array that is twice as bigger\nthan the current array (`self.capacity * 2`).\n\nAfter that, we use a different built-in function named `@memcpy()`. This built-in function\nis equivalent to the `memcpy()` function from the C Standard Library[^cmemcpy]. It's used to\ncopy the values from one block of memory to another block of memory. In other words,\nyou can use this function to copy the values from one array into another array.\n\n[^cmemcpy]: \n\nWe are using this `@memcpy()` built-in function to copy the values that are currently stored\nin the underlying array of the stack object (`self.items`) into our new and bigger array that\nwe have allocated (`new_buf`). After we execute this function, the `new_buf` contains a copy\nof the values that are present at `self.items`.\n\nNow that we have secured a copy of our current values in the `new_buf` object, we\ncan now free the memory currently allocated at `self.items`. After that, we just need\nto assign our new and bigger array to `self.items`. This is the sequence\nof steps necessary to expand our array.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn push(self: *Stack, val: u32) !void {\n if ((self.length + 1) > self.capacity) {\n var new_buf = try self.allocator.alloc(\n u32, self.capacity * 2\n );\n @memcpy(\n new_buf[0..self.capacity], self.items\n );\n self.allocator.free(self.items);\n self.items = new_buf;\n self.capacity = self.capacity * 2;\n }\n\n self.items[self.length] = val;\n self.length += 1;\n}\n```\n:::\n\n\n\n\nAfter we make sure that we have enough room to store this new value\nthat we are adding to the stack, all we have to do is to assign\nthis value to the top element in this stack, and, increase the\nvalue of the `length` attribute by one. We find the top element\nin the stack by using the `length` attribute.\n\n\n\n### Implementing the `pop` operation\n\nNow we can implement the pop operation of our stack object.\nThis is a much easier operation to implement, and the `pop()` method below summarises\nall the logic that is needed.\n\nWe just have to find the element in the underlying array that currently represents the top\nof the stack, and set this element to \"undefined\", to indicate that\nthis element is \"empty\". After that, we also need to decrease\nthe `length` attribute of the stack by one.\n\nIf the current length of the stack is zero, it means that there is\nno values being stored in the stack currently. So, in this case,\nwe could just return from the function and do nothing really.\nThis is what the if statement inside this function is checking for.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn pop(self: *Stack) void {\n if (self.length == 0) return;\n\n self.items[self.length - 1] = undefined;\n self.length -= 1;\n}\n```\n:::\n\n\n\n\n\n\n### Implementing the `deinit` method\n\nWe have implemented the methods responsible for the two main operations\nassociated with the stack data structure, which is `pop()` and `push()`,\nand we also have implemented the method responsible for instantiating\na new `Stack` object, which is the `init()` method.\n\nBut now, we need to implement also the method responsible for destroying\na `Stack` object. In Zig, this task is commonly associated with the method\nnamed `deinit()`. Most struct objects in Zig have such method, and it\nis commonly nicknamed \"the destructor method\".\n\nIn theory, all we have to do to destroy the `Stack` object is to make\nsure that we free the allocated memory for the underlying array, using\nthe allocator object that is stored inside the `Stack` object.\nThis is what the `deinit()` method below is doing.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn deinit(self: *Stack) void {\n self.allocator.free(self.items);\n}\n```\n:::\n\n\n\n\n\n\n\n## Making it generic\n\nNow that we have implemented the basic skeleton of our stack data structure,\nwe can now focus on discussing how we can make it generic. How can we make\nthis basic skeleton to work not only with `u32` values, but also with any other\ndata type we want?\nFor example, we might need to create a stack object to store `User` values\nin it. How can we make this possible? The answer lies in the use of generics\nand `comptime`.\n\nAs I described in @sec-generic-struct, the basic idea is to write a generic\nfunction that returns a struct definition as output.\nIn theory, we do not need much to transform our `Stack` struct into a generic\ndata structure. All that we need to do is to transform the underlying array\nof the stack into a generic array.\n\nIn other words, this underlying array needs to be a \"chameleon\". It needs to adapt,\nand transform it into an array of any data type that we want. For example, if we need to create\na stack that will store `u8` values, then this underlying array needs to be\na `u8` array (i.e., `[]u8`). But if we need to store `User` values instead, then,\nthis array needs to be a `User` array (i.e., `[]User`). Etc.\n\nWe do that by using a generic function. Because a generic function can receive a data type\nas input, and we can pass this data type to the struct definition of our `Stack` object.\nTherefore, we can use the generic function to create a `Stack` object that can store\nthe data type we want. If we want to create a stack structure that stores `User` values,\nwe pass the `User` data type to this generic function, and it will create for us\nthe struct definition that describes a `Stack` object that can store `User` values in it.\n\nLook at the code example below. I have omitted some parts of the `Stack` struct definition\nfor brevity. However, if a specific part of our `Stack` struct is not exposed here\nin this example, then it's because this part did not change from the previous example.\nIt remains the same.\n\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn Stack(comptime T: type) type {\n return struct {\n items: []T,\n capacity: usize,\n length: usize,\n allocator: Allocator,\n const Self = @This();\n\n pub fn init(allocator: Allocator,\n capacity: usize) !Stack(T) {\n var buf = try allocator.alloc(T, capacity);\n return .{\n .items = buf[0..],\n .capacity = capacity,\n .length = 0,\n .allocator = allocator,\n };\n }\n\n pub fn push(self: *Self, val: T) !void {\n // Truncate the rest of the struct\n };\n}\n```\n:::\n\n\n\n\nNotice that we have created a function in this example named `Stack()`. This function\ntakes a type as input, and passes this type to the struct definition of our\n`Stack` object. The data member `items` is now, an array of type `T`, which is the\ndata type that we have provided as input to the function. The function argument\n`val` in the `push()` function is now a value of type `T` too.\n\nWe can just provide a data type to this function, and it will create a definition of a\n`Stack` object that can store values of the data type that we have provided. In the example below, we are creating\nthe definition of a\n`Stack` object that can store `u8` values in it. This definition is stored at the `Stacku8` object.\nThis `Stacku8` object becomes our new struct, that we are going to use\nto create our `Stack` object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nconst Stacku8 = Stack(u8);\nvar stack = try Stacku8.init(allocator, 10);\ndefer stack.deinit();\ntry stack.push(1);\ntry stack.push(2);\ntry stack.push(3);\ntry stack.push(4);\ntry stack.push(5);\ntry stack.push(6);\n\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstd.debug.print(\"Stack capacity: {d}\\n\", .{stack.capacity});\n\nstack.pop();\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstack.pop();\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstd.debug.print(\n \"Stack state: {any}\\n\",\n .{stack.items[0..stack.length]}\n);\n```\n:::\n\n\n\n\n```\nStack len: 6\nStack capacity: 10\nStack len: 5\nStack len: 4\nStack state: { 1, 2, 3, 4, 0, 0, 0, 0, 0, 0 }\n```\n\nEvery generic data structure in the Zig Standard Library (`ArrayList`, `HashMap`, `SinlyLinkedList`, etc.)\nis implemented through this logic. They use a generic function to create the struct definition that can work\nwith the data type that you provided as input.\n\n\n\n\n## Conclusion\n\nThe full source code of the stack structure discussed in this chapter is freely available in the official\nrepository of this book. Just checkout the [`stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/stack.zig)[^zig-stack]\nfor the `u32` version of our stack,\nand the [`generic_stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/generic_stack.zig)[^zig-stack2]\nfor the generic version, available inside the `ZigExamples` folder of the repository.\n\n\n[^zig-stack]: \n[^zig-stack2]: \n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n# Project 3 - Building a stack data structure\n\nIn this chapter we are going to implement a stack data structure as our next small project\nin this book. Implementing basic data structures in any language is kind of a\n\"kindergarten task\" (if this term even exist) in computer science (CS), because\nwe normally learn and implement them in the first semesters of CS.\n\nBut this is actually good! Since this should be a very easy task, we don't need much to explain\nwhat a stack is, then, we can concentrate on what is really important here, which is learning\nhow the concept of \"generics\" is implemented in the Zig language, and how one of the key\nfeatures of Zig, which is comptime, works, and use the stack data structure to demonstrate\nthese concepts on the fly.\n\nBut before we get into building the stack data structure, we first need to understand\nwhat the `comptime` keyword does to your code, and after that, we also need to learn about\nhow generics work in Zig.\n\n\n## Understanding `comptime` in Zig {#sec-comptime}\n\nOne of the key features of Zig is `comptime`. This keyword introduces a whole\nnew concept and paradigm, that is tightly connected with the compilation process.\nIn @sec-compile-time we have described the importance and the role that \"compile-time versus runtime\"\nplays into Zig. In that section, we learned that the rules applied to a value/object change\na lot depending on whether this value is known at compile-time, or just at runtime.\n\nThe `comptime` keyword is strongly related to these two spaces in time (compile-time and runtime).\nLet's quickly recap the differences. Compile-time is the period of time when your\nZig source code is being compiled by the `zig` compiler, while the runtime is\nthe period of time when your Zig program is being executed, i.e., when we execute\nthe binary files that were generated by the `zig` compiler.\n\nThere are three ways in which you can apply the `comptime` keyword, which are:\n\n- apply `comptime` on a function argument.\n- apply `comptime` on an object.\n- apply `comptime` on a block of expressions.\n\n\n\n### Applying over a function argument\n\nWhen you apply the `comptime` keyword on a function argument, you are saying to the `zig` compiler\nthat the value assigned to that particular function argument must be known at compile-time.\nWe explained in detail in @sec-compile-time what exactly \"value known at compile-time\" means. So\nif you have any doubts about this idea, refer back to that section.\n\nNow let's think about the consequences of this idea. First of all, we are imposing a limit, or, a requirement\nto that particular function argument. If the programmer accidentally tries to give a value to this\nfunction argument that is not known at compile time, the `zig` compiler will notice this problem, and\nas a consequence, it will raise a compilation error saying that it cannot compile your program. Because\nyou are providing a value that is \"runtime known\" to a function argument that must be \"compile-time known\".\n\nTake a look at this very simple example below, where we define a `twice()` function, that simply\ndoubles the input value named `num`. Notice that we use the `comptime` keyword before the name\nof the function argument. This keyword is marking the function argument `num` as a \"comptime argument\".\n\nThat is a function argument whose value must be compile-time known. This is why the expression\n`twice(5678)` is valid, and no compilation errors are raised. Because the value `5678`\nis compile-time known, so this is the expected behaviour for this function.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\ntest \"test comptime\" {\n _ = twice(5678);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file20a25a72e5e3.test.test comptime...OKAll 1 \n tests passed.\n```\n\n\n:::\n:::\n\n\nBut what if we provide a number that is not compile-time known to this function?\nFor example, your program might receive some input from the user through the `stdin`\nchannel of your system. This input from the user might be many different things,\nand cannot be predicted at compile-time. These circumstances make this \"input\nfrom the user\" a value that is runtime-known only.\n\nIn the example below, this \"input from the user\" is initially received as a string,\nwhich is then parsed and transformed into a integer value, and the result of this operation\nis stored inside the `n` object.\n\nBecause the \"input of the user\" is known only at runtime, the value of the object `n` is determined only at runtime.\nAs consequence, we cannot provide this object as input to the `twice()` function.\nThe `zig` compiler will not allow it, because we marked\nthe `num` argument as a \"comptime argument\". That is why the `zig` compiler raises\nthe compile-time error exposed below:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn twice(comptime num: u32) u32 {\n return num * 2;\n}\n\npub fn main() !void {\n var buffer: [5]u8 = .{ 0, 0, 0, 0, 0 };\n const stdout = std.io.getStdOut().writer();\n const stdin = std.io.getStdIn().reader();\n _ = try stdout.write(\"Please write a 4-digit integer number\\n\");\n _ = try stdin.readUntilDelimiter(&buffer, '\\n');\n\n try stdout.print(\"Input: {s}\", .{buffer});\n const n: u32 = try std.fmt.parseInt(\n u32, buffer[0 .. buffer.len - 1], 10\n );\n const twice_result = twice(n);\n try stdout.print(\"Result: {d}\\n\", .{twice_result});\n}\n```\n:::\n\n\n```\nt.zig:12:16: error: unable to resolve comptime value\n const twice_result = twice(n);\n ^\n```\n\nComptime arguments are frequently used on functions that return some sort\nof generic structure. In fact, `comptime` is the essence (or the basis) to make generics in Zig.\nWe are going to talk more about generics in @sec-generics.\n\nFor now, let's take a look at this code example from @karlseguin_generics. You\ncan see that this `IntArray()` function has one argument named `length`.\nThis argument is marked as comptime, and receives a value of type `usize` as input. So the value given to this argument\nmust be compile-time known.\nWe can also see that this function returns an array of `i64` values as output.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn IntArray(comptime length: usize) type {\n return [length]i64;\n}\n```\n:::\n\n\nNow, the key component of this function is the `length` argument. This argument\nis used to determine the size of the array that is produced by the function. Let's\nthink about the consequences of that. If the size of the array is dependent on\nthe value assigned to the `length` argument, this means that the data type of the\noutput of the function depends on the value of this `length` argument.\n\nLet this statement sink for a bit in your mind. As I described in @sec-root-file,\nZig is a strongly-typed language, especially on function declarations.\nSo every time we write a function in Zig, we have to annotate the data type of\nthe value returned by the function. But how can we do that, if this data type\ndepends on the value given to the argument of the function?\n\nThink about this for a second. If `length` is equal to 3 for example, then, the\nreturn type of the function is `[3]i64`. But if `length` is equal to 40, then,\nthe return type becomes `[40]i64`. At this point the `zig` compiler would be confused,\nand raise a compilation error, saying something like this:\n\n> Hey! You have annotated that this function should return a `[3]i64` value, but I got a `[40]i64` value instead! This doesn't look right!\n\nSo how can you solve this problem? How do we overcome this barrier? This is when\nthe `type` keyword comes in. This `type` keyword is basically saying to the\n`zig` compiler that this function will return some data type as output, but it doesn't know yet\nwhat exactly data type that is. We will talk more about this in @sec-generics.\n\n\n\n### Applying over an expression\n\nWhen you apply the `comptime` keyword over an expression, then, it is guaranteed that the `zig` compiler will\nexecute this expression at compile-time. If for some reason, this expression cannot be executed at compile-time\n(e.g. for example, maybe this expression depends on a value that is only known at runtime), then, the `zig` compiler\nwill raise a compilation error.\n\nTake this example from the official documentation of Zig [@zigdocs]. We\nare executing the same `fibonacci()` function both at runtime, and, at compile-time.\nThe function is executed by default at runtime, but because we use the `comptime`\nkeyword in the second \"try expression\", this expression is executed at compile-time.\n\nThis might be a bit confusing for some people. Yes! When I say that this expression\nis executed at compile-time, I mean that this expression is compiled and executed\nwhile the `zig` compiler is compiling your Zig source code.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci\" {\n // test fibonacci at run-time\n try expect(fibonacci(7) == 13);\n // test fibonacci at compile-time\n try comptime expect(fibonacci(7) == 13);\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file20a26d02bee1.test.fibonacci...OKAll 1 test\n ts passed.\n```\n\n\n:::\n:::\n\n\nA lot of your Zig source code might be potentially executed at compile-time,\nbecause the `zig` compiler can figure out the output of some expressions.\nEspecially if these expressions depend only on compile-time known values.\nWe have talked about this in @sec-compile-time.\n\nBut when you use the `comptime` keyword on an expression, there is no \"it might be executed\nat compile-time\" anymore. With the `comptime` keyword you are ordering the `zig` compiler\nto execute this expression at compile-time. You are imposing this rule, it is guaranteed\nthat the compiler will always execute it at compile-time. Or, at least, the compiler\nwill try to execute it. If the compiler cannot execute the expression for whatever reason,\nthe compiler will raise a compilation error.\n\n\n### Applying over a block\n\nBlocks were described in @sec-blocks. When you apply the `comptime` keyword to a\nblock of expressions, you get essentially the same effect as when you apply this keyword to\na single expression. That is, the entire block of expressions is executed at\ncompile-time by the `zig` compiler.\n\nIn the example below, we mark the block labeled of `blk` as a comptime block,\nand, therefore, the expressions inside this block are executed at compile-time.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst expect = @import(\"std\").testing.expect;\nfn fibonacci(index: u32) u32 {\n if (index < 2) return index;\n return fibonacci(index - 1) + fibonacci(index - 2);\n}\n\ntest \"fibonacci in a block\" {\n const x = comptime blk: {\n const n1 = 5;\n const n2 = 2;\n const n3 = n1 + n2;\n try expect(fibonacci(n3) == 13);\n break :blk n3;\n };\n _ = x;\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n1/1 file20a238222e11.test.fibonacci in a block...O\n OKAll 1 tests passed.\n```\n\n\n:::\n:::\n\n\n\n\n\n\n## Introducing Generics {#sec-generics}\n\nFirst of all, what is a generic? Generic is the idea to allow a type\n(`f64`, `u8`, `u32`, `bool`, and also, user-defined types, like the `User` struct\nthat we defined in @sec-structs-and-oop) to be a parameter to methods, classes and\ninterfaces [@geeks_generics]. In other words, a \"generic\" is a class (or a method) that can work\nwith multiple data types.\n\nFor example, in Java, generics are created through the operator `<>`. With this operator,\na Java class is capable of receiving a data type as input, and therefore, the class can fit\nits features according to this input data type.\nAs another example, generics in C++ are supported through the concept of templates.\nClass templates in C++ are generics.\n\nIn Zig, generics are implemented through `comptime`. The `comptime` keyword\nallows us to collect a data type at compile time, and pass this data type as\ninput to a piece of code.\n\n\n### A generic function {#sec-generic-fun}\n\nTake the `max()` function exposed below as a first example.\nThis function is essentially a \"generic function\".\nIn this function, we have a comptime function argument named `T`.\nNotice that this `T` argument has a data type of `type`. Weird right? This `type` keyword is the\n\"father of all types\", or, \"the type of types\" in Zig.\n\nBecause we have used this `type` keyword in the `T` argument, we are telling\nthe `zig` compiler that this `T` argument will receive some data type as input.\nAlso notice the use of the `comptime` keyword in this argument.\nAs I described in @sec-comptime, every time you use this keyword in a function argument,\nthis means that the value of this argument must be known at compile-time.\nThis makes sense, right? Because there is no data type that is not known at compile-time.\n\nThink about this. Every data type that you will ever write is always\nknown at compile-time. Especially because data types are an essential\ninformation for the compiler to actually compile your source code.\nHaving this in mind, makes sense to mark this argument as a comptime argument.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn max(comptime T: type, a: T, b: T) T {\n return if (a > b) a else b;\n}\n```\n:::\n\n\nAlso notice that the value of the `T` argument is actually used\nto define the data type of the other arguments in the function, `a` and `b`, and also at the\nreturn type annotation of the function.\nThat is, the data type of these arguments (`a` and `b`), and, the return data type of the function itself,\nare determined by the input value given to the `T` argument.\n\nAs a result, we have a generic function that works with different data types.\nFor example, I can provide `u8` values to this `max()` function, and it will work as expected.\nBut if I provide `f64` values instead, it will also work as expected.\nWithout a generic function, I would have to write a different `max()` function\nfor each data type I wanted to use.\nThis generic function provides a very useful shortcut for us.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nfn max(comptime T: type, a: T, b: T) T {\n return if (a > b) a else b;\n}\ntest \"test max\" {\n const n1 = max(u8, 4, 10);\n std.debug.print(\"Max n1: {d}\\n\", .{n1});\n const n2 = max(f64, 89.24, 64.001);\n std.debug.print(\"Max n2: {d}\\n\", .{n2});\n}\n```\n:::\n\n\n```\nMax n1: 10\nMax n2: 89.24\n```\n\n\n### A generic data structure {#sec-generic-struct}\n\nEvery data structure that you find in the Zig Standard Library (e.g. `ArrayList`, `HashMap`, etc.)\nis essentially a generic data structure.\nThese data structures are generic in the sense that they work with any data type you want.\nYou just say which is the data type of the values that are going to be stored in this data\nstructure, and they just work as expected.\n\nA generic data structure in Zig is how you replicate a generic class from Java,\nor, a class template from C++. But you may ask yourself: how do we build a\ngeneric data structure in Zig?\n\nThe basic idea is to write a generic function that creates the data structure definition\nfor the specific type we want. In other words, this generic function behaves as a \"factory of data structures\".\nThe generic function outputs the `struct` definition that defines this data structure for a\nspecific data type.\n\nTo create such function, we need to add a comptime argument to this function that receives a data type\nas input. We already learned how to do this in the previous section (@sec-generic-fun).\nI think the best way to demonstrate how to create a generic data structure is to actually write one.\nThis where we go into our next small project in this book. This one is a very small project,\nwhich is to write a generic stack data structure.\n\n\n\n\n## What is a stack? {#sec-what-stack}\n\nA stack data structure is a structure that follows a LIFO (*last in, first out*) principle.\nOnly two operations are normally supported in a stack data structure, which are `push` and `pop`.\nThe `push` operation is used to add new values to the stack, while `pop` is used to remove\nvalues from the stack.\n\nWhen people try to explain how the stack data structure works, the most common analogy\nthat they use is a stack of plates. Imagine that you have a stack of plates,\nfor example, a stack of 10 plates in your table. Each plate represents a value that\nis currently stored in this stack.\n\nWe begin with a stack of 10 different values, or 10 different plates. Now, imagine that you want to\nadd a new plate (or a new value) to this stack, which translates to the `push` operation.\nYou would add this plate (or this value) by just putting the new plate\non the top of the stack. Then, you would increase the stack to 11 plates.\n\nBut how would you remove plates (or remove values) from this stack (a.k.a. the `pop` operation) ?\nTo do that, we would have to remove the plate on the top of the stack, and, as a result, we would\nhave, once again, 10 plates in the stack.\n\nThis demonstrates the LIFO concept, because the first plate in the stack, which is the plate\nin the bottom of the stack, is always the last plate to get out of the stack. Think about it. In order\nto remove this specific plate from the stack, we have to remove all plates in the\nstack. So every operation in the stack, either insertion or deletion, is always made at the top of the stack.\nThe @fig-stack below exposes this logic visually:\n\n![A diagram of a stack structure. Source: Wikipedia, the free encyclopedia.](./../Figures/lifo-stack.svg){#fig-stack}\n\n\n\n## Writing the stack data structure\n\nWe are going to write the stack data structure in two steps. First, we are going\nto implement a stack that can only store `u32` values. Then, after that, we are going\nto extend our implementation to make it generic, so that it works with any data type\nwe want.\n\nFirst, we need to decide how the values will be stored inside the stack. There are multiple\nways to implement the storage behind a stack structure. Some people prefer to use a doubly linked list,\nothers prefer to use a dynamic array, etc. In this example we are going to use an array behind the hood,\nto store the values in the stack, which is the `items` data member of our `Stack` struct definition.\n\nAlso notice in our `Stack` struct that we have three other data members: `capacity`, `length` and `allocator`.\nThe `capacity` member contains the capacity of the underlying array that stores the values in the stack.\nThe `length` contains the number of values that are currently being stored in the stack.\nAnd the `allocator` contains the allocator object that will be used by the stack structure whenever it\nneeds to allocate more space for the values that are being stored.\n\nWe begin by defining an `init()` method of this struct, which is going to be\nresponsible for instantiating a `Stack` object. Notice that, inside this\n`init()` method, we start by allocating an array with the capacity specified\nin the `capacity` argument.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Allocator = std.mem.Allocator;\nconst Stack = struct {\n items: []u32,\n capacity: usize,\n length: usize,\n allocator: Allocator,\n\n pub fn init(allocator: Allocator, capacity: usize) !Stack {\n var buf = try allocator.alloc(u32, capacity);\n return .{\n .items = buf[0..],\n .capacity = capacity,\n .length = 0,\n .allocator = allocator,\n };\n }\n};\n```\n:::\n\n\n\n### Implementing the `push` operation\n\nNow that we have written the basic logic to create a new `Stack` object,\nwe can start writing the logic responsible for performing a push operation.\nRemember, a push operation in a stack data structure is the operation\nresponsible for adding a new value to the stack.\n\nSo how can we add a new value to the `Stack` object that we have?\nThe `push()` function exposed below is a possible answer to this question.\nRemember from what we discussed in @sec-what-stack that values are always added to the top of the stack.\nThis means that this `push()` function must always find the element in the underlying array\nthat currently represents the top position of the stack, and then, add the input value there.\n\nFirst, we have an if statement in this function. This if statement is\nchecking whether we need to expand the underlying array to store\nthis new value that we are adding to the stack. In other words, maybe\nthe underlying array does not have enough capacity to store this new\nvalue, and, in this case, we need to expand our array to get the capacity that we need.\n\nSo, if the logical test in this if statement returns true, it means that the array\ndoes not have enough capacity, and we need to expand it before we store this new value.\nSo inside this if statement we are executing the necessary expressions to expand the underlying array.\nNotice that we use the allocator object to allocate a new array that is twice as bigger\nthan the current array (`self.capacity * 2`).\n\nAfter that, we use a different built-in function named `@memcpy()`. This built-in function\nis equivalent to the `memcpy()` function from the C Standard Library[^cmemcpy]. It's used to\ncopy the values from one block of memory to another block of memory. In other words,\nyou can use this function to copy the values from one array into another array.\n\n[^cmemcpy]: \n\nWe are using this `@memcpy()` built-in function to copy the values that are currently stored\nin the underlying array of the stack object (`self.items`) into our new and bigger array that\nwe have allocated (`new_buf`). After we execute this function, the `new_buf` contains a copy\nof the values that are present at `self.items`.\n\nNow that we have secured a copy of our current values in the `new_buf` object, we\ncan now free the memory currently allocated at `self.items`. After that, we just need\nto assign our new and bigger array to `self.items`. This is the sequence\nof steps necessary to expand our array.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn push(self: *Stack, val: u32) !void {\n if ((self.length + 1) > self.capacity) {\n var new_buf = try self.allocator.alloc(\n u32, self.capacity * 2\n );\n @memcpy(\n new_buf[0..self.capacity], self.items\n );\n self.allocator.free(self.items);\n self.items = new_buf;\n self.capacity = self.capacity * 2;\n }\n\n self.items[self.length] = val;\n self.length += 1;\n}\n```\n:::\n\n\nAfter we make sure that we have enough room to store this new value\nthat we are adding to the stack, all we have to do is to assign\nthis value to the top element in this stack, and, increase the\nvalue of the `length` attribute by one. We find the top element\nin the stack by using the `length` attribute.\n\n\n\n### Implementing the `pop` operation\n\nNow we can implement the pop operation of our stack object.\nThis is a much easier operation to implement, and the `pop()` method below summarises\nall the logic that is needed.\n\nWe just have to find the element in the underlying array that currently represents the top\nof the stack, and set this element to \"undefined\", to indicate that\nthis element is \"empty\". After that, we also need to decrease\nthe `length` attribute of the stack by one.\n\nIf the current length of the stack is zero, it means that there is\nno values being stored in the stack currently. So, in this case,\nwe could just return from the function and do nothing really.\nThis is what the if statement inside this function is checking for.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn pop(self: *Stack) void {\n if (self.length == 0) return;\n\n self.items[self.length - 1] = undefined;\n self.length -= 1;\n}\n```\n:::\n\n\n\n\n### Implementing the `deinit` method\n\nWe have implemented the methods responsible for the two main operations\nassociated with the stack data structure, which is `pop()` and `push()`,\nand we also have implemented the method responsible for instantiating\na new `Stack` object, which is the `init()` method.\n\nBut now, we need to implement also the method responsible for destroying\na `Stack` object. In Zig, this task is commonly associated with the method\nnamed `deinit()`. Most struct objects in Zig have such method, and it\nis commonly nicknamed \"the destructor method\".\n\nIn theory, all we have to do to destroy the `Stack` object is to make\nsure that we free the allocated memory for the underlying array, using\nthe allocator object that is stored inside the `Stack` object.\nThis is what the `deinit()` method below is doing.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn deinit(self: *Stack) void {\n self.allocator.free(self.items);\n}\n```\n:::\n\n\n\n\n\n## Making it generic\n\nNow that we have implemented the basic skeleton of our stack data structure,\nwe can now focus on discussing how we can make it generic. How can we make\nthis basic skeleton to work not only with `u32` values, but also with any other\ndata type we want?\nFor example, we might need to create a stack object to store `User` values\nin it. How can we make this possible? The answer lies in the use of generics\nand `comptime`.\n\nAs I described in @sec-generic-struct, the basic idea is to write a generic\nfunction that returns a struct definition as output.\nIn theory, we do not need much to transform our `Stack` struct into a generic\ndata structure. All that we need to do is to transform the underlying array\nof the stack into a generic array.\n\nIn other words, this underlying array needs to be a \"chameleon\". It needs to adapt,\nand transform it into an array of any data type that we want. For example, if we need to create\na stack that will store `u8` values, then this underlying array needs to be\na `u8` array (i.e., `[]u8`). But if we need to store `User` values instead, then,\nthis array needs to be a `User` array (i.e., `[]User`). Etc.\n\nWe do that by using a generic function. Because a generic function can receive a data type\nas input, and we can pass this data type to the struct definition of our `Stack` object.\nTherefore, we can use the generic function to create a `Stack` object that can store\nthe data type we want. If we want to create a stack structure that stores `User` values,\nwe pass the `User` data type to this generic function, and it will create for us\nthe struct definition that describes a `Stack` object that can store `User` values in it.\n\nLook at the code example below. I have omitted some parts of the `Stack` struct definition\nfor brevity. However, if a specific part of our `Stack` struct is not exposed here\nin this example, then it's because this part did not change from the previous example.\nIt remains the same.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn Stack(comptime T: type) type {\n return struct {\n items: []T,\n capacity: usize,\n length: usize,\n allocator: Allocator,\n const Self = @This();\n\n pub fn init(allocator: Allocator,\n capacity: usize) !Stack(T) {\n var buf = try allocator.alloc(T, capacity);\n return .{\n .items = buf[0..],\n .capacity = capacity,\n .length = 0,\n .allocator = allocator,\n };\n }\n\n pub fn push(self: *Self, val: T) !void {\n // Truncate the rest of the struct\n };\n}\n```\n:::\n\n\nNotice that we have created a function in this example named `Stack()`. This function\ntakes a type as input, and passes this type to the struct definition of our\n`Stack` object. The data member `items` is now, an array of type `T`, which is the\ndata type that we have provided as input to the function. The function argument\n`val` in the `push()` function is now a value of type `T` too.\n\nWe can just provide a data type to this function, and it will create a definition of a\n`Stack` object that can store values of the data type that we have provided. In the example below, we are creating\nthe definition of a\n`Stack` object that can store `u8` values in it. This definition is stored at the `Stacku8` object.\nThis `Stacku8` object becomes our new struct, that we are going to use\nto create our `Stack` object.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\nconst Stacku8 = Stack(u8);\nvar stack = try Stacku8.init(allocator, 10);\ndefer stack.deinit();\ntry stack.push(1);\ntry stack.push(2);\ntry stack.push(3);\ntry stack.push(4);\ntry stack.push(5);\ntry stack.push(6);\n\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstd.debug.print(\"Stack capacity: {d}\\n\", .{stack.capacity});\n\nstack.pop();\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstack.pop();\nstd.debug.print(\"Stack len: {d}\\n\", .{stack.length});\nstd.debug.print(\n \"Stack state: {any}\\n\",\n .{stack.items[0..stack.length]}\n);\n```\n:::\n\n\n```\nStack len: 6\nStack capacity: 10\nStack len: 5\nStack len: 4\nStack state: { 1, 2, 3, 4, 0, 0, 0, 0, 0, 0 }\n```\n\nEvery generic data structure in the Zig Standard Library (`ArrayList`, `HashMap`, `SinlyLinkedList`, etc.)\nis implemented through this logic. They use a generic function to create the struct definition that can work\nwith the data type that you provided as input.\n\n\n\n\n## Conclusion\n\nThe full source code of the stack structure discussed in this chapter is freely available in the official\nrepository of this book. Just checkout the [`stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/stack.zig)[^zig-stack]\nfor the `u32` version of our stack,\nand the [`generic_stack.zig`](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/data-structures/generic_stack.zig)[^zig-stack2]\nfor the generic version, available inside the `ZigExamples` folder of the repository.\n\n\n[^zig-stack]: \n[^zig-stack2]: \n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/_freeze/Chapters/12-file-op/execute-results/epub.json b/_freeze/Chapters/12-file-op/execute-results/epub.json deleted file mode 100644 index acf050fc..00000000 --- a/_freeze/Chapters/12-file-op/execute-results/epub.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "hash": "1e79228e1613c85b9e688833811e2fda", - "result": { - "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Filesystem and Input/Output (IO) {#sec-filesystem}\n\nIn this chapter we are going to discuss how to use the cross-platform structs and functions\nfrom the Zig Standard Library that can execute filesystem operations. Most of these functions and structs\ncomes from the `std.fs` module.\n\nWe are also going to talk about Input/Output (also known as IO) operations in Zig. Most of\nthese operations are made by using the structs and functions from `std.io` module, which defines\nfile descriptors for the *standard channels* of your system (`stdout` and `stdin`), and also,\nfunctions to create and use I/O streams.\n\n\n## Input/Output basics {#sec-io-basics}\n\nIf you have some experience in a high-level language, you have certainly used\nthese input and output functionalities before in this language. In other words, you certainly have\nbeen in a situation where you needed to sent some output to the user, or, to receive an input\nfrom the user.\n\nFor example, in Python we can receive some input from the user by using the `input()` built-in\nfunction. But we can also print (or \"show\") some output to the user by using the `print()`\nbuilt-in function. So yes, if you have programmed before in Python, you certainly have\nused these functions once before.\n\nBut do you know how these functions relate back to your operating system (OS)? How exactly\nthey are interacting with the resources of your OS to receive or sent some input/output.\nIn essence, these input/output functions from high-level languages are just abstractions\nover the *standard output* and *standard input* channels of your operating system.\n\nThis means that we receive an input, or send some output, through the operating system.\nIt's the OS that makes the bridge between the user and your program. Your program\ndoes not have a direct access to the user. It's the OS that intermediates every\nmessage exchanged between your program and the user.\n\nThe *standard output* and *standard input* channels of your OS are commonly known as the\n`stdout` and `stdin` channels of your OS, respectively. In some contexts, they are also\ncalled the *standard output device* and the *standard input device*. As the name suggests,\nthe *standard output* is the channel through which output flows, while the *standard input*\nis the channel in which input flows.\n\nFurthermore, OS's also normally create a dedicated channel for exchanging error messages, which is known as the\n*standard error* channel, or, the `stderr` channel. This is the channel to which error and warning messages\nare usually sent to. These are the messages that are normally displayed in red-like or orange-like colors\ninto your terminal.\n\nNormally, every OS (e.g. Windows, macOS, Linux, etc.) creates a dedicated and separate set of\n*standard output*, *standard error* and *standard input* channels for every single program (or process) that runs in your computer.\nThis means that every program you write have a dedicated `stdin`, `stderr` and `stdout` that are separate\nfrom the `stdin`, `stderr` and `stdout` of other programs and processes that are currently running.\n\nThis is a behaviour from your OS. This does not come from the programming language that you are using.\nBecause as I sad earlier, input and output in programming languages, especially\nin high-level ones, are just a simple abstraction over the `stdin`, `stderr` and `stdout` from your current OS.\nThat is, your OS is the intermediary between every input/output operation made in your program,\nregardless of the programming language that you are using.\n\n\n### The writer and reader pattern {#sec-writer-reader}\n\nIn Zig, there is a pattern around input/output (IO). I (the author of this book) don't know if there\nis an official name for this pattern. But here, in this book, I will call it the \"writer and reader pattern\".\nIn essence, every IO operation in Zig is made through either a `GenericReader` or a `GenericWriter` object[^gen-zig].\n\nThese two data types come from the `std.io` module of the Zig Standard Library. As their names suggests, a\n`GenericReader` is an object that offers tools to read data from \"something\" (or \"somewhere\"), while a `GenericWriter`\noffers tools to write data into this \"something\". This \"something\" might be different things: like a\nfile that exists in your filesystem; or, it might be a network socket in your system[^sock]; or,\na continuous stream of data, like a standard input device from your system, that might be constantly\nreceiving new data from users, or, as another example, a live chat in a game that is constantly\nreceiving and displaying new messages from the players of the game.\n\n[^gen-zig]: Previously, these objects were known as the `Reader` and `Writer` objects.\n[^sock]: The socket objects that we have created in @sec-create-socket, are examples of network sockets.\n\nSo, if you want to **read** data from something, or somewhere, it means that you need to use a `GenericReader` object.\nBut if you need instead, to **write** data into this \"something\", then, you need to use a `GenericWriter` object instead.\nBoth of these objects are normally created from a file descriptor object. More specifically, through the `writer()` and `reader()`\nmethods of this file descriptor object. If you are not familiar with this type of object, go to the next section.\n\nEvery `GenericWriter` object have methods like `print()`, which allows you to write/send a formatted string\n(i.e., this formatted string is like a `f` string in Python, or, similar to the `printf()` C function)\ninto the \"something\" (file, socket, stream, etc.) that you are using. It also have a `writeAll()` method, which allows you to\nwrite a string, or, an array of bytes into the \"something\".\n\nLikewise, every `GenericReader` object have methods like `readAll()`, which allows you to read the\ndata from the \"something\" (file, socket, stream, etc.) until it fills a particular array (i.e., a \"buffer\") object.\nIn other words, if you provide an array object of 300 `u8` values to `readAll()`, then, this method attempts to read 300 bytes\nof data from the \"something\", and it stores them into the array object that you have provided.\n\nWe also have other methods, like the `readAtLeast()` method, which allows you to specify how\nmany bytes exactly you want to read from the \"something\". In more details, if you give the\nnumber $n$ as input to this method, then, it will attempt to read at least $n$ bytes of data\nfrom the \"something\". The \"something\" might have less than $n$ bytes of data available for you\nto read, so, it's not guaranteed that you will get precisely $n$ bytes as result.\n\nAnother useful method is `readUntilDelimiterOrEof()`. In this method, you specify a \"delimiter character\".\nThe idea is that this function will attempt to read as many bytes of data as possible from the \"something\",\nuntil it encounters the end of the stream, or, it encounters the \"delimiter character\" that you have specified.\n\nIf you don't know exactly how many bytes will come from the \"something\", you may find the `readAllAlloc()` method\nuseful. In essence, you provide an allocator object to this method, so that it can allocate more space if needed.\nAs consequence, this method will try to read all bytes of the \"something\", and, if it runs out of space at some point\nduring the \"reading process\", it uses the allocator object to allocate more space to continue reading the bytes.\nAs result, this method returns a slice to the array object containing all the bytes read.\n\nThis is just a quick description of the methods present in these types of objects. But I recommend you\nto read the official docs, both for\n[`GenericWriter`](https://ziglang.org/documentation/master/std/#std.io.GenericWriter)[^gen-write] and\n[`GenericReader`](https://ziglang.org/documentation/master/std/#std.io.GenericReader)[^gen-read].\nI also think it's a good idea to read the source code of the modules in the Zig Standard Library\nthat defines the methods present in these objects, which are the\n[`Reader.zig`](https://github.com/ziglang/zig/blob/master/lib/std/io/Reader.zig)[^mod-read]\nand [`Writer.zig`]()[^mod-write].\n\n[^gen-read]: .\n[^gen-write]: .\n[^mod-read]: .\n[^mod-write]: .\n\n\n\n### Introducing file descriptors {#sec-file-descriptor}\n\nA \"file descriptor\" object is a core component behind every IO operation that is made in any operating system (OS).\nSuch object is an identifier for a particular input/output (IO) resource from your OS [@wiki_file_descriptor].\nIt describes and identifies this particular resource. An IO resource might be:\n\n- an existing file in your filesystem.\n- an existing network socket.\n- other types of stream channels.\n- a pipeline (or just \"pipe\") in your terminal[^pipes].\n\n[^pipes]: A pipeline is a mechanism for inter-process communication, or, inter-process IO. You could also interpret a pipeline as a \"set of processes that are chained together, through the standard input/output devices of the system\". At Linux for example, a pipeline is created inside a terminal, by connecting two or more terminal commands with the \"pipe\" character (`|`).\n\nFrom the bullet points listed above, we know that although the term \"file\" is present,\na \"file descriptor\" might describe something more than just a file.\nThis concept of a \"file descriptor\" comes from the Portable Operating System Interface (POSIX) API,\nwhich is a set of standards that guide how operating systems across the world should be implemented,\nto maintain compatibility between them.\n\nA file descriptor not only identifies the input/output resource that you are using to receive or send some data,\nbut it also describes where this resource is, and also, which IO mode this resource is currently using.\nFor example, this IO resource might be using only the \"read\" IO mode, which means that this resource\nis open to \"read operations\", while \"write operations\" are not authorized.\nThese IO modes are essentially the modes that you provide to the argument `mode`\nfrom the `fopen()` C function, and also, from the `open()` Python built-in function.\n\nIn C, a \"file descriptor\" is a `FILE` pointer, but, in Zig, a file descriptor is a `File` object.\nThis data type (`File`) is described in the `std.fs` module of the Zig Standard Library.\nWe normally don't create a `File` object directly in our Zig code. Instead, we normally get such object as result when we\nopen an IO resource. In other words, we normally ask our OS to open a particular IO resource for us,\nand, if the OS do open successfully this IO resource, the OS normally handles back to us\na file descriptor to this particular IO resource.\n\nSo you usually get a `File` object by using functions and methods from the Zig Standard Library\nthat asks the OS to open some IO resource, like the `openFile()` method that opens a file in the\nfilesystem. The `net.Stream` object that we have created in @sec-create-socket is also a type of\nfile descriptor object.\n\n\n### The *standard output*\n\nYou already saw across this book, how can we access and use specifically the `stdout` in Zig\nto send some output to the user.\nFor that, we use the `getStdOut()` function from the `std.io` module. This function returns\na file descriptor that describes the `stdout` channel of your current OS. Through this file\ndescriptor object, we can read from or write stuff to the `stdout` of our program.\n\nAlthough we can read stuff recorded into the `stdout` channel, we normally only\nwrite to (or \"print\") stuff into this channel. The reason is very similar to what we discussed at\n@sec-read-http-message, when we were discussing what \"reading from\" versus \"writing to\" the connection\nobject from our small HTTP Server project would mean.\n\nWhen we write stuff into a channel, we are essentially sending data to the other end of this channel.\nIn contrast, when we read stuff from this channel, we are essentially reading the data that was sent\nthrough this channel. Since the `stdout` is a channel to send output to the user, the key verb here\nis **send**. We want to send something to someone, and, as consequence, we want to **write** something\ninto some channel.\n\nThat is why, when we use `getStdOut()`, most of the times, we also use the `writer()` method from the `stdout` file descriptor,\nto get access to a writer object that we can use to write stuff into this `stdout` channel.\nMore specifically, this `writer()` method returns a `GenericWriter` object. One of the\nmain methods of this `GenericWriter` object is the `print()` method that we have used\nbefore to write (or \"print\") a formatted string into the `stdout` channel.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n try stdout.writeAll(\n \"This message was written into stdout.\\n\"\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nThis message was written into stdout.\n```\n\n\n:::\n:::\n\n\n\n\n\nThis `GenericWriter` object is like any other generic writer object that you would normally get from a file descriptor object.\nSo, the same methods from a generic writer object that you would use while writing files to the filesystem for example, you could also\nuse them here, from the file descriptor object of `stdout`, and vice-versa.\n\n\n### The *standard input*\n\nYou can access the *standard input* (i.e., `stdin`) in Zig by using the `getStdIn()` function from the `std.io` module.\nLike its brother (`getStdOut()`), this function also returns a file descriptor object that describes the `stdin` channel\nof your OS.\n\nBecause we want to receive some input from the user, the key verb here becomes **receive**, and, as consequence,\nwe usually want to **read** data from the `stdin` channel, instead of writing data into it. So, we normally use\nthe `reader()` method of the file descriptor object returned by `getStdIn()`, to get access to a `GenericReader`\nobject that we can use to read data from `stdin`.\n\nIn the example below, we are creating a small buffer capable of holding 20 characters. Then, we try to read\nthe data from the `stdin` with the `readUntilDelimiterOrEof()` method, and save this data into the `buffer` object.\nAlso notice that we are reading the data from the `stdin` until we hit a new line character (`'\\n'`).\n\nIf you execute this program, you will notice that it stops the execution, ands start to wait indefinitely\nfor some input from the user. In other words, you need to type your name into the terminal, and then, you press Enter to\nsend your name to `stdin`. After you send your name to `stdin`, the program reads this input, and continues with the execution,\nby printing the given name to `stdout`. In the example below, I typed my name (Pedro) into the terminal, and then, pressed Enter.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst stdin = std.io.getStdIn().reader();\npub fn main() !void {\n try stdout.writeAll(\"Type your name\\n\");\n var buffer: [20]u8 = undefined;\n @memset(buffer[0..], 0);\n _ = try stdin.readUntilDelimiterOrEof(buffer[0..], '\\n');\n try stdout.print(\"Your name is: {s}\\n\", .{buffer});\n}\n```\n:::\n\n\n\n```\nType your name\nYour name is: Pedro\n\n```\n\n\n### The *standard error*\n\nThe *standard error* (a.k.a. the `stderr`) works exactly the same as `stdout` and `stdin`.\nYou just call the `getStdErr()` function from the `std.io` module, and you get the file descriptor to `stderr`.\nIdeally, you should write only error or warning messages to `stderr`, because this is\nthe purpose of this channel.\n\n\n\n\n\n## Buffered IO\n\nAs we described in @sec-io-basics, input/output (IO) operations are made directly by the operating system.\nIt's the OS that manages the IO resource that you want to use for your IO operations.\nThe consequence of this fact is that IO operations are heavily based on system calls (i.e., calling the operating system directly).\n\nJust to be clear, there is nothing particularly wrong with system calls. We use them all the time on\nany serious codebase written in any low-level programming language. However, system calls are\nalways orders of magnitude slower than many different types of operations.\n\nSo is perfectly fine to use a system call once in a while. But when these system calls are used often,\nyou can clearly notice most of the time the loss of performance in your application. So, the good rule of thumb\nis to use a system call only when it's needed, and also, only in infrequent situations, to reduce\nthe number of system calls performed to a minimum.\n\n\n### Understanding how buffered IO works\n\nBuffered IO is a strategy to achieve better performance. It's used to reduce the number of system calls made by IO operations, and, as\nconsequence, achieve a much higher performance. In @fig-unbuffered-io and @fig-buffered-io you can find two different diagrams\nwhich presents the difference between read operations performed in an unbuffered IO environment versus a buffered IO environment.\n\nTo give a better context to these diagrams, let's suppose that we have a text file that contains the famous Lorem ipsum text[^lorem]\nin our filesystem. Let's also suppose that these diagrams in @fig-unbuffered-io and @fig-buffered-io\nare showing the read operations that we are performing to read the Lorem ipsum text from this text file.\nThe first thing you will notice when looking at these diagrams, is that in an unbuffered environment\nthe read operations leads to many system calls.\nMore precisely, in the diagram exposed in @fig-unbuffered-io we get one system call per each byte that we read from the text file.\nOn the other hand, in @fig-buffered-io we have only one system call at the very beginning.\n\nWhen we use a buffered IO system, at the first read operation we perform, instead of sending one single byte directly\nto our program, the OS first sends a chunk of bytes from the file to a buffer object (i.e., an array).\nThis chunk of bytes are cached/stored inside this buffer object.\n\nTherefore, from now on, for every new read operation that you perform, instead of making a new system call to ask\nfor the next byte in the file to the OS, this read operation is redirected to the buffer object, that have\nthis next byte already cached and ready to go.\n\n\n[^lorem]: .\n\n\n![Unbuffered IO](./../Figures/unbuffered-io.png){#fig-unbuffered-io width=60%}\n\n![Buffered IO](./../Figures/buffered-io.png){#fig-buffered-io}\n\n\n\nThis is the basic logic behind buffered IO systems. The size of the buffer object depends on multiple factors. But it's usually\nequal to the size of a full page of memory (4096 bytes). If we follow this logic, then, the OS reads the first 4096 bytes\nof the file and caches it into the buffer object. As long as your program does not consume all of these 4096 bytes from the buffer,\nyou will not create new system calls.\n\nHowever, as soon as you consume all of these 4096 bytes from the buffer, it means that there is no bytes left in the buffer.\nIn this situation, a new system call is made to ask the OS to send the next 4096 bytes in the file, and once again,\nthese bytes are cached into the buffer object, and the cycle starts once again.\n\n\n### Buffered IO across different languages\n\nIO operations made through a `FILE` pointer in C are buffered\nby default, so, at least in C, you don't need to worry about this subject. But in contrast, IO operations in both Rust and Zig are not\nbuffered depending on which functions from the standard libraries that you are using.\n\nFor example, in Rust, buffered IO is implemented through the `BufReader` and `BufWriter` structs, while in Zig, it's implemented\nthrough the `BufferedReader` and `BufferedWriter` structs.\nSo any IO operation that you perform through the `GenericWriter` and `GenericReader` objects\nthat I presented in @sec-writer-reader are not buffered, which means that these objects\nmight create a lot of system calls depending on the situation.\n\n\n### Using buffered IO in Zig\n\nUsing buffered IO in Zig is actually very easy. All you have to do is to just\ngive the `GenericWriter` object to the `bufferedWriter()` function, or, to give the `GenericReader`\nobject to the `bufferedReader()` function. These functions come from the `std.io` module,\nand they will construct the `BufferedWriter` or `BufferedReader` object for you.\n\nAfter you create this new `BufferedWriter` or `BufferedReader` object, you can call the `writer()`\nor `reader()` method of this new object, to get access to a new (and buffered) generic reader or\ngeneric writer.\n\nLet's describe the process once again. Every time that you have a file descriptor object, you first get the generic writer or generic reader\nobject from it, by calling the `writer()` or `reader()` methods of this file descriptor object.\nThen, you provide this generic writer or generic reader to the `bufferedWriter()` or `bufferedReader()`\nfunction, which creates a new `BufferedWriter` or `BufferedReader` object. Then, you call\nthe `writer()` or `reader()` methods of this buffered writer or buffered reader object,\nwhich gives you access to a generic writer or a generic reader object that is buffered.\n\nTake this program as an example. This program is demonstrating the process exposed in @fig-buffered-io.\nWe are simply opening a text file that contains the Lorem ipsum text, and then, we create a buffered IO reader object\nat `bufreader`, and we use this `bufreader` object to read the contents of this file into a buffer object, then,\nwe end the program by printing this buffer to `stdout`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar file = try std.fs.cwd().openFile(\n \"ZigExamples/file-io/lorem.txt\", .{}\n);\ndefer file.close();\nvar buffered = std.io.bufferedReader(file.reader());\nvar bufreader = buffered.reader();\n\nvar buffer: [1000]u8 = undefined;\n@memset(buffer[0..], 0);\n\n_ = try bufreader.readUntilDelimiterOrEof(\n buffer[0..], '\\n'\n);\ntry stdout.print(\"{s}\\n\", .{buffer});\n```\n:::\n\n\n\n```\nLorem ipsum dolor sit amet, consectetur\nadipiscing elit. Sed tincidunt erat sed nulla ornare, nec\naliquet ex laoreet. Ut nec rhoncus nunc. Integer magna metus,\nultrices eleifend porttitor ut, finibus ut tortor. Maecenas\nsapien justo, finibus tincidunt dictum ac, semper et lectus.\nVivamus molestie egestas orci ac viverra. Pellentesque nec\narcu facilisis, euismod eros eu, sodales nisl. Ut egestas\nsagittis arcu, in accumsan sapien rhoncus sit amet. Aenean\nneque lectus, imperdiet ac lobortis a, ullamcorper sed massa.\nNullam porttitor porttitor erat nec dapibus. Ut vel dui nec\nnulla vulputate molestie eget non nunc. Ut commodo luctus ipsum,\nin finibus libero feugiat eget. Etiam vel ante at urna tincidunt\nposuere sit amet ut felis. Maecenas finibus suscipit tristique.\nDonec viverra non sapien id suscipit.\n```\n\nDespite being a buffered IO reader, this `bufreader` object is similar to any other `GenericReader` object,\nand have the exact same methods. So, although these two types of objects perform very different IO operations,\nthey have the same interface, so you, the programmer, can interchangeably use them\nwithout the need to change anything in your source code.\nSo a buffered IO reader or a buffered IO writer objects have the same methods than its generic and unbuffered brothers,\ni.e., the generic reader and generic writer objects that I presented in @sec-writer-reader.\n\n::: {.callout-tip}\nIn general, you should always use a buffered IO reader or a buffered IO writer object to perform\nIO operations in Zig. Because they deliver better performance to your IO operations.\n:::\n\n\n## Filesystem basics\n\nNow that we have discussed the basics around Input/Output operations in Zig, we need to\ntalk about the basics around filesystems, which is another core part of any operating system.\nAlso, filesystems are related to input/output, because the files that we store and create in our\ncomputer are considered an IO resource, as we described in @sec-file-descriptor.\n\n\n### The concept of current working directory (CWD)\n\nThe working directory is the folder on your computer where you are currently rooted at.\nIn other words, it's the folder that your program is currently looking at.\nTherefore, whenever you are executing a program, this program is always working with\na specific folder on your computer. It's always in this folder that the program will initially\nlook for the files you require, and it's also in this folder that the program\nwill initially save all the files you ask it to save.\n\nThe working directory is determined by the folder from which you invoke your program\nin the terminal. In other words, if you are in the terminal of your OS, and you\nexecute a binary file (i.e., a program) from this terminal, the folder to which your terminal\nis pointing at is the current working directory of your program that is being executed.\n\nIn @fig-cwd we have an example of me executing a program from the terminal. We are executing\nthe program outputted by the `zig` compiler by compiling the Zig module named `hello.zig`.\nThe CWD in this case is the `zig-book` folder. In other words, while the `hello.zig` program\nis executing, it will be looking at the `zig-book` folder, and any file operation that we perform\ninside this program, will be using this `zig-book` folder as the \"starting point\", or, as the \"central focus\".\n\n![Executing a program from the terminal](./../Figures/cwd.png){#fig-cwd}\n\nJust because we are rooted inside a particular folder (in the case of @fig-cwd, the `zig-book` folder) of our computer,\nit doesn't mean that we cannot access or write resources in other locations of our computer.\nThe current working directory (CWD) mechanism just defines where your program will look first\nfor the files you ask for. This does not prevent you from accessing files that are located\nelsewhere on your computer. However, to access any file that is in a folder other than your\ncurrent working directory, you must provide a path to that file or folder.\n\n\n### The concept of paths\n\nA path is essentially a location. It points to a location in your filesystem. We use\npaths to describe the location of files and folders in our computer.\nOne important aspect about paths is that they are always written inside strings,\ni.e., they are always provided as text values.\n\nThere are two types of paths that you can provide to any program in any OS: a relative path, or an absolute path.\nAbsolute paths are paths that start at the root of your filesystem, and go all the way to the file name or the specific folder\nthat you are referring to. This type of path is called absolute, because it points to an unique and absolute location on your computer.\nThat is, there is no other existing location on your computer that corresponds to this path. It's an unique identifier.\n\nIn Windows, an absolute path is a path that starts with a hard disk identifier (e.g. `C:/Users/pedro`).\nOn the other hand, absolute paths in Linux and macOS, are paths that start with a forward slash character (e.g. `/usr/local/bin`).\nNotice that a path is composed by \"segments\". Each segment is connected to each other by a slash character (`\\` or `/`).\nOn Windows, the backward slash (`\\`) is normally used to connect the path segments. While on Linux and macOS, the forward\nslash (`/`) is the character used to connect path segments.\n\nA relative path is a path that start at the CWD. In other words, a relative path is\n\"relative to the CWD\". The path used to access the `hello.zig` file in @fig-cwd is an example of a relative path. This path\nis reproduced below. This path begins at the CWD, which in the context of @fig-cwd, is the `zig-book` folder,\nthen, it goes to the `ZigExamples` folder, then, into `zig-basics`, then, to the `hello.zig` file.\n\n```\nZigExamples/zig-basics/hello_world.zig\n```\n\n\n### Path wildcards\n\nWhen providing paths, especially relative paths, you have the option of using a *wildcard*.\nThere are two commonly used *wildcards* in paths, which are \"one period\" (.) and \"two periods\" (..).\nIn other words, these two specific characters have special meanings when used in paths,\nand can be used on any operating system (Mac, Windows, Linux, etc.). That is, they\nare \"cross platform\".\n\nThe \"one period\" represents an alias for the current directory.\nThis means that the relative paths `\"./Course/Data/covid.csv\"` and `\"Course/Data/covid.csv\"` are equivalent.\nOn the other hand, the \"two periods\" refers to the previous directory.\nFor example, the path `\"Course/..\"` is equivalent to the path `\".\"`, that is, the current working directory.\n\nTherefore, the path `\"Course/..\"` refers to the folder before the `Course` folder.\nAs another example, the path `\"src/writexml/../xml.cpp\"` refers to the file `xml.cpp`\nthat is inside the folder before the `writexml` folder, which in this example is the `src` folder.\nTherefore, this path is equivalent to `\"src/xml.cpp\"`.\n\n\n\n\n## The CWD handler\n\nIn Zig, filesystem operations are usually made through a directory handler object.\nA directory handler in Zig is an object of type `Dir`, which is an object that describes\na particular folder in the filesystem of our computer.\nYou normally create a `Dir` object, by calling the `std.fs.cwd()` function.\nThis function returns a `Dir` object that points to (or, that describes) the\ncurrent working directory (CWD).\n\nThrough this `Dir` object, you can create new files, or modify, or read existing ones that are\ninside your CWD. In other words, a `Dir` object is the main entrypoint in Zig to perform\nmultiple types of filesystem operations.\nIn the example below, we are creating this `Dir` object, and storing it\ninside the `cwd` object. Although we are not using this object at this code example,\nwe are going to use it a lot over the next examples.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\n_ = cwd;\n```\n:::\n\n\n\n\n\n\n\n\n\n\n## File operations\n\n### Creating files {#sec-creating-files}\n\nWe create new files by using the `createFile()` method from the `Dir` object.\nJust provide the name of the file that you want to create, and this function will\ndo the necessary steps to create such file. You can also provide a relative path to this function,\nand it will create the file by following this path, which is relative to the CWD.\n\nThis function might return an error, so, you should use `try`, `catch`, or any of the other methods presented\nin @sec-error-handling to handle the possible error. But if everything goes well,\nthis `createFile()` method returns a file descriptor object (i.e., a `File` object) as result,\nthrough which you can add content to the file with the IO operations that I presented before.\n\nTake this code example below. In this example, we are creating a new text file\nnamed `foo.txt`. If the function `createFile()` succeeds, the object named `file` will contain a file descriptor\nobject, which we can use to write (or add) new content to the file, like we do in this example, by using\na buffered writer object to write a new line of text to the file.\n\nNow, a quick note, when we create a file descriptor object in C, by using a C function like `fopen()`, we must always close the file\nat the end of our program, or, as soon as we complete all operations that we wanted to perform\non the file. In Zig, this is no different. So everytime we create a new file, this file remains\n\"open\", waiting for some operation to be performed. As soon as we are done with it, we always have\nto close this file, to free the resources associated with it.\nIn Zig, we do this by calling the method `close()` from the file descriptor object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.createFile(\"foo.txt\", .{});\n// Don't forget to close the file at the end.\ndefer file.close();\n// Do things with the file ...\nvar fw = file.writer();\n_ = try fw.writeAll(\n \"Writing this line to the file\\n\"\n);\n```\n:::\n\n\n\n\nSo, in this example we not only have created a file into the filesystem,\nbut we also wrote some data into this file, using the file descriptor object\nreturned by `createFile()`. If the file that you are trying to create\nalready exists in your filesystem, this `createFile()` call will\noverwrite the contents of the file, or, in other words, it will\nin erase all the contents of the existing file.\n\nIf you don't want this to happen, meaning, that you don't want to overwrite\nthe contents of the existing file, but you want to write data to this file anyway\n(i.e., you want to append data to the file), you should use the `openFile()`\nmethod from the `Dir` object.\n\nAnother important aspect about `createFile()` is that this method creates a file\nthat is not open to read operations by default. It means that you cannot read this file.\nYou are not allowed to.\nSo for example, you might want to write some stuff into this file at the beginning of the execution\nof your program. Then, at a future point in your program you might need to read what you\nwrote in this file. If you try to read data from this file, you will likely\nget a `NotOpenForReading` error as result.\n\n\nBut how can you overcome this barrier? How can you create a file that is open\nto read operations? All you have to do, is to set the `read` flag to true\nin the second argument of `createFile()`. When you set this flag to true,\nthen the file gets create with \"read permissions\", and, as consequence,\na program like this one below becomes valid:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.createFile(\n \"foo.txt\",\n .{ .read = true }\n);\ndefer file.close();\n\nvar fw = file.writer();\n_ = try fw.writeAll(\"We are going to read this line\\n\");\n\nvar buffer: [300]u8 = undefined;\n@memset(buffer[0..], 0);\ntry file.seekTo(0);\nvar fr = file.reader();\n_ = try fr.readAll(buffer[0..]);\ntry stdout.print(\"{s}\\n\", .{buffer});\n```\n:::\n\n\n\n\n```\nWe are going to read this line\n```\n\n\nIf you are not familiar with position indicators, you might not recognize the method\n`seekTo()`. If that is your case, do not worry,\nwe are going to talk more about this method in @sec-indicators. But essentially\nthis method is moving the position indicator back to the beginning of the file,\nso that we can read the contents of the file from the beginning.\n\n\n### Opening files and appending data to it\n\nOpening files is easy. Just use the `openFile()` method instead of `createFile()`.\nIn the first argument of `openFile()` you provide the path to the file that\nyou want to open. Then, on the second argument you provide the flags (or, the options)\nthat dictates how the file is opened.\n\nYou can see the full list of options for `openFile()` by visiting the documentation for\n[`OpenFlags`](https://ziglang.org/documentation/master/std/#std.fs.File.OpenFlags)[^oflags].\nBut the main flag that you will most certainly use is the `mode` flag.\nThis flag specifies the IO mode that the file will be using when it gets opened.\nThere are three IO modes, or, three values that you can provide to this flag, which are:\n\n- `read_only`, allows only read operations on the file. All write operations are blocked.\n- `write_only`, allows only write operations on the file. All read operations are blocked.\n- `read_write`, allows both write and read operations on the file.\n\n[^oflags]: \n\nThese modes are similar to the modes that you provide to the `mode` argument of the\n`open()` Python built-in function[^py-open], or, the `mode` argument of the\n`fopen()` C function[^c-open].\nIn the code example below, we are opening the `foo.txt` text file with a `write_only` mode,\nand appending a new line of text to the end of the file. We use `seekFromEnd()` this time\nto guarantee that we are going to append the text to the end of the file. Once again, methods\nsuch as `seekFromEnd()` are described in more depth in @sec-indicators.\n\n[^py-open]: \n[^c-open]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.openFile(\n \"foo.txt\", .{ .mode = .write_only }\n);\ndefer file.close();\ntry file.seekFromEnd(0);\nvar fw = file.writer();\n_ = try fw.writeAll(\"Some random text to write\\n\");\n```\n:::\n\n\n\n\n### Deleting files\n\nSometimes, we just need to delete/remove the files that we have.\nTo do that, we use the `deleteFile()` method. You just provide the path of the\nfile that you want to delete, and this method will try to delete the file located\nat this path.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.deleteFile(\"foo.txt\");\n```\n:::\n\n\n\n### Copying files\n\nTo copy existing files, we use the `copyFile()` method. The first argument in this method\nis the path to the file that you want to copy. The second argument is a `Dir` object, i.e., a directory handler,\nmore specifically, a `Dir` object that points to the folder in your computer where you want to\ncopy the file to. The third argument is the new path of the file, or, in other words, the new location\nof the file. The fourth argument is the options (or flags) to be used in the copy operation.\n\nThe `Dir` object that you provide as input to this method will be used to copy the file to\nthe new location. You may create this `Dir` object before calling the `copyFile()` method.\nMaybe you are planning to copy the file to a completely different location in your computer,\nso it might be worth to create a directory handler to that location. But if you are copying the\nfile to a subfolder of your CWD, then, you can just simply pass the CWD handler to this argument.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.copyFile(\n \"foo.txt\",\n cwd,\n \"ZigExamples/file-io/foo.txt\",\n .{}\n);\n```\n:::\n\n\n\n\n### Read the docs!\n\nThere are some other useful methods for file operations available at `Dir` objects,\nsuch as the `writeFile()` method, but I recommend you to read the docs for the\n[`Dir` type](https://ziglang.org/documentation/master/std/#std.fs.Dir)[^zig-dir]\nto explore the other available methods, since I already talked too much about them.\n\n\n[^zig-dir]: \n\n\n\n\n## Position indicators {#sec-indicators}\n\nA position indicator is like a type of cursor, or, an index. This \"index\" identifies the current\nlocation in the file (or, in the data stream) that the file descriptor object that you have\nis currently looking at.\nWhen you create a file descriptor, the position indicator starts at the beginning of the file,\nor, at the beginning of the stream. When you read from or write into the file (or socket, or data stream, etc.)\ndescribed by this file descriptor object, you end up moving the position indicator.\n\nIn other words, any IO operation have a common side effect, which is to move the position indicator.\nFor example, suppose that we have a file of 300 bytes total in size. If you\nread 100 bytes from the file, then, the position indicator moves 100 bytes forward. If you try\nto write 50 bytes into this same file, these 50 bytes will be written from the current\nposition indicated by the position indicator. Since the indicator is at a 100 bytes forward from\nthe beginning of the file, these 50 bytes would be written in the middle of the file.\n\nThis is why we have used the `seekTo()` method at the last code example presented in @sec-creating-files.\nWe have used this method to move the position indicator back to the beginning of the file, which\nwould make sure that we would write the text that we wanted to write from the beginning of the file,\ninstead of writing it from the middle of the file. Because before the write operation, we had\nperformed a read operation, which means that the position indicator was moved in this read operation.\n\nThe position indicators of a file descriptor object can be changed (or altered) by using the\n\"seek\" methods from this file descriptor, which are: `seekTo()`, `seekFromEnd()` and `seekBy()`.\nThese methods have the same effect, or, the same responsibility that the\n[`fseek()`](https://en.cppreference.com/w/c/io/fseek)[^c-fseek] C function.\n\n[^c-fseek]: \n\n\nConsidering that `offset` refers to the index that you provide as input to these \"seek\" methods,\nthe bullet points below summarises what is the effect of each of these methods.\nAs a quick note, in the case of `seekFromEnd()` and `seekBy()`, the `offset` provided can be either a\npositive or a negative index.\n\n- `seekTo()` will move the position indicator to the location that is `offset` bytes from the beginning of the file.\n- `seekFromEnd()` will move the position indicator to the location that is `offset` bytes from the end of the file.\n- `seekBy()` will move the position indicator to the location that is `offset` bytes from the current position in the file.\n\n\n\n\n\n\n\n## Directory operations\n\n### Iterating through the files in a directory\n\nOne of the most classic tasks related to filesystem is to be able\nto iterate through the existing files in a directory. To iterate over the\nfiles in a directory, we need to create an iterator object.\n\nYou can produce such iterator object by using either the `iterate()` or `walk()` methods\nof a `Dir` object. Both methods return an iterator object as output, which you can advance by using the\n`next()` method. The difference between these methods, is that `iterate()` returns a non-recursive iterator,\nwhile `walk()` does. It means that the iterator returned by `walk()` will not only iterate through\nthe files available in the current directory, but also, through the files from any subdirectory found\ninside the current directory.\n\nIn the example below, we are displaying the names of the files stored inside the\ndirectory `ZigExamples/file-io`. Notice that we had to open this directory through\nthe `openDir()` function. Also notice that we provided the flag `iterate` in the\nsecond argument of `openDir()`. This flag is important, because without this flag,\nwe would not be allowed to iterate through the files in this directory.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst dir = try cwd.openDir(\n \"ZigExamples/file-io/\",\n .{ .iterate = true }\n);\nvar it = dir.iterate();\nwhile (try it.next()) |entry| {\n try stdout.print(\n \"File name: {s}\\n\",\n .{entry.name}\n );\n}\n```\n:::\n\n\n\n```\nFile name: create_file_and_write_toit.zig\nFile name: create_file.zig\nFile name: lorem.txt\nFile name: iterate.zig\nFile name: delete_file.zig\nFile name: append_to_file.zig\nFile name: user_input.zig\nFile name: foo.txt\nFile name: create_file_and_read.zig\nFile name: buff_io.zig\nFile name: copy_file.zig\n```\n\n\n### Creating new directories\n\nThere are two methods that are important when it comes to\ncreating directories, which are `makeDir()` and `makePath()`.\nThe difference between these two methods is that `makeDir()` can\nonly create one single directory in the current directory in each call,\nwhile `makePath()` is capable of recursively create subdirectories in the same call.\n\n\nThis is why the name of this method is \"make path\". It will create as many\nsubdirectories as necessary to create the path that you provided as input.\nSo, if you provide the path `\"sub1/sub2/sub3\"` as input to this method,\nit will create three different subdirectories, `sub1`, `sub2` and `sub3`,\nwithin the same function call. In contrast, if you provided such path\nas input to `makeDir()`, you would likely get an error as result, since\nthis method can only create a single subdirectory.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.makeDir(\"src\");\ntry cwd.makePath(\"src/decoders/jpg/\");\n```\n:::\n\n\n\n### Deleting directories\n\nTo delete a directory, just provide the path to the directory that you want to delete\nas input to the `deleteDir()` method from a `Dir` object. In the example below,\nwe are deleting the `src` directory that we have just created in the previous example.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.deleteDir(\"src\");\n```\n:::\n\n\n\n\n## Conclusion\n\nIn this chapter, I have described how to perform in Zig the most common filesystem and IO operations.\nBut you might feel the lack of some other, less common, operation in this chapter, such as: how to rename files,\nor how to open a directory, or how to create symbolic links, or how to use `access()` to test if a particular\npath exists in your computer. But for all of these less common tasks, I recommend you to read\nthe documentation of the [`Dir` type](https://ziglang.org/documentation/master/std/#std.fs.Dir)[^zig-dir]\n, since you can find a good description of these cases there.\n", - "supporting": [ - "12-file-op_files" - ], - "filters": [ - "rmarkdown/pagebreak.lua" - ], - "includes": {}, - "engineDependencies": { - "knitr": [ - "{\"type\":\"list\",\"attributes\":{},\"value\":[]}" - ] - }, - "preserve": null, - "postProcess": false - } -} \ No newline at end of file diff --git a/_freeze/Chapters/12-file-op/execute-results/html.json b/_freeze/Chapters/12-file-op/execute-results/html.json index f21b00fa..5ebb0a55 100644 --- a/_freeze/Chapters/12-file-op/execute-results/html.json +++ b/_freeze/Chapters/12-file-op/execute-results/html.json @@ -2,10 +2,8 @@ "hash": "1e79228e1613c85b9e688833811e2fda", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n\n# Filesystem and Input/Output (IO) {#sec-filesystem}\n\nIn this chapter we are going to discuss how to use the cross-platform structs and functions\nfrom the Zig Standard Library that can execute filesystem operations. Most of these functions and structs\ncomes from the `std.fs` module.\n\nWe are also going to talk about Input/Output (also known as IO) operations in Zig. Most of\nthese operations are made by using the structs and functions from `std.io` module, which defines\nfile descriptors for the *standard channels* of your system (`stdout` and `stdin`), and also,\nfunctions to create and use I/O streams.\n\n\n## Input/Output basics {#sec-io-basics}\n\nIf you have some experience in a high-level language, you have certainly used\nthese input and output functionalities before in this language. In other words, you certainly have\nbeen in a situation where you needed to sent some output to the user, or, to receive an input\nfrom the user.\n\nFor example, in Python we can receive some input from the user by using the `input()` built-in\nfunction. But we can also print (or \"show\") some output to the user by using the `print()`\nbuilt-in function. So yes, if you have programmed before in Python, you certainly have\nused these functions once before.\n\nBut do you know how these functions relate back to your operating system (OS)? How exactly\nthey are interacting with the resources of your OS to receive or sent some input/output.\nIn essence, these input/output functions from high-level languages are just abstractions\nover the *standard output* and *standard input* channels of your operating system.\n\nThis means that we receive an input, or send some output, through the operating system.\nIt's the OS that makes the bridge between the user and your program. Your program\ndoes not have a direct access to the user. It's the OS that intermediates every\nmessage exchanged between your program and the user.\n\nThe *standard output* and *standard input* channels of your OS are commonly known as the\n`stdout` and `stdin` channels of your OS, respectively. In some contexts, they are also\ncalled the *standard output device* and the *standard input device*. As the name suggests,\nthe *standard output* is the channel through which output flows, while the *standard input*\nis the channel in which input flows.\n\nFurthermore, OS's also normally create a dedicated channel for exchanging error messages, which is known as the\n*standard error* channel, or, the `stderr` channel. This is the channel to which error and warning messages\nare usually sent to. These are the messages that are normally displayed in red-like or orange-like colors\ninto your terminal.\n\nNormally, every OS (e.g. Windows, macOS, Linux, etc.) creates a dedicated and separate set of\n*standard output*, *standard error* and *standard input* channels for every single program (or process) that runs in your computer.\nThis means that every program you write have a dedicated `stdin`, `stderr` and `stdout` that are separate\nfrom the `stdin`, `stderr` and `stdout` of other programs and processes that are currently running.\n\nThis is a behaviour from your OS. This does not come from the programming language that you are using.\nBecause as I sad earlier, input and output in programming languages, especially\nin high-level ones, are just a simple abstraction over the `stdin`, `stderr` and `stdout` from your current OS.\nThat is, your OS is the intermediary between every input/output operation made in your program,\nregardless of the programming language that you are using.\n\n\n### The writer and reader pattern {#sec-writer-reader}\n\nIn Zig, there is a pattern around input/output (IO). I (the author of this book) don't know if there\nis an official name for this pattern. But here, in this book, I will call it the \"writer and reader pattern\".\nIn essence, every IO operation in Zig is made through either a `GenericReader` or a `GenericWriter` object[^gen-zig].\n\nThese two data types come from the `std.io` module of the Zig Standard Library. As their names suggests, a\n`GenericReader` is an object that offers tools to read data from \"something\" (or \"somewhere\"), while a `GenericWriter`\noffers tools to write data into this \"something\". This \"something\" might be different things: like a\nfile that exists in your filesystem; or, it might be a network socket in your system[^sock]; or,\na continuous stream of data, like a standard input device from your system, that might be constantly\nreceiving new data from users, or, as another example, a live chat in a game that is constantly\nreceiving and displaying new messages from the players of the game.\n\n[^gen-zig]: Previously, these objects were known as the `Reader` and `Writer` objects.\n[^sock]: The socket objects that we have created in @sec-create-socket, are examples of network sockets.\n\nSo, if you want to **read** data from something, or somewhere, it means that you need to use a `GenericReader` object.\nBut if you need instead, to **write** data into this \"something\", then, you need to use a `GenericWriter` object instead.\nBoth of these objects are normally created from a file descriptor object. More specifically, through the `writer()` and `reader()`\nmethods of this file descriptor object. If you are not familiar with this type of object, go to the next section.\n\nEvery `GenericWriter` object have methods like `print()`, which allows you to write/send a formatted string\n(i.e., this formatted string is like a `f` string in Python, or, similar to the `printf()` C function)\ninto the \"something\" (file, socket, stream, etc.) that you are using. It also have a `writeAll()` method, which allows you to\nwrite a string, or, an array of bytes into the \"something\".\n\nLikewise, every `GenericReader` object have methods like `readAll()`, which allows you to read the\ndata from the \"something\" (file, socket, stream, etc.) until it fills a particular array (i.e., a \"buffer\") object.\nIn other words, if you provide an array object of 300 `u8` values to `readAll()`, then, this method attempts to read 300 bytes\nof data from the \"something\", and it stores them into the array object that you have provided.\n\nWe also have other methods, like the `readAtLeast()` method, which allows you to specify how\nmany bytes exactly you want to read from the \"something\". In more details, if you give the\nnumber $n$ as input to this method, then, it will attempt to read at least $n$ bytes of data\nfrom the \"something\". The \"something\" might have less than $n$ bytes of data available for you\nto read, so, it's not guaranteed that you will get precisely $n$ bytes as result.\n\nAnother useful method is `readUntilDelimiterOrEof()`. In this method, you specify a \"delimiter character\".\nThe idea is that this function will attempt to read as many bytes of data as possible from the \"something\",\nuntil it encounters the end of the stream, or, it encounters the \"delimiter character\" that you have specified.\n\nIf you don't know exactly how many bytes will come from the \"something\", you may find the `readAllAlloc()` method\nuseful. In essence, you provide an allocator object to this method, so that it can allocate more space if needed.\nAs consequence, this method will try to read all bytes of the \"something\", and, if it runs out of space at some point\nduring the \"reading process\", it uses the allocator object to allocate more space to continue reading the bytes.\nAs result, this method returns a slice to the array object containing all the bytes read.\n\nThis is just a quick description of the methods present in these types of objects. But I recommend you\nto read the official docs, both for\n[`GenericWriter`](https://ziglang.org/documentation/master/std/#std.io.GenericWriter)[^gen-write] and\n[`GenericReader`](https://ziglang.org/documentation/master/std/#std.io.GenericReader)[^gen-read].\nI also think it's a good idea to read the source code of the modules in the Zig Standard Library\nthat defines the methods present in these objects, which are the\n[`Reader.zig`](https://github.com/ziglang/zig/blob/master/lib/std/io/Reader.zig)[^mod-read]\nand [`Writer.zig`]()[^mod-write].\n\n[^gen-read]: .\n[^gen-write]: .\n[^mod-read]: .\n[^mod-write]: .\n\n\n\n### Introducing file descriptors {#sec-file-descriptor}\n\nA \"file descriptor\" object is a core component behind every IO operation that is made in any operating system (OS).\nSuch object is an identifier for a particular input/output (IO) resource from your OS [@wiki_file_descriptor].\nIt describes and identifies this particular resource. An IO resource might be:\n\n- an existing file in your filesystem.\n- an existing network socket.\n- other types of stream channels.\n- a pipeline (or just \"pipe\") in your terminal[^pipes].\n\n[^pipes]: A pipeline is a mechanism for inter-process communication, or, inter-process IO. You could also interpret a pipeline as a \"set of processes that are chained together, through the standard input/output devices of the system\". At Linux for example, a pipeline is created inside a terminal, by connecting two or more terminal commands with the \"pipe\" character (`|`).\n\nFrom the bullet points listed above, we know that although the term \"file\" is present,\na \"file descriptor\" might describe something more than just a file.\nThis concept of a \"file descriptor\" comes from the Portable Operating System Interface (POSIX) API,\nwhich is a set of standards that guide how operating systems across the world should be implemented,\nto maintain compatibility between them.\n\nA file descriptor not only identifies the input/output resource that you are using to receive or send some data,\nbut it also describes where this resource is, and also, which IO mode this resource is currently using.\nFor example, this IO resource might be using only the \"read\" IO mode, which means that this resource\nis open to \"read operations\", while \"write operations\" are not authorized.\nThese IO modes are essentially the modes that you provide to the argument `mode`\nfrom the `fopen()` C function, and also, from the `open()` Python built-in function.\n\nIn C, a \"file descriptor\" is a `FILE` pointer, but, in Zig, a file descriptor is a `File` object.\nThis data type (`File`) is described in the `std.fs` module of the Zig Standard Library.\nWe normally don't create a `File` object directly in our Zig code. Instead, we normally get such object as result when we\nopen an IO resource. In other words, we normally ask our OS to open a particular IO resource for us,\nand, if the OS do open successfully this IO resource, the OS normally handles back to us\na file descriptor to this particular IO resource.\n\nSo you usually get a `File` object by using functions and methods from the Zig Standard Library\nthat asks the OS to open some IO resource, like the `openFile()` method that opens a file in the\nfilesystem. The `net.Stream` object that we have created in @sec-create-socket is also a type of\nfile descriptor object.\n\n\n### The *standard output*\n\nYou already saw across this book, how can we access and use specifically the `stdout` in Zig\nto send some output to the user.\nFor that, we use the `getStdOut()` function from the `std.io` module. This function returns\na file descriptor that describes the `stdout` channel of your current OS. Through this file\ndescriptor object, we can read from or write stuff to the `stdout` of our program.\n\nAlthough we can read stuff recorded into the `stdout` channel, we normally only\nwrite to (or \"print\") stuff into this channel. The reason is very similar to what we discussed at\n@sec-read-http-message, when we were discussing what \"reading from\" versus \"writing to\" the connection\nobject from our small HTTP Server project would mean.\n\nWhen we write stuff into a channel, we are essentially sending data to the other end of this channel.\nIn contrast, when we read stuff from this channel, we are essentially reading the data that was sent\nthrough this channel. Since the `stdout` is a channel to send output to the user, the key verb here\nis **send**. We want to send something to someone, and, as consequence, we want to **write** something\ninto some channel.\n\nThat is why, when we use `getStdOut()`, most of the times, we also use the `writer()` method from the `stdout` file descriptor,\nto get access to a writer object that we can use to write stuff into this `stdout` channel.\nMore specifically, this `writer()` method returns a `GenericWriter` object. One of the\nmain methods of this `GenericWriter` object is the `print()` method that we have used\nbefore to write (or \"print\") a formatted string into the `stdout` channel.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n try stdout.writeAll(\n \"This message was written into stdout.\\n\"\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nThis message was written into stdout.\n```\n\n\n:::\n:::\n\n\n\n\n\n\nThis `GenericWriter` object is like any other generic writer object that you would normally get from a file descriptor object.\nSo, the same methods from a generic writer object that you would use while writing files to the filesystem for example, you could also\nuse them here, from the file descriptor object of `stdout`, and vice-versa.\n\n\n### The *standard input*\n\nYou can access the *standard input* (i.e., `stdin`) in Zig by using the `getStdIn()` function from the `std.io` module.\nLike its brother (`getStdOut()`), this function also returns a file descriptor object that describes the `stdin` channel\nof your OS.\n\nBecause we want to receive some input from the user, the key verb here becomes **receive**, and, as consequence,\nwe usually want to **read** data from the `stdin` channel, instead of writing data into it. So, we normally use\nthe `reader()` method of the file descriptor object returned by `getStdIn()`, to get access to a `GenericReader`\nobject that we can use to read data from `stdin`.\n\nIn the example below, we are creating a small buffer capable of holding 20 characters. Then, we try to read\nthe data from the `stdin` with the `readUntilDelimiterOrEof()` method, and save this data into the `buffer` object.\nAlso notice that we are reading the data from the `stdin` until we hit a new line character (`'\\n'`).\n\nIf you execute this program, you will notice that it stops the execution, ands start to wait indefinitely\nfor some input from the user. In other words, you need to type your name into the terminal, and then, you press Enter to\nsend your name to `stdin`. After you send your name to `stdin`, the program reads this input, and continues with the execution,\nby printing the given name to `stdout`. In the example below, I typed my name (Pedro) into the terminal, and then, pressed Enter.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst stdin = std.io.getStdIn().reader();\npub fn main() !void {\n try stdout.writeAll(\"Type your name\\n\");\n var buffer: [20]u8 = undefined;\n @memset(buffer[0..], 0);\n _ = try stdin.readUntilDelimiterOrEof(buffer[0..], '\\n');\n try stdout.print(\"Your name is: {s}\\n\", .{buffer});\n}\n```\n:::\n\n\n\n\n```\nType your name\nYour name is: Pedro\n\n```\n\n\n### The *standard error*\n\nThe *standard error* (a.k.a. the `stderr`) works exactly the same as `stdout` and `stdin`.\nYou just call the `getStdErr()` function from the `std.io` module, and you get the file descriptor to `stderr`.\nIdeally, you should write only error or warning messages to `stderr`, because this is\nthe purpose of this channel.\n\n\n\n\n\n## Buffered IO\n\nAs we described in @sec-io-basics, input/output (IO) operations are made directly by the operating system.\nIt's the OS that manages the IO resource that you want to use for your IO operations.\nThe consequence of this fact is that IO operations are heavily based on system calls (i.e., calling the operating system directly).\n\nJust to be clear, there is nothing particularly wrong with system calls. We use them all the time on\nany serious codebase written in any low-level programming language. However, system calls are\nalways orders of magnitude slower than many different types of operations.\n\nSo is perfectly fine to use a system call once in a while. But when these system calls are used often,\nyou can clearly notice most of the time the loss of performance in your application. So, the good rule of thumb\nis to use a system call only when it's needed, and also, only in infrequent situations, to reduce\nthe number of system calls performed to a minimum.\n\n\n### Understanding how buffered IO works\n\nBuffered IO is a strategy to achieve better performance. It's used to reduce the number of system calls made by IO operations, and, as\nconsequence, achieve a much higher performance. In @fig-unbuffered-io and @fig-buffered-io you can find two different diagrams\nwhich presents the difference between read operations performed in an unbuffered IO environment versus a buffered IO environment.\n\nTo give a better context to these diagrams, let's suppose that we have a text file that contains the famous Lorem ipsum text[^lorem]\nin our filesystem. Let's also suppose that these diagrams in @fig-unbuffered-io and @fig-buffered-io\nare showing the read operations that we are performing to read the Lorem ipsum text from this text file.\nThe first thing you will notice when looking at these diagrams, is that in an unbuffered environment\nthe read operations leads to many system calls.\nMore precisely, in the diagram exposed in @fig-unbuffered-io we get one system call per each byte that we read from the text file.\nOn the other hand, in @fig-buffered-io we have only one system call at the very beginning.\n\nWhen we use a buffered IO system, at the first read operation we perform, instead of sending one single byte directly\nto our program, the OS first sends a chunk of bytes from the file to a buffer object (i.e., an array).\nThis chunk of bytes are cached/stored inside this buffer object.\n\nTherefore, from now on, for every new read operation that you perform, instead of making a new system call to ask\nfor the next byte in the file to the OS, this read operation is redirected to the buffer object, that have\nthis next byte already cached and ready to go.\n\n\n[^lorem]: .\n\n\n![Unbuffered IO](./../Figures/unbuffered-io.png){#fig-unbuffered-io width=60%}\n\n![Buffered IO](./../Figures/buffered-io.png){#fig-buffered-io}\n\n\n\nThis is the basic logic behind buffered IO systems. The size of the buffer object depends on multiple factors. But it's usually\nequal to the size of a full page of memory (4096 bytes). If we follow this logic, then, the OS reads the first 4096 bytes\nof the file and caches it into the buffer object. As long as your program does not consume all of these 4096 bytes from the buffer,\nyou will not create new system calls.\n\nHowever, as soon as you consume all of these 4096 bytes from the buffer, it means that there is no bytes left in the buffer.\nIn this situation, a new system call is made to ask the OS to send the next 4096 bytes in the file, and once again,\nthese bytes are cached into the buffer object, and the cycle starts once again.\n\n\n### Buffered IO across different languages\n\nIO operations made through a `FILE` pointer in C are buffered\nby default, so, at least in C, you don't need to worry about this subject. But in contrast, IO operations in both Rust and Zig are not\nbuffered depending on which functions from the standard libraries that you are using.\n\nFor example, in Rust, buffered IO is implemented through the `BufReader` and `BufWriter` structs, while in Zig, it's implemented\nthrough the `BufferedReader` and `BufferedWriter` structs.\nSo any IO operation that you perform through the `GenericWriter` and `GenericReader` objects\nthat I presented in @sec-writer-reader are not buffered, which means that these objects\nmight create a lot of system calls depending on the situation.\n\n\n### Using buffered IO in Zig\n\nUsing buffered IO in Zig is actually very easy. All you have to do is to just\ngive the `GenericWriter` object to the `bufferedWriter()` function, or, to give the `GenericReader`\nobject to the `bufferedReader()` function. These functions come from the `std.io` module,\nand they will construct the `BufferedWriter` or `BufferedReader` object for you.\n\nAfter you create this new `BufferedWriter` or `BufferedReader` object, you can call the `writer()`\nor `reader()` method of this new object, to get access to a new (and buffered) generic reader or\ngeneric writer.\n\nLet's describe the process once again. Every time that you have a file descriptor object, you first get the generic writer or generic reader\nobject from it, by calling the `writer()` or `reader()` methods of this file descriptor object.\nThen, you provide this generic writer or generic reader to the `bufferedWriter()` or `bufferedReader()`\nfunction, which creates a new `BufferedWriter` or `BufferedReader` object. Then, you call\nthe `writer()` or `reader()` methods of this buffered writer or buffered reader object,\nwhich gives you access to a generic writer or a generic reader object that is buffered.\n\nTake this program as an example. This program is demonstrating the process exposed in @fig-buffered-io.\nWe are simply opening a text file that contains the Lorem ipsum text, and then, we create a buffered IO reader object\nat `bufreader`, and we use this `bufreader` object to read the contents of this file into a buffer object, then,\nwe end the program by printing this buffer to `stdout`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar file = try std.fs.cwd().openFile(\n \"ZigExamples/file-io/lorem.txt\", .{}\n);\ndefer file.close();\nvar buffered = std.io.bufferedReader(file.reader());\nvar bufreader = buffered.reader();\n\nvar buffer: [1000]u8 = undefined;\n@memset(buffer[0..], 0);\n\n_ = try bufreader.readUntilDelimiterOrEof(\n buffer[0..], '\\n'\n);\ntry stdout.print(\"{s}\\n\", .{buffer});\n```\n:::\n\n\n\n\n```\nLorem ipsum dolor sit amet, consectetur\nadipiscing elit. Sed tincidunt erat sed nulla ornare, nec\naliquet ex laoreet. Ut nec rhoncus nunc. Integer magna metus,\nultrices eleifend porttitor ut, finibus ut tortor. Maecenas\nsapien justo, finibus tincidunt dictum ac, semper et lectus.\nVivamus molestie egestas orci ac viverra. Pellentesque nec\narcu facilisis, euismod eros eu, sodales nisl. Ut egestas\nsagittis arcu, in accumsan sapien rhoncus sit amet. Aenean\nneque lectus, imperdiet ac lobortis a, ullamcorper sed massa.\nNullam porttitor porttitor erat nec dapibus. Ut vel dui nec\nnulla vulputate molestie eget non nunc. Ut commodo luctus ipsum,\nin finibus libero feugiat eget. Etiam vel ante at urna tincidunt\nposuere sit amet ut felis. Maecenas finibus suscipit tristique.\nDonec viverra non sapien id suscipit.\n```\n\nDespite being a buffered IO reader, this `bufreader` object is similar to any other `GenericReader` object,\nand have the exact same methods. So, although these two types of objects perform very different IO operations,\nthey have the same interface, so you, the programmer, can interchangeably use them\nwithout the need to change anything in your source code.\nSo a buffered IO reader or a buffered IO writer objects have the same methods than its generic and unbuffered brothers,\ni.e., the generic reader and generic writer objects that I presented in @sec-writer-reader.\n\n::: {.callout-tip}\nIn general, you should always use a buffered IO reader or a buffered IO writer object to perform\nIO operations in Zig. Because they deliver better performance to your IO operations.\n:::\n\n\n## Filesystem basics\n\nNow that we have discussed the basics around Input/Output operations in Zig, we need to\ntalk about the basics around filesystems, which is another core part of any operating system.\nAlso, filesystems are related to input/output, because the files that we store and create in our\ncomputer are considered an IO resource, as we described in @sec-file-descriptor.\n\n\n### The concept of current working directory (CWD)\n\nThe working directory is the folder on your computer where you are currently rooted at.\nIn other words, it's the folder that your program is currently looking at.\nTherefore, whenever you are executing a program, this program is always working with\na specific folder on your computer. It's always in this folder that the program will initially\nlook for the files you require, and it's also in this folder that the program\nwill initially save all the files you ask it to save.\n\nThe working directory is determined by the folder from which you invoke your program\nin the terminal. In other words, if you are in the terminal of your OS, and you\nexecute a binary file (i.e., a program) from this terminal, the folder to which your terminal\nis pointing at is the current working directory of your program that is being executed.\n\nIn @fig-cwd we have an example of me executing a program from the terminal. We are executing\nthe program outputted by the `zig` compiler by compiling the Zig module named `hello.zig`.\nThe CWD in this case is the `zig-book` folder. In other words, while the `hello.zig` program\nis executing, it will be looking at the `zig-book` folder, and any file operation that we perform\ninside this program, will be using this `zig-book` folder as the \"starting point\", or, as the \"central focus\".\n\n![Executing a program from the terminal](./../Figures/cwd.png){#fig-cwd}\n\nJust because we are rooted inside a particular folder (in the case of @fig-cwd, the `zig-book` folder) of our computer,\nit doesn't mean that we cannot access or write resources in other locations of our computer.\nThe current working directory (CWD) mechanism just defines where your program will look first\nfor the files you ask for. This does not prevent you from accessing files that are located\nelsewhere on your computer. However, to access any file that is in a folder other than your\ncurrent working directory, you must provide a path to that file or folder.\n\n\n### The concept of paths\n\nA path is essentially a location. It points to a location in your filesystem. We use\npaths to describe the location of files and folders in our computer.\nOne important aspect about paths is that they are always written inside strings,\ni.e., they are always provided as text values.\n\nThere are two types of paths that you can provide to any program in any OS: a relative path, or an absolute path.\nAbsolute paths are paths that start at the root of your filesystem, and go all the way to the file name or the specific folder\nthat you are referring to. This type of path is called absolute, because it points to an unique and absolute location on your computer.\nThat is, there is no other existing location on your computer that corresponds to this path. It's an unique identifier.\n\nIn Windows, an absolute path is a path that starts with a hard disk identifier (e.g. `C:/Users/pedro`).\nOn the other hand, absolute paths in Linux and macOS, are paths that start with a forward slash character (e.g. `/usr/local/bin`).\nNotice that a path is composed by \"segments\". Each segment is connected to each other by a slash character (`\\` or `/`).\nOn Windows, the backward slash (`\\`) is normally used to connect the path segments. While on Linux and macOS, the forward\nslash (`/`) is the character used to connect path segments.\n\nA relative path is a path that start at the CWD. In other words, a relative path is\n\"relative to the CWD\". The path used to access the `hello.zig` file in @fig-cwd is an example of a relative path. This path\nis reproduced below. This path begins at the CWD, which in the context of @fig-cwd, is the `zig-book` folder,\nthen, it goes to the `ZigExamples` folder, then, into `zig-basics`, then, to the `hello.zig` file.\n\n```\nZigExamples/zig-basics/hello_world.zig\n```\n\n\n### Path wildcards\n\nWhen providing paths, especially relative paths, you have the option of using a *wildcard*.\nThere are two commonly used *wildcards* in paths, which are \"one period\" (.) and \"two periods\" (..).\nIn other words, these two specific characters have special meanings when used in paths,\nand can be used on any operating system (Mac, Windows, Linux, etc.). That is, they\nare \"cross platform\".\n\nThe \"one period\" represents an alias for the current directory.\nThis means that the relative paths `\"./Course/Data/covid.csv\"` and `\"Course/Data/covid.csv\"` are equivalent.\nOn the other hand, the \"two periods\" refers to the previous directory.\nFor example, the path `\"Course/..\"` is equivalent to the path `\".\"`, that is, the current working directory.\n\nTherefore, the path `\"Course/..\"` refers to the folder before the `Course` folder.\nAs another example, the path `\"src/writexml/../xml.cpp\"` refers to the file `xml.cpp`\nthat is inside the folder before the `writexml` folder, which in this example is the `src` folder.\nTherefore, this path is equivalent to `\"src/xml.cpp\"`.\n\n\n\n\n## The CWD handler\n\nIn Zig, filesystem operations are usually made through a directory handler object.\nA directory handler in Zig is an object of type `Dir`, which is an object that describes\na particular folder in the filesystem of our computer.\nYou normally create a `Dir` object, by calling the `std.fs.cwd()` function.\nThis function returns a `Dir` object that points to (or, that describes) the\ncurrent working directory (CWD).\n\nThrough this `Dir` object, you can create new files, or modify, or read existing ones that are\ninside your CWD. In other words, a `Dir` object is the main entrypoint in Zig to perform\nmultiple types of filesystem operations.\nIn the example below, we are creating this `Dir` object, and storing it\ninside the `cwd` object. Although we are not using this object at this code example,\nwe are going to use it a lot over the next examples.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\n_ = cwd;\n```\n:::\n\n\n\n\n\n\n\n\n\n\n\n## File operations\n\n### Creating files {#sec-creating-files}\n\nWe create new files by using the `createFile()` method from the `Dir` object.\nJust provide the name of the file that you want to create, and this function will\ndo the necessary steps to create such file. You can also provide a relative path to this function,\nand it will create the file by following this path, which is relative to the CWD.\n\nThis function might return an error, so, you should use `try`, `catch`, or any of the other methods presented\nin @sec-error-handling to handle the possible error. But if everything goes well,\nthis `createFile()` method returns a file descriptor object (i.e., a `File` object) as result,\nthrough which you can add content to the file with the IO operations that I presented before.\n\nTake this code example below. In this example, we are creating a new text file\nnamed `foo.txt`. If the function `createFile()` succeeds, the object named `file` will contain a file descriptor\nobject, which we can use to write (or add) new content to the file, like we do in this example, by using\na buffered writer object to write a new line of text to the file.\n\nNow, a quick note, when we create a file descriptor object in C, by using a C function like `fopen()`, we must always close the file\nat the end of our program, or, as soon as we complete all operations that we wanted to perform\non the file. In Zig, this is no different. So everytime we create a new file, this file remains\n\"open\", waiting for some operation to be performed. As soon as we are done with it, we always have\nto close this file, to free the resources associated with it.\nIn Zig, we do this by calling the method `close()` from the file descriptor object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.createFile(\"foo.txt\", .{});\n// Don't forget to close the file at the end.\ndefer file.close();\n// Do things with the file ...\nvar fw = file.writer();\n_ = try fw.writeAll(\n \"Writing this line to the file\\n\"\n);\n```\n:::\n\n\n\n\n\nSo, in this example we not only have created a file into the filesystem,\nbut we also wrote some data into this file, using the file descriptor object\nreturned by `createFile()`. If the file that you are trying to create\nalready exists in your filesystem, this `createFile()` call will\noverwrite the contents of the file, or, in other words, it will\nin erase all the contents of the existing file.\n\nIf you don't want this to happen, meaning, that you don't want to overwrite\nthe contents of the existing file, but you want to write data to this file anyway\n(i.e., you want to append data to the file), you should use the `openFile()`\nmethod from the `Dir` object.\n\nAnother important aspect about `createFile()` is that this method creates a file\nthat is not open to read operations by default. It means that you cannot read this file.\nYou are not allowed to.\nSo for example, you might want to write some stuff into this file at the beginning of the execution\nof your program. Then, at a future point in your program you might need to read what you\nwrote in this file. If you try to read data from this file, you will likely\nget a `NotOpenForReading` error as result.\n\n\nBut how can you overcome this barrier? How can you create a file that is open\nto read operations? All you have to do, is to set the `read` flag to true\nin the second argument of `createFile()`. When you set this flag to true,\nthen the file gets create with \"read permissions\", and, as consequence,\na program like this one below becomes valid:\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.createFile(\n \"foo.txt\",\n .{ .read = true }\n);\ndefer file.close();\n\nvar fw = file.writer();\n_ = try fw.writeAll(\"We are going to read this line\\n\");\n\nvar buffer: [300]u8 = undefined;\n@memset(buffer[0..], 0);\ntry file.seekTo(0);\nvar fr = file.reader();\n_ = try fr.readAll(buffer[0..]);\ntry stdout.print(\"{s}\\n\", .{buffer});\n```\n:::\n\n\n\n\n\n```\nWe are going to read this line\n```\n\n\nIf you are not familiar with position indicators, you might not recognize the method\n`seekTo()`. If that is your case, do not worry,\nwe are going to talk more about this method in @sec-indicators. But essentially\nthis method is moving the position indicator back to the beginning of the file,\nso that we can read the contents of the file from the beginning.\n\n\n### Opening files and appending data to it\n\nOpening files is easy. Just use the `openFile()` method instead of `createFile()`.\nIn the first argument of `openFile()` you provide the path to the file that\nyou want to open. Then, on the second argument you provide the flags (or, the options)\nthat dictates how the file is opened.\n\nYou can see the full list of options for `openFile()` by visiting the documentation for\n[`OpenFlags`](https://ziglang.org/documentation/master/std/#std.fs.File.OpenFlags)[^oflags].\nBut the main flag that you will most certainly use is the `mode` flag.\nThis flag specifies the IO mode that the file will be using when it gets opened.\nThere are three IO modes, or, three values that you can provide to this flag, which are:\n\n- `read_only`, allows only read operations on the file. All write operations are blocked.\n- `write_only`, allows only write operations on the file. All read operations are blocked.\n- `read_write`, allows both write and read operations on the file.\n\n[^oflags]: \n\nThese modes are similar to the modes that you provide to the `mode` argument of the\n`open()` Python built-in function[^py-open], or, the `mode` argument of the\n`fopen()` C function[^c-open].\nIn the code example below, we are opening the `foo.txt` text file with a `write_only` mode,\nand appending a new line of text to the end of the file. We use `seekFromEnd()` this time\nto guarantee that we are going to append the text to the end of the file. Once again, methods\nsuch as `seekFromEnd()` are described in more depth in @sec-indicators.\n\n[^py-open]: \n[^c-open]: \n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.openFile(\n \"foo.txt\", .{ .mode = .write_only }\n);\ndefer file.close();\ntry file.seekFromEnd(0);\nvar fw = file.writer();\n_ = try fw.writeAll(\"Some random text to write\\n\");\n```\n:::\n\n\n\n\n\n### Deleting files\n\nSometimes, we just need to delete/remove the files that we have.\nTo do that, we use the `deleteFile()` method. You just provide the path of the\nfile that you want to delete, and this method will try to delete the file located\nat this path.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.deleteFile(\"foo.txt\");\n```\n:::\n\n\n\n\n### Copying files\n\nTo copy existing files, we use the `copyFile()` method. The first argument in this method\nis the path to the file that you want to copy. The second argument is a `Dir` object, i.e., a directory handler,\nmore specifically, a `Dir` object that points to the folder in your computer where you want to\ncopy the file to. The third argument is the new path of the file, or, in other words, the new location\nof the file. The fourth argument is the options (or flags) to be used in the copy operation.\n\nThe `Dir` object that you provide as input to this method will be used to copy the file to\nthe new location. You may create this `Dir` object before calling the `copyFile()` method.\nMaybe you are planning to copy the file to a completely different location in your computer,\nso it might be worth to create a directory handler to that location. But if you are copying the\nfile to a subfolder of your CWD, then, you can just simply pass the CWD handler to this argument.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.copyFile(\n \"foo.txt\",\n cwd,\n \"ZigExamples/file-io/foo.txt\",\n .{}\n);\n```\n:::\n\n\n\n\n\n### Read the docs!\n\nThere are some other useful methods for file operations available at `Dir` objects,\nsuch as the `writeFile()` method, but I recommend you to read the docs for the\n[`Dir` type](https://ziglang.org/documentation/master/std/#std.fs.Dir)[^zig-dir]\nto explore the other available methods, since I already talked too much about them.\n\n\n[^zig-dir]: \n\n\n\n\n## Position indicators {#sec-indicators}\n\nA position indicator is like a type of cursor, or, an index. This \"index\" identifies the current\nlocation in the file (or, in the data stream) that the file descriptor object that you have\nis currently looking at.\nWhen you create a file descriptor, the position indicator starts at the beginning of the file,\nor, at the beginning of the stream. When you read from or write into the file (or socket, or data stream, etc.)\ndescribed by this file descriptor object, you end up moving the position indicator.\n\nIn other words, any IO operation have a common side effect, which is to move the position indicator.\nFor example, suppose that we have a file of 300 bytes total in size. If you\nread 100 bytes from the file, then, the position indicator moves 100 bytes forward. If you try\nto write 50 bytes into this same file, these 50 bytes will be written from the current\nposition indicated by the position indicator. Since the indicator is at a 100 bytes forward from\nthe beginning of the file, these 50 bytes would be written in the middle of the file.\n\nThis is why we have used the `seekTo()` method at the last code example presented in @sec-creating-files.\nWe have used this method to move the position indicator back to the beginning of the file, which\nwould make sure that we would write the text that we wanted to write from the beginning of the file,\ninstead of writing it from the middle of the file. Because before the write operation, we had\nperformed a read operation, which means that the position indicator was moved in this read operation.\n\nThe position indicators of a file descriptor object can be changed (or altered) by using the\n\"seek\" methods from this file descriptor, which are: `seekTo()`, `seekFromEnd()` and `seekBy()`.\nThese methods have the same effect, or, the same responsibility that the\n[`fseek()`](https://en.cppreference.com/w/c/io/fseek)[^c-fseek] C function.\n\n[^c-fseek]: \n\n\nConsidering that `offset` refers to the index that you provide as input to these \"seek\" methods,\nthe bullet points below summarises what is the effect of each of these methods.\nAs a quick note, in the case of `seekFromEnd()` and `seekBy()`, the `offset` provided can be either a\npositive or a negative index.\n\n- `seekTo()` will move the position indicator to the location that is `offset` bytes from the beginning of the file.\n- `seekFromEnd()` will move the position indicator to the location that is `offset` bytes from the end of the file.\n- `seekBy()` will move the position indicator to the location that is `offset` bytes from the current position in the file.\n\n\n\n\n\n\n\n## Directory operations\n\n### Iterating through the files in a directory\n\nOne of the most classic tasks related to filesystem is to be able\nto iterate through the existing files in a directory. To iterate over the\nfiles in a directory, we need to create an iterator object.\n\nYou can produce such iterator object by using either the `iterate()` or `walk()` methods\nof a `Dir` object. Both methods return an iterator object as output, which you can advance by using the\n`next()` method. The difference between these methods, is that `iterate()` returns a non-recursive iterator,\nwhile `walk()` does. It means that the iterator returned by `walk()` will not only iterate through\nthe files available in the current directory, but also, through the files from any subdirectory found\ninside the current directory.\n\nIn the example below, we are displaying the names of the files stored inside the\ndirectory `ZigExamples/file-io`. Notice that we had to open this directory through\nthe `openDir()` function. Also notice that we provided the flag `iterate` in the\nsecond argument of `openDir()`. This flag is important, because without this flag,\nwe would not be allowed to iterate through the files in this directory.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst dir = try cwd.openDir(\n \"ZigExamples/file-io/\",\n .{ .iterate = true }\n);\nvar it = dir.iterate();\nwhile (try it.next()) |entry| {\n try stdout.print(\n \"File name: {s}\\n\",\n .{entry.name}\n );\n}\n```\n:::\n\n\n\n\n```\nFile name: create_file_and_write_toit.zig\nFile name: create_file.zig\nFile name: lorem.txt\nFile name: iterate.zig\nFile name: delete_file.zig\nFile name: append_to_file.zig\nFile name: user_input.zig\nFile name: foo.txt\nFile name: create_file_and_read.zig\nFile name: buff_io.zig\nFile name: copy_file.zig\n```\n\n\n### Creating new directories\n\nThere are two methods that are important when it comes to\ncreating directories, which are `makeDir()` and `makePath()`.\nThe difference between these two methods is that `makeDir()` can\nonly create one single directory in the current directory in each call,\nwhile `makePath()` is capable of recursively create subdirectories in the same call.\n\n\nThis is why the name of this method is \"make path\". It will create as many\nsubdirectories as necessary to create the path that you provided as input.\nSo, if you provide the path `\"sub1/sub2/sub3\"` as input to this method,\nit will create three different subdirectories, `sub1`, `sub2` and `sub3`,\nwithin the same function call. In contrast, if you provided such path\nas input to `makeDir()`, you would likely get an error as result, since\nthis method can only create a single subdirectory.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.makeDir(\"src\");\ntry cwd.makePath(\"src/decoders/jpg/\");\n```\n:::\n\n\n\n\n### Deleting directories\n\nTo delete a directory, just provide the path to the directory that you want to delete\nas input to the `deleteDir()` method from a `Dir` object. In the example below,\nwe are deleting the `src` directory that we have just created in the previous example.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.deleteDir(\"src\");\n```\n:::\n\n\n\n\n\n## Conclusion\n\nIn this chapter, I have described how to perform in Zig the most common filesystem and IO operations.\nBut you might feel the lack of some other, less common, operation in this chapter, such as: how to rename files,\nor how to open a directory, or how to create symbolic links, or how to use `access()` to test if a particular\npath exists in your computer. But for all of these less common tasks, I recommend you to read\nthe documentation of the [`Dir` type](https://ziglang.org/documentation/master/std/#std.fs.Dir)[^zig-dir]\n, since you can find a good description of these cases there.\n", - "supporting": [ - "12-file-op_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Filesystem and Input/Output (IO) {#sec-filesystem}\n\nIn this chapter we are going to discuss how to use the cross-platform structs and functions\nfrom the Zig Standard Library that can execute filesystem operations. Most of these functions and structs\ncomes from the `std.fs` module.\n\nWe are also going to talk about Input/Output (also known as IO) operations in Zig. Most of\nthese operations are made by using the structs and functions from `std.io` module, which defines\nfile descriptors for the *standard channels* of your system (`stdout` and `stdin`), and also,\nfunctions to create and use I/O streams.\n\n\n## Input/Output basics {#sec-io-basics}\n\nIf you have some experience in a high-level language, you have certainly used\nthese input and output functionalities before in this language. In other words, you certainly have\nbeen in a situation where you needed to sent some output to the user, or, to receive an input\nfrom the user.\n\nFor example, in Python we can receive some input from the user by using the `input()` built-in\nfunction. But we can also print (or \"show\") some output to the user by using the `print()`\nbuilt-in function. So yes, if you have programmed before in Python, you certainly have\nused these functions once before.\n\nBut do you know how these functions relate back to your operating system (OS)? How exactly\nthey are interacting with the resources of your OS to receive or sent some input/output.\nIn essence, these input/output functions from high-level languages are just abstractions\nover the *standard output* and *standard input* channels of your operating system.\n\nThis means that we receive an input, or send some output, through the operating system.\nIt's the OS that makes the bridge between the user and your program. Your program\ndoes not have a direct access to the user. It's the OS that intermediates every\nmessage exchanged between your program and the user.\n\nThe *standard output* and *standard input* channels of your OS are commonly known as the\n`stdout` and `stdin` channels of your OS, respectively. In some contexts, they are also\ncalled the *standard output device* and the *standard input device*. As the name suggests,\nthe *standard output* is the channel through which output flows, while the *standard input*\nis the channel in which input flows.\n\nFurthermore, OS's also normally create a dedicated channel for exchanging error messages, which is known as the\n*standard error* channel, or, the `stderr` channel. This is the channel to which error and warning messages\nare usually sent to. These are the messages that are normally displayed in red-like or orange-like colors\ninto your terminal.\n\nNormally, every OS (e.g. Windows, macOS, Linux, etc.) creates a dedicated and separate set of\n*standard output*, *standard error* and *standard input* channels for every single program (or process) that runs in your computer.\nThis means that every program you write have a dedicated `stdin`, `stderr` and `stdout` that are separate\nfrom the `stdin`, `stderr` and `stdout` of other programs and processes that are currently running.\n\nThis is a behaviour from your OS. This does not come from the programming language that you are using.\nBecause as I sad earlier, input and output in programming languages, especially\nin high-level ones, are just a simple abstraction over the `stdin`, `stderr` and `stdout` from your current OS.\nThat is, your OS is the intermediary between every input/output operation made in your program,\nregardless of the programming language that you are using.\n\n\n### The writer and reader pattern {#sec-writer-reader}\n\nIn Zig, there is a pattern around input/output (IO). I (the author of this book) don't know if there\nis an official name for this pattern. But here, in this book, I will call it the \"writer and reader pattern\".\nIn essence, every IO operation in Zig is made through either a `GenericReader` or a `GenericWriter` object[^gen-zig].\n\nThese two data types come from the `std.io` module of the Zig Standard Library. As their names suggests, a\n`GenericReader` is an object that offers tools to read data from \"something\" (or \"somewhere\"), while a `GenericWriter`\noffers tools to write data into this \"something\". This \"something\" might be different things: like a\nfile that exists in your filesystem; or, it might be a network socket in your system[^sock]; or,\na continuous stream of data, like a standard input device from your system, that might be constantly\nreceiving new data from users, or, as another example, a live chat in a game that is constantly\nreceiving and displaying new messages from the players of the game.\n\n[^gen-zig]: Previously, these objects were known as the `Reader` and `Writer` objects.\n[^sock]: The socket objects that we have created in @sec-create-socket, are examples of network sockets.\n\nSo, if you want to **read** data from something, or somewhere, it means that you need to use a `GenericReader` object.\nBut if you need instead, to **write** data into this \"something\", then, you need to use a `GenericWriter` object instead.\nBoth of these objects are normally created from a file descriptor object. More specifically, through the `writer()` and `reader()`\nmethods of this file descriptor object. If you are not familiar with this type of object, go to the next section.\n\nEvery `GenericWriter` object have methods like `print()`, which allows you to write/send a formatted string\n(i.e., this formatted string is like a `f` string in Python, or, similar to the `printf()` C function)\ninto the \"something\" (file, socket, stream, etc.) that you are using. It also have a `writeAll()` method, which allows you to\nwrite a string, or, an array of bytes into the \"something\".\n\nLikewise, every `GenericReader` object have methods like `readAll()`, which allows you to read the\ndata from the \"something\" (file, socket, stream, etc.) until it fills a particular array (i.e., a \"buffer\") object.\nIn other words, if you provide an array object of 300 `u8` values to `readAll()`, then, this method attempts to read 300 bytes\nof data from the \"something\", and it stores them into the array object that you have provided.\n\nWe also have other methods, like the `readAtLeast()` method, which allows you to specify how\nmany bytes exactly you want to read from the \"something\". In more details, if you give the\nnumber $n$ as input to this method, then, it will attempt to read at least $n$ bytes of data\nfrom the \"something\". The \"something\" might have less than $n$ bytes of data available for you\nto read, so, it's not guaranteed that you will get precisely $n$ bytes as result.\n\nAnother useful method is `readUntilDelimiterOrEof()`. In this method, you specify a \"delimiter character\".\nThe idea is that this function will attempt to read as many bytes of data as possible from the \"something\",\nuntil it encounters the end of the stream, or, it encounters the \"delimiter character\" that you have specified.\n\nIf you don't know exactly how many bytes will come from the \"something\", you may find the `readAllAlloc()` method\nuseful. In essence, you provide an allocator object to this method, so that it can allocate more space if needed.\nAs consequence, this method will try to read all bytes of the \"something\", and, if it runs out of space at some point\nduring the \"reading process\", it uses the allocator object to allocate more space to continue reading the bytes.\nAs result, this method returns a slice to the array object containing all the bytes read.\n\nThis is just a quick description of the methods present in these types of objects. But I recommend you\nto read the official docs, both for\n[`GenericWriter`](https://ziglang.org/documentation/master/std/#std.io.GenericWriter)[^gen-write] and\n[`GenericReader`](https://ziglang.org/documentation/master/std/#std.io.GenericReader)[^gen-read].\nI also think it's a good idea to read the source code of the modules in the Zig Standard Library\nthat defines the methods present in these objects, which are the\n[`Reader.zig`](https://github.com/ziglang/zig/blob/master/lib/std/io/Reader.zig)[^mod-read]\nand [`Writer.zig`]()[^mod-write].\n\n[^gen-read]: .\n[^gen-write]: .\n[^mod-read]: .\n[^mod-write]: .\n\n\n\n### Introducing file descriptors {#sec-file-descriptor}\n\nA \"file descriptor\" object is a core component behind every IO operation that is made in any operating system (OS).\nSuch object is an identifier for a particular input/output (IO) resource from your OS [@wiki_file_descriptor].\nIt describes and identifies this particular resource. An IO resource might be:\n\n- an existing file in your filesystem.\n- an existing network socket.\n- other types of stream channels.\n- a pipeline (or just \"pipe\") in your terminal[^pipes].\n\n[^pipes]: A pipeline is a mechanism for inter-process communication, or, inter-process IO. You could also interpret a pipeline as a \"set of processes that are chained together, through the standard input/output devices of the system\". At Linux for example, a pipeline is created inside a terminal, by connecting two or more terminal commands with the \"pipe\" character (`|`).\n\nFrom the bullet points listed above, we know that although the term \"file\" is present,\na \"file descriptor\" might describe something more than just a file.\nThis concept of a \"file descriptor\" comes from the Portable Operating System Interface (POSIX) API,\nwhich is a set of standards that guide how operating systems across the world should be implemented,\nto maintain compatibility between them.\n\nA file descriptor not only identifies the input/output resource that you are using to receive or send some data,\nbut it also describes where this resource is, and also, which IO mode this resource is currently using.\nFor example, this IO resource might be using only the \"read\" IO mode, which means that this resource\nis open to \"read operations\", while \"write operations\" are not authorized.\nThese IO modes are essentially the modes that you provide to the argument `mode`\nfrom the `fopen()` C function, and also, from the `open()` Python built-in function.\n\nIn C, a \"file descriptor\" is a `FILE` pointer, but, in Zig, a file descriptor is a `File` object.\nThis data type (`File`) is described in the `std.fs` module of the Zig Standard Library.\nWe normally don't create a `File` object directly in our Zig code. Instead, we normally get such object as result when we\nopen an IO resource. In other words, we normally ask our OS to open a particular IO resource for us,\nand, if the OS do open successfully this IO resource, the OS normally handles back to us\na file descriptor to this particular IO resource.\n\nSo you usually get a `File` object by using functions and methods from the Zig Standard Library\nthat asks the OS to open some IO resource, like the `openFile()` method that opens a file in the\nfilesystem. The `net.Stream` object that we have created in @sec-create-socket is also a type of\nfile descriptor object.\n\n\n### The *standard output*\n\nYou already saw across this book, how can we access and use specifically the `stdout` in Zig\nto send some output to the user.\nFor that, we use the `getStdOut()` function from the `std.io` module. This function returns\na file descriptor that describes the `stdout` channel of your current OS. Through this file\ndescriptor object, we can read from or write stuff to the `stdout` of our program.\n\nAlthough we can read stuff recorded into the `stdout` channel, we normally only\nwrite to (or \"print\") stuff into this channel. The reason is very similar to what we discussed at\n@sec-read-http-message, when we were discussing what \"reading from\" versus \"writing to\" the connection\nobject from our small HTTP Server project would mean.\n\nWhen we write stuff into a channel, we are essentially sending data to the other end of this channel.\nIn contrast, when we read stuff from this channel, we are essentially reading the data that was sent\nthrough this channel. Since the `stdout` is a channel to send output to the user, the key verb here\nis **send**. We want to send something to someone, and, as consequence, we want to **write** something\ninto some channel.\n\nThat is why, when we use `getStdOut()`, most of the times, we also use the `writer()` method from the `stdout` file descriptor,\nto get access to a writer object that we can use to write stuff into this `stdout` channel.\nMore specifically, this `writer()` method returns a `GenericWriter` object. One of the\nmain methods of this `GenericWriter` object is the `print()` method that we have used\nbefore to write (or \"print\") a formatted string into the `stdout` channel.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\npub fn main() !void {\n try stdout.writeAll(\n \"This message was written into stdout.\\n\"\n );\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nThis message was written into stdout.\n```\n\n\n:::\n:::\n\n\n\n\nThis `GenericWriter` object is like any other generic writer object that you would normally get from a file descriptor object.\nSo, the same methods from a generic writer object that you would use while writing files to the filesystem for example, you could also\nuse them here, from the file descriptor object of `stdout`, and vice-versa.\n\n\n### The *standard input*\n\nYou can access the *standard input* (i.e., `stdin`) in Zig by using the `getStdIn()` function from the `std.io` module.\nLike its brother (`getStdOut()`), this function also returns a file descriptor object that describes the `stdin` channel\nof your OS.\n\nBecause we want to receive some input from the user, the key verb here becomes **receive**, and, as consequence,\nwe usually want to **read** data from the `stdin` channel, instead of writing data into it. So, we normally use\nthe `reader()` method of the file descriptor object returned by `getStdIn()`, to get access to a `GenericReader`\nobject that we can use to read data from `stdin`.\n\nIn the example below, we are creating a small buffer capable of holding 20 characters. Then, we try to read\nthe data from the `stdin` with the `readUntilDelimiterOrEof()` method, and save this data into the `buffer` object.\nAlso notice that we are reading the data from the `stdin` until we hit a new line character (`'\\n'`).\n\nIf you execute this program, you will notice that it stops the execution, ands start to wait indefinitely\nfor some input from the user. In other words, you need to type your name into the terminal, and then, you press Enter to\nsend your name to `stdin`. After you send your name to `stdin`, the program reads this input, and continues with the execution,\nby printing the given name to `stdout`. In the example below, I typed my name (Pedro) into the terminal, and then, pressed Enter.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst stdin = std.io.getStdIn().reader();\npub fn main() !void {\n try stdout.writeAll(\"Type your name\\n\");\n var buffer: [20]u8 = undefined;\n @memset(buffer[0..], 0);\n _ = try stdin.readUntilDelimiterOrEof(buffer[0..], '\\n');\n try stdout.print(\"Your name is: {s}\\n\", .{buffer});\n}\n```\n:::\n\n\n```\nType your name\nYour name is: Pedro\n\n```\n\n\n### The *standard error*\n\nThe *standard error* (a.k.a. the `stderr`) works exactly the same as `stdout` and `stdin`.\nYou just call the `getStdErr()` function from the `std.io` module, and you get the file descriptor to `stderr`.\nIdeally, you should write only error or warning messages to `stderr`, because this is\nthe purpose of this channel.\n\n\n\n\n\n## Buffered IO\n\nAs we described in @sec-io-basics, input/output (IO) operations are made directly by the operating system.\nIt's the OS that manages the IO resource that you want to use for your IO operations.\nThe consequence of this fact is that IO operations are heavily based on system calls (i.e., calling the operating system directly).\n\nJust to be clear, there is nothing particularly wrong with system calls. We use them all the time on\nany serious codebase written in any low-level programming language. However, system calls are\nalways orders of magnitude slower than many different types of operations.\n\nSo is perfectly fine to use a system call once in a while. But when these system calls are used often,\nyou can clearly notice most of the time the loss of performance in your application. So, the good rule of thumb\nis to use a system call only when it's needed, and also, only in infrequent situations, to reduce\nthe number of system calls performed to a minimum.\n\n\n### Understanding how buffered IO works\n\nBuffered IO is a strategy to achieve better performance. It's used to reduce the number of system calls made by IO operations, and, as\nconsequence, achieve a much higher performance. In @fig-unbuffered-io and @fig-buffered-io you can find two different diagrams\nwhich presents the difference between read operations performed in an unbuffered IO environment versus a buffered IO environment.\n\nTo give a better context to these diagrams, let's suppose that we have a text file that contains the famous Lorem ipsum text[^lorem]\nin our filesystem. Let's also suppose that these diagrams in @fig-unbuffered-io and @fig-buffered-io\nare showing the read operations that we are performing to read the Lorem ipsum text from this text file.\nThe first thing you will notice when looking at these diagrams, is that in an unbuffered environment\nthe read operations leads to many system calls.\nMore precisely, in the diagram exposed in @fig-unbuffered-io we get one system call per each byte that we read from the text file.\nOn the other hand, in @fig-buffered-io we have only one system call at the very beginning.\n\nWhen we use a buffered IO system, at the first read operation we perform, instead of sending one single byte directly\nto our program, the OS first sends a chunk of bytes from the file to a buffer object (i.e., an array).\nThis chunk of bytes are cached/stored inside this buffer object.\n\nTherefore, from now on, for every new read operation that you perform, instead of making a new system call to ask\nfor the next byte in the file to the OS, this read operation is redirected to the buffer object, that have\nthis next byte already cached and ready to go.\n\n\n[^lorem]: .\n\n\n![Unbuffered IO](./../Figures/unbuffered-io.png){#fig-unbuffered-io width=60%}\n\n![Buffered IO](./../Figures/buffered-io.png){#fig-buffered-io}\n\n\n\nThis is the basic logic behind buffered IO systems. The size of the buffer object depends on multiple factors. But it's usually\nequal to the size of a full page of memory (4096 bytes). If we follow this logic, then, the OS reads the first 4096 bytes\nof the file and caches it into the buffer object. As long as your program does not consume all of these 4096 bytes from the buffer,\nyou will not create new system calls.\n\nHowever, as soon as you consume all of these 4096 bytes from the buffer, it means that there is no bytes left in the buffer.\nIn this situation, a new system call is made to ask the OS to send the next 4096 bytes in the file, and once again,\nthese bytes are cached into the buffer object, and the cycle starts once again.\n\n\n### Buffered IO across different languages\n\nIO operations made through a `FILE` pointer in C are buffered\nby default, so, at least in C, you don't need to worry about this subject. But in contrast, IO operations in both Rust and Zig are not\nbuffered depending on which functions from the standard libraries that you are using.\n\nFor example, in Rust, buffered IO is implemented through the `BufReader` and `BufWriter` structs, while in Zig, it's implemented\nthrough the `BufferedReader` and `BufferedWriter` structs.\nSo any IO operation that you perform through the `GenericWriter` and `GenericReader` objects\nthat I presented in @sec-writer-reader are not buffered, which means that these objects\nmight create a lot of system calls depending on the situation.\n\n\n### Using buffered IO in Zig\n\nUsing buffered IO in Zig is actually very easy. All you have to do is to just\ngive the `GenericWriter` object to the `bufferedWriter()` function, or, to give the `GenericReader`\nobject to the `bufferedReader()` function. These functions come from the `std.io` module,\nand they will construct the `BufferedWriter` or `BufferedReader` object for you.\n\nAfter you create this new `BufferedWriter` or `BufferedReader` object, you can call the `writer()`\nor `reader()` method of this new object, to get access to a new (and buffered) generic reader or\ngeneric writer.\n\nLet's describe the process once again. Every time that you have a file descriptor object, you first get the generic writer or generic reader\nobject from it, by calling the `writer()` or `reader()` methods of this file descriptor object.\nThen, you provide this generic writer or generic reader to the `bufferedWriter()` or `bufferedReader()`\nfunction, which creates a new `BufferedWriter` or `BufferedReader` object. Then, you call\nthe `writer()` or `reader()` methods of this buffered writer or buffered reader object,\nwhich gives you access to a generic writer or a generic reader object that is buffered.\n\nTake this program as an example. This program is demonstrating the process exposed in @fig-buffered-io.\nWe are simply opening a text file that contains the Lorem ipsum text, and then, we create a buffered IO reader object\nat `bufreader`, and we use this `bufreader` object to read the contents of this file into a buffer object, then,\nwe end the program by printing this buffer to `stdout`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar file = try std.fs.cwd().openFile(\n \"ZigExamples/file-io/lorem.txt\", .{}\n);\ndefer file.close();\nvar buffered = std.io.bufferedReader(file.reader());\nvar bufreader = buffered.reader();\n\nvar buffer: [1000]u8 = undefined;\n@memset(buffer[0..], 0);\n\n_ = try bufreader.readUntilDelimiterOrEof(\n buffer[0..], '\\n'\n);\ntry stdout.print(\"{s}\\n\", .{buffer});\n```\n:::\n\n\n```\nLorem ipsum dolor sit amet, consectetur\nadipiscing elit. Sed tincidunt erat sed nulla ornare, nec\naliquet ex laoreet. Ut nec rhoncus nunc. Integer magna metus,\nultrices eleifend porttitor ut, finibus ut tortor. Maecenas\nsapien justo, finibus tincidunt dictum ac, semper et lectus.\nVivamus molestie egestas orci ac viverra. Pellentesque nec\narcu facilisis, euismod eros eu, sodales nisl. Ut egestas\nsagittis arcu, in accumsan sapien rhoncus sit amet. Aenean\nneque lectus, imperdiet ac lobortis a, ullamcorper sed massa.\nNullam porttitor porttitor erat nec dapibus. Ut vel dui nec\nnulla vulputate molestie eget non nunc. Ut commodo luctus ipsum,\nin finibus libero feugiat eget. Etiam vel ante at urna tincidunt\nposuere sit amet ut felis. Maecenas finibus suscipit tristique.\nDonec viverra non sapien id suscipit.\n```\n\nDespite being a buffered IO reader, this `bufreader` object is similar to any other `GenericReader` object,\nand have the exact same methods. So, although these two types of objects perform very different IO operations,\nthey have the same interface, so you, the programmer, can interchangeably use them\nwithout the need to change anything in your source code.\nSo a buffered IO reader or a buffered IO writer objects have the same methods than its generic and unbuffered brothers,\ni.e., the generic reader and generic writer objects that I presented in @sec-writer-reader.\n\n::: {.callout-tip}\nIn general, you should always use a buffered IO reader or a buffered IO writer object to perform\nIO operations in Zig. Because they deliver better performance to your IO operations.\n:::\n\n\n## Filesystem basics\n\nNow that we have discussed the basics around Input/Output operations in Zig, we need to\ntalk about the basics around filesystems, which is another core part of any operating system.\nAlso, filesystems are related to input/output, because the files that we store and create in our\ncomputer are considered an IO resource, as we described in @sec-file-descriptor.\n\n\n### The concept of current working directory (CWD)\n\nThe working directory is the folder on your computer where you are currently rooted at.\nIn other words, it's the folder that your program is currently looking at.\nTherefore, whenever you are executing a program, this program is always working with\na specific folder on your computer. It's always in this folder that the program will initially\nlook for the files you require, and it's also in this folder that the program\nwill initially save all the files you ask it to save.\n\nThe working directory is determined by the folder from which you invoke your program\nin the terminal. In other words, if you are in the terminal of your OS, and you\nexecute a binary file (i.e., a program) from this terminal, the folder to which your terminal\nis pointing at is the current working directory of your program that is being executed.\n\nIn @fig-cwd we have an example of me executing a program from the terminal. We are executing\nthe program outputted by the `zig` compiler by compiling the Zig module named `hello.zig`.\nThe CWD in this case is the `zig-book` folder. In other words, while the `hello.zig` program\nis executing, it will be looking at the `zig-book` folder, and any file operation that we perform\ninside this program, will be using this `zig-book` folder as the \"starting point\", or, as the \"central focus\".\n\n![Executing a program from the terminal](./../Figures/cwd.png){#fig-cwd}\n\nJust because we are rooted inside a particular folder (in the case of @fig-cwd, the `zig-book` folder) of our computer,\nit doesn't mean that we cannot access or write resources in other locations of our computer.\nThe current working directory (CWD) mechanism just defines where your program will look first\nfor the files you ask for. This does not prevent you from accessing files that are located\nelsewhere on your computer. However, to access any file that is in a folder other than your\ncurrent working directory, you must provide a path to that file or folder.\n\n\n### The concept of paths\n\nA path is essentially a location. It points to a location in your filesystem. We use\npaths to describe the location of files and folders in our computer.\nOne important aspect about paths is that they are always written inside strings,\ni.e., they are always provided as text values.\n\nThere are two types of paths that you can provide to any program in any OS: a relative path, or an absolute path.\nAbsolute paths are paths that start at the root of your filesystem, and go all the way to the file name or the specific folder\nthat you are referring to. This type of path is called absolute, because it points to an unique and absolute location on your computer.\nThat is, there is no other existing location on your computer that corresponds to this path. It's an unique identifier.\n\nIn Windows, an absolute path is a path that starts with a hard disk identifier (e.g. `C:/Users/pedro`).\nOn the other hand, absolute paths in Linux and macOS, are paths that start with a forward slash character (e.g. `/usr/local/bin`).\nNotice that a path is composed by \"segments\". Each segment is connected to each other by a slash character (`\\` or `/`).\nOn Windows, the backward slash (`\\`) is normally used to connect the path segments. While on Linux and macOS, the forward\nslash (`/`) is the character used to connect path segments.\n\nA relative path is a path that start at the CWD. In other words, a relative path is\n\"relative to the CWD\". The path used to access the `hello.zig` file in @fig-cwd is an example of a relative path. This path\nis reproduced below. This path begins at the CWD, which in the context of @fig-cwd, is the `zig-book` folder,\nthen, it goes to the `ZigExamples` folder, then, into `zig-basics`, then, to the `hello.zig` file.\n\n```\nZigExamples/zig-basics/hello_world.zig\n```\n\n\n### Path wildcards\n\nWhen providing paths, especially relative paths, you have the option of using a *wildcard*.\nThere are two commonly used *wildcards* in paths, which are \"one period\" (.) and \"two periods\" (..).\nIn other words, these two specific characters have special meanings when used in paths,\nand can be used on any operating system (Mac, Windows, Linux, etc.). That is, they\nare \"cross platform\".\n\nThe \"one period\" represents an alias for the current directory.\nThis means that the relative paths `\"./Course/Data/covid.csv\"` and `\"Course/Data/covid.csv\"` are equivalent.\nOn the other hand, the \"two periods\" refers to the previous directory.\nFor example, the path `\"Course/..\"` is equivalent to the path `\".\"`, that is, the current working directory.\n\nTherefore, the path `\"Course/..\"` refers to the folder before the `Course` folder.\nAs another example, the path `\"src/writexml/../xml.cpp\"` refers to the file `xml.cpp`\nthat is inside the folder before the `writexml` folder, which in this example is the `src` folder.\nTherefore, this path is equivalent to `\"src/xml.cpp\"`.\n\n\n\n\n## The CWD handler\n\nIn Zig, filesystem operations are usually made through a directory handler object.\nA directory handler in Zig is an object of type `Dir`, which is an object that describes\na particular folder in the filesystem of our computer.\nYou normally create a `Dir` object, by calling the `std.fs.cwd()` function.\nThis function returns a `Dir` object that points to (or, that describes) the\ncurrent working directory (CWD).\n\nThrough this `Dir` object, you can create new files, or modify, or read existing ones that are\ninside your CWD. In other words, a `Dir` object is the main entrypoint in Zig to perform\nmultiple types of filesystem operations.\nIn the example below, we are creating this `Dir` object, and storing it\ninside the `cwd` object. Although we are not using this object at this code example,\nwe are going to use it a lot over the next examples.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\n_ = cwd;\n```\n:::\n\n\n\n\n\n\n\n\n\n## File operations\n\n### Creating files {#sec-creating-files}\n\nWe create new files by using the `createFile()` method from the `Dir` object.\nJust provide the name of the file that you want to create, and this function will\ndo the necessary steps to create such file. You can also provide a relative path to this function,\nand it will create the file by following this path, which is relative to the CWD.\n\nThis function might return an error, so, you should use `try`, `catch`, or any of the other methods presented\nin @sec-error-handling to handle the possible error. But if everything goes well,\nthis `createFile()` method returns a file descriptor object (i.e., a `File` object) as result,\nthrough which you can add content to the file with the IO operations that I presented before.\n\nTake this code example below. In this example, we are creating a new text file\nnamed `foo.txt`. If the function `createFile()` succeeds, the object named `file` will contain a file descriptor\nobject, which we can use to write (or add) new content to the file, like we do in this example, by using\na buffered writer object to write a new line of text to the file.\n\nNow, a quick note, when we create a file descriptor object in C, by using a C function like `fopen()`, we must always close the file\nat the end of our program, or, as soon as we complete all operations that we wanted to perform\non the file. In Zig, this is no different. So everytime we create a new file, this file remains\n\"open\", waiting for some operation to be performed. As soon as we are done with it, we always have\nto close this file, to free the resources associated with it.\nIn Zig, we do this by calling the method `close()` from the file descriptor object.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.createFile(\"foo.txt\", .{});\n// Don't forget to close the file at the end.\ndefer file.close();\n// Do things with the file ...\nvar fw = file.writer();\n_ = try fw.writeAll(\n \"Writing this line to the file\\n\"\n);\n```\n:::\n\n\n\nSo, in this example we not only have created a file into the filesystem,\nbut we also wrote some data into this file, using the file descriptor object\nreturned by `createFile()`. If the file that you are trying to create\nalready exists in your filesystem, this `createFile()` call will\noverwrite the contents of the file, or, in other words, it will\nin erase all the contents of the existing file.\n\nIf you don't want this to happen, meaning, that you don't want to overwrite\nthe contents of the existing file, but you want to write data to this file anyway\n(i.e., you want to append data to the file), you should use the `openFile()`\nmethod from the `Dir` object.\n\nAnother important aspect about `createFile()` is that this method creates a file\nthat is not open to read operations by default. It means that you cannot read this file.\nYou are not allowed to.\nSo for example, you might want to write some stuff into this file at the beginning of the execution\nof your program. Then, at a future point in your program you might need to read what you\nwrote in this file. If you try to read data from this file, you will likely\nget a `NotOpenForReading` error as result.\n\n\nBut how can you overcome this barrier? How can you create a file that is open\nto read operations? All you have to do, is to set the `read` flag to true\nin the second argument of `createFile()`. When you set this flag to true,\nthen the file gets create with \"read permissions\", and, as consequence,\na program like this one below becomes valid:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.createFile(\n \"foo.txt\",\n .{ .read = true }\n);\ndefer file.close();\n\nvar fw = file.writer();\n_ = try fw.writeAll(\"We are going to read this line\\n\");\n\nvar buffer: [300]u8 = undefined;\n@memset(buffer[0..], 0);\ntry file.seekTo(0);\nvar fr = file.reader();\n_ = try fr.readAll(buffer[0..]);\ntry stdout.print(\"{s}\\n\", .{buffer});\n```\n:::\n\n\n\n```\nWe are going to read this line\n```\n\n\nIf you are not familiar with position indicators, you might not recognize the method\n`seekTo()`. If that is your case, do not worry,\nwe are going to talk more about this method in @sec-indicators. But essentially\nthis method is moving the position indicator back to the beginning of the file,\nso that we can read the contents of the file from the beginning.\n\n\n### Opening files and appending data to it\n\nOpening files is easy. Just use the `openFile()` method instead of `createFile()`.\nIn the first argument of `openFile()` you provide the path to the file that\nyou want to open. Then, on the second argument you provide the flags (or, the options)\nthat dictates how the file is opened.\n\nYou can see the full list of options for `openFile()` by visiting the documentation for\n[`OpenFlags`](https://ziglang.org/documentation/master/std/#std.fs.File.OpenFlags)[^oflags].\nBut the main flag that you will most certainly use is the `mode` flag.\nThis flag specifies the IO mode that the file will be using when it gets opened.\nThere are three IO modes, or, three values that you can provide to this flag, which are:\n\n- `read_only`, allows only read operations on the file. All write operations are blocked.\n- `write_only`, allows only write operations on the file. All read operations are blocked.\n- `read_write`, allows both write and read operations on the file.\n\n[^oflags]: \n\nThese modes are similar to the modes that you provide to the `mode` argument of the\n`open()` Python built-in function[^py-open], or, the `mode` argument of the\n`fopen()` C function[^c-open].\nIn the code example below, we are opening the `foo.txt` text file with a `write_only` mode,\nand appending a new line of text to the end of the file. We use `seekFromEnd()` this time\nto guarantee that we are going to append the text to the end of the file. Once again, methods\nsuch as `seekFromEnd()` are described in more depth in @sec-indicators.\n\n[^py-open]: \n[^c-open]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst file = try cwd.openFile(\n \"foo.txt\", .{ .mode = .write_only }\n);\ndefer file.close();\ntry file.seekFromEnd(0);\nvar fw = file.writer();\n_ = try fw.writeAll(\"Some random text to write\\n\");\n```\n:::\n\n\n\n### Deleting files\n\nSometimes, we just need to delete/remove the files that we have.\nTo do that, we use the `deleteFile()` method. You just provide the path of the\nfile that you want to delete, and this method will try to delete the file located\nat this path.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.deleteFile(\"foo.txt\");\n```\n:::\n\n\n### Copying files\n\nTo copy existing files, we use the `copyFile()` method. The first argument in this method\nis the path to the file that you want to copy. The second argument is a `Dir` object, i.e., a directory handler,\nmore specifically, a `Dir` object that points to the folder in your computer where you want to\ncopy the file to. The third argument is the new path of the file, or, in other words, the new location\nof the file. The fourth argument is the options (or flags) to be used in the copy operation.\n\nThe `Dir` object that you provide as input to this method will be used to copy the file to\nthe new location. You may create this `Dir` object before calling the `copyFile()` method.\nMaybe you are planning to copy the file to a completely different location in your computer,\nso it might be worth to create a directory handler to that location. But if you are copying the\nfile to a subfolder of your CWD, then, you can just simply pass the CWD handler to this argument.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.copyFile(\n \"foo.txt\",\n cwd,\n \"ZigExamples/file-io/foo.txt\",\n .{}\n);\n```\n:::\n\n\n\n### Read the docs!\n\nThere are some other useful methods for file operations available at `Dir` objects,\nsuch as the `writeFile()` method, but I recommend you to read the docs for the\n[`Dir` type](https://ziglang.org/documentation/master/std/#std.fs.Dir)[^zig-dir]\nto explore the other available methods, since I already talked too much about them.\n\n\n[^zig-dir]: \n\n\n\n\n## Position indicators {#sec-indicators}\n\nA position indicator is like a type of cursor, or, an index. This \"index\" identifies the current\nlocation in the file (or, in the data stream) that the file descriptor object that you have\nis currently looking at.\nWhen you create a file descriptor, the position indicator starts at the beginning of the file,\nor, at the beginning of the stream. When you read from or write into the file (or socket, or data stream, etc.)\ndescribed by this file descriptor object, you end up moving the position indicator.\n\nIn other words, any IO operation have a common side effect, which is to move the position indicator.\nFor example, suppose that we have a file of 300 bytes total in size. If you\nread 100 bytes from the file, then, the position indicator moves 100 bytes forward. If you try\nto write 50 bytes into this same file, these 50 bytes will be written from the current\nposition indicated by the position indicator. Since the indicator is at a 100 bytes forward from\nthe beginning of the file, these 50 bytes would be written in the middle of the file.\n\nThis is why we have used the `seekTo()` method at the last code example presented in @sec-creating-files.\nWe have used this method to move the position indicator back to the beginning of the file, which\nwould make sure that we would write the text that we wanted to write from the beginning of the file,\ninstead of writing it from the middle of the file. Because before the write operation, we had\nperformed a read operation, which means that the position indicator was moved in this read operation.\n\nThe position indicators of a file descriptor object can be changed (or altered) by using the\n\"seek\" methods from this file descriptor, which are: `seekTo()`, `seekFromEnd()` and `seekBy()`.\nThese methods have the same effect, or, the same responsibility that the\n[`fseek()`](https://en.cppreference.com/w/c/io/fseek)[^c-fseek] C function.\n\n[^c-fseek]: \n\n\nConsidering that `offset` refers to the index that you provide as input to these \"seek\" methods,\nthe bullet points below summarises what is the effect of each of these methods.\nAs a quick note, in the case of `seekFromEnd()` and `seekBy()`, the `offset` provided can be either a\npositive or a negative index.\n\n- `seekTo()` will move the position indicator to the location that is `offset` bytes from the beginning of the file.\n- `seekFromEnd()` will move the position indicator to the location that is `offset` bytes from the end of the file.\n- `seekBy()` will move the position indicator to the location that is `offset` bytes from the current position in the file.\n\n\n\n\n\n\n\n## Directory operations\n\n### Iterating through the files in a directory\n\nOne of the most classic tasks related to filesystem is to be able\nto iterate through the existing files in a directory. To iterate over the\nfiles in a directory, we need to create an iterator object.\n\nYou can produce such iterator object by using either the `iterate()` or `walk()` methods\nof a `Dir` object. Both methods return an iterator object as output, which you can advance by using the\n`next()` method. The difference between these methods, is that `iterate()` returns a non-recursive iterator,\nwhile `walk()` does. It means that the iterator returned by `walk()` will not only iterate through\nthe files available in the current directory, but also, through the files from any subdirectory found\ninside the current directory.\n\nIn the example below, we are displaying the names of the files stored inside the\ndirectory `ZigExamples/file-io`. Notice that we had to open this directory through\nthe `openDir()` function. Also notice that we provided the flag `iterate` in the\nsecond argument of `openDir()`. This flag is important, because without this flag,\nwe would not be allowed to iterate through the files in this directory.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\nconst dir = try cwd.openDir(\n \"ZigExamples/file-io/\",\n .{ .iterate = true }\n);\nvar it = dir.iterate();\nwhile (try it.next()) |entry| {\n try stdout.print(\n \"File name: {s}\\n\",\n .{entry.name}\n );\n}\n```\n:::\n\n\n```\nFile name: create_file_and_write_toit.zig\nFile name: create_file.zig\nFile name: lorem.txt\nFile name: iterate.zig\nFile name: delete_file.zig\nFile name: append_to_file.zig\nFile name: user_input.zig\nFile name: foo.txt\nFile name: create_file_and_read.zig\nFile name: buff_io.zig\nFile name: copy_file.zig\n```\n\n\n### Creating new directories\n\nThere are two methods that are important when it comes to\ncreating directories, which are `makeDir()` and `makePath()`.\nThe difference between these two methods is that `makeDir()` can\nonly create one single directory in the current directory in each call,\nwhile `makePath()` is capable of recursively create subdirectories in the same call.\n\n\nThis is why the name of this method is \"make path\". It will create as many\nsubdirectories as necessary to create the path that you provided as input.\nSo, if you provide the path `\"sub1/sub2/sub3\"` as input to this method,\nit will create three different subdirectories, `sub1`, `sub2` and `sub3`,\nwithin the same function call. In contrast, if you provided such path\nas input to `makeDir()`, you would likely get an error as result, since\nthis method can only create a single subdirectory.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.makeDir(\"src\");\ntry cwd.makePath(\"src/decoders/jpg/\");\n```\n:::\n\n\n### Deleting directories\n\nTo delete a directory, just provide the path to the directory that you want to delete\nas input to the `deleteDir()` method from a `Dir` object. In the example below,\nwe are deleting the `src` directory that we have just created in the previous example.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst cwd = std.fs.cwd();\ntry cwd.deleteDir(\"src\");\n```\n:::\n\n\n\n## Conclusion\n\nIn this chapter, I have described how to perform in Zig the most common filesystem and IO operations.\nBut you might feel the lack of some other, less common, operation in this chapter, such as: how to rename files,\nor how to open a directory, or how to create symbolic links, or how to use `access()` to test if a particular\npath exists in your computer. But for all of these less common tasks, I recommend you to read\nthe documentation of the [`Dir` type](https://ziglang.org/documentation/master/std/#std.fs.Dir)[^zig-dir]\n, since you can find a good description of these cases there.\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/13-image-filter/execute-results/epub.json b/_freeze/Chapters/13-image-filter/execute-results/epub.json deleted file mode 100644 index 31e3f7fe..00000000 --- a/_freeze/Chapters/13-image-filter/execute-results/epub.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "hash": "99b3cf5d4ae363f25838f780686e3234", - "result": { - "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n# Project 4 - Developing an image filter\n\nIn this chapter we are going to build a new project. The objective of\nthis project is to write a program that applies a filter over an image.\nMore specifically, a \"grayscale filter\", which transforms\nany color image into a grayscale image.\n\nWe are going to use the image displayed in @fig-pascal in this project.\nIn other words, we want to transform this colored image into a grayscale image,\nby using our \"image filter program\" written in Zig.\n\n![A photo of the chilean-american actor Pedro Pascal. Source: Google Images.](../ZigExamples/image_filter/pedro_pascal.png){#fig-pascal}\n\nWe don't need to write a lot of code to build such \"image filter program\". However, we first need\nto understand how digital images work. That is why we begin this chapter\nby explaining the theory behind digital images and how colors are represented in modern computers.\nWe also give a brief explanation about the PNG (Portable Network Graphics) file format, which is the format used\nin the example images.\n\nAt the end of this chapter, we should have a full example of a program that takes the PNG image displayed in @fig-pascal\nas input, and writes a new image to the current working directory that is the grayscale version of this input image.\nThis grayscale version of @fig-pascal is exposed in @fig-pascal-gray.\nYou can find the full source code of this small project at the `ZigExamples/image_filter`\n[folder at the official repository of this book](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/image_filter)[^img-filter-folder].\n\n\n![The grayscale version of the photo.](../ZigExamples/image_filter/pedro_pascal_filter.png){#fig-pascal-gray}\n\n\n## How we see things? {#sec-eyes}\n\nIn this section, I want to briefly describe to you how we (humans) actually see things with our own eyes.\nI mean, how our eyes work? If you do have a very basic understanding of how our eyes work, you will understand\nmore easily how digital images are made. Because the techniques behind digital images\nwere developed by taking a lot of inspiration from how our human eyes work.\n\nYou can interpret a human eye as a light sensor, or, a light receptor. The eye receives some amount of light as input,\nand it interprets the colors that are present in this \"amount of light\".\nIf no amount of light hits the eye, then, the eye cannot extract color from it, and as result,\nwe end up seeing nothing, or, more precisely, we see complete blackness.\n\nTherefore, everything depends on light. What we actually see are the colors (blue, red, orange, green, purple, yellow, etc.) that\nare being reflected from the light that is hitting our eyes. **Light is the source of all colors!**\nThis is what Isaac Newton discovered on his famous prism experiment[^newton] in the 1660s.\n\n[^newton]: \n\nInside our eyes, we have a specific type of cell called the \"cone cell\".\nOur eye have three different types, or, three different versions of these \"cone cells\".\nEach type of cone cell is very sensitive to a specific spectrum of the light. More specifically,\nto the spectrums that define the colors red, green and blue.\nSo, in summary, our eyes have specific types of cells that\nare highly sensitive to these three colors (red, green and blue).\n\nThese are the cells responsible for perceiving the color present in the light that hits our eyes.\nAs a result, our eyes perceives color as a mixture of these three colors (red, green and blue). By having an amount\nof each one of these three colors, and mixing them together, we can get any other visible color\nthat we want. So every color that we see is perceived as a specific mixture of blues, greens and reds,\nlike 30% of red, plus 20% of green, plus 50% of blue.\n\nWhen these cone cells perceive (or, detect) the colors that are found in the\nlight that is hitting our eyes, these cells produce electrical signals, which are sent to the brain.\nOur brain interprets these electrical signals, and use them to form the image that we are seeing\ninside our head.\n\nBased on what we have discussed here, the bullet points exposed below describes the sequence of events that\ncomposes this very simplified version of how our human eyes work:\n\n1. Light hits our eyes.\n1. The cone cells perceive the colors that are present in this light.\n1. Cone cells produce electrical signals that describes the colors that were perceived in the light.\n1. The electrical signals are sent to the brain.\n1. Brain interprets these signals, and form the image based on the colors identified by these electrical signals.\n\n\n## How digital images work? {#sec-digital-img}\n\nA digital image is a \"digital representation\" of an image that we see with our eyes.\nIn other words, a digital image is a \"digital representation\" of the colors that we see\nand perceive through the light.\nIn the digital world, we have two types of images, which are: vector images and raster images.\nVector images are not described here. So just remember that the content discussed here\n**is related solely to raster images**, and not vector images.\n\nA raster image is a type of digital image that is represented as a 2D (two dimensional) matrix\nof pixels. In other words, every raster image is basically a rectangle of pixels, and each pixel have a particular color.\nSo, a raster image is just a rectangle of pixels, and each of these pixels are displayed in the screen of your computer (or the screen\nof any other device, e.g. laptop, tablet, smartphone, etc.) as a color.\n\n@fig-raster demonstrates this idea. If you take any raster image, and you zoom into it very hard,\nyou will see the actual pixels of the image. JPEG, TIFF and PNG are file formats that are commonly\nused to store raster images.\n\n![Zooming over a raster image to see the pixels. Source: Google Images.](../Figures/imagem-raster.png){#fig-raster}\n\nThe more pixels the image has, the more information and detail we can include in the image.\nThe more accurate, sharp and pretty the image will look. This is why photographic cameras\nusually produce big raster images, with several megapixels of resolution, to include as much detail as possible into the final image.\nAs an example, a digital image with dimensions of 1920 pixels wide and 1080 pixels high, would be a image that\ncontains $1920 \\times 1080 = 2073600$ pixels in total. You could also say that the \"total area\" of the image is\nof 2073600 pixels, although the concept of \"area\" is not really used here in computer graphics.\n\nMost digital images we see in our modern world uses the RGB color model. RGB stands for (red, green and blue).\nSo the color of each pixel in these raster images are usually represented as a mixture of red, green and blue,\njust like in our eyes. That is, the color of each pixel is identified by a set of\nthree different integer values. Each integer value identifies the \"amount\" of each color (red, green and blue).\nFor example, the set `(199, 78, 70)` identifies a color that is more close to red. We have 199 of red, 78 of green,\nand 70 of blue. In contrast, the set `(129, 77, 250)` describes a color that is more close to purple. Et cetera.\n\n\n\n### Images are displayed from top to bottom\n\nThis is not a rule written in stone, but the big majority of digital images are displayed from top\nto bottom and left to right. Most computers screens also follow this pattern. So, the first pixels\nin the image are the ones that are at the top and left corner of the image. You can find a visual representation\nof this logic in @fig-img-display.\n\nAlso notice in @fig-img-display that, because a raster image is essentially a 2D matrix of pixels,\nthe image is organized into rows and columns of pixels. The columns are defined by the horizontal x axis,\nwhile the rows are defined by the vertical y axis.\n\nEach pixel (i.e., the gray rectangles) exposed in @fig-img-display contains a number inside of it.\nThese numbers are the indexes of the pixels. You can notice that the first pixels are in the top and left\ncorner, and also, that the indexes of these pixels \"grow to the sides\", or, in other words, they grow in the direction of the horizontal x axis.\nMost raster images are organized as rows of pixels. Thus, when these digital images are\ndisplayed, the screen display the first row of pixels, then, the second row, then, the third row, etc.\n\n![How the pixels of raster images are displayed.](./../Figures/image-display.png){#fig-img-display}\n\n\n\n\n\n\n### Representing the matrix of pixels in code {#sec-pixel-repr}\n\nOk, we know already that raster images are represented as 2D matrices of pixels.\nBut we do not have a notion of a 2D matrix in Zig. Actually, most low-level languages in general\n(Zig, C, Rust, etc.) do not have such notion.\nSo how can we represent such matrix of pixels in Zig, or any other low-level language?\nThe strategy that most programmers choose in this situation is to just use a normal 1D array to store the values of\nthis 2D matrix. In other words, you just create an normal 1D array, and store all values from both dimensions into this 1D array.\n\nAs an example, suppose we have a very small image of dimensions 4x3.\nSince a raster image is represented as a 2D matrix of pixels, and each pixel\nis represented by 3 \"unsigned 8-bit\" integer values, we have 12 pixels in\ntotal in this image, which are represented by $3 \\times 12 = 36$ integer values.\nTherefore, we need to create an array of 36 `u8` values to store this small image.\n\nThe reason why unsigned 8-bit integer (`u8`) values are used to represent the amounts of each color,\ninstead of any other integer type, is because they take the minimum amount of space as possible, or,\nthe minimum amount of bits as possible. Which helps to reduces the binary size of the image, i.e., the 2D matrix.\nAlso, they convey a good amount of precision and detail about the colors, even though they can represent\na relatively small range (from 0 to 255) of \"color amounts\".\n\nComing back to our initial example of a 4x3 image,\nthe `matrix` object exposed below could be an example of an 1D array that stores\nthe data that represents this 4x3 image.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst matrix = [_]u8{\n 201, 10, 25, 185, 65, 70,\n 65, 120, 110, 65, 120, 117,\n 98, 95, 12, 213, 26, 88,\n 143, 112, 65, 97, 99, 205,\n 234, 105, 56, 43, 44, 216,\n 45, 59, 243, 211, 209, 54,\n};\n```\n:::\n\n\n\nThe first three integer values in this array are the color amounts of the first pixel in the image.\nThe next three integers are the colors amounts for the second pixel.\nAnd the sequence goes on in this pattern. Having that in mind, the size of the array that stores\na raster image is usually a multiple of 3. In this case, the array have a size of 36.\n\nI mean, the size of the array is **usually** a multiple of 3, because in specific circumstances,\nit can also be a multiple of 4. This happens when a transparency amount is\nalso included into the raster image. In other words, there are some types of raster images\nthat uses a different color model, which is the RGBA (red, green, blue and alpha)\ncolor model. The \"alpha\" corresponds to an amount of transparency in the pixel.\nSo every pixel in a RGBA image is represented by a red, green, blue and alpha values.\n\nMost raster images uses the standard RGB model, so, for the most part, you will\nsee arrays sizes that are multiples of 3. But some images, especially the ones\nthat are stored in PNG files, might be using the RGBA model, and, therefore, are\nrepresented by an array whose size is a multiple of 4.\n\nIn our case here, the example image of our project (@fig-pascal) is a raster image\nstored in a PNG file, and this specific image is using the RGBA color model. Therefore,\neach pixel in the image is represented by 4 different integer values, and, as consequence,\nto store this image in our Zig code, we need to create an array whose size is a multiple of 4.\n\n\n## The PNG library that we are going to use\n\nLet's begin our project by focusing on writing the necessary Zig code to\nread the data from the PNG file. In other words, we want to read the PNG file exposed\nin @fig-pascal, and parse its data to extract the 2D matrix of pixels that represents the image.\n\nAs we have discussed in @sec-pixel-repr, the image that we are using as example here\nis a PNG file that uses the RGBA color model, and, therefore, each pixel of the image\nis represented by 4 integer values. You can download this image by visiting the `ZigExamples/image_filter`\n[folder at the official repository of this book](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/image_filter)[^img-filter-folder].\nYou can also find in this folder the complete source code of this small project that we\nare developing here.\n\n[^img-filter-folder]: \n\nThere are some C libraries available that we can use to read and parse PNG files.\nThe most famous and used of all is `libpng`, which is the \"official library\" for reading and writing\nPNG files. Although this library is available on most operating system, it's well known\nfor being complex and hard to use.\n\nThat is why, I'm going to use a more modern alternative here in this project, which is the `libspng` library.\nI choose to use this C library here, because it's much, much simpler to use than `libpng`,\nand it also offers very good performance for all operations. You can checkout the\n[official website of the library](https://libspng.org/)[^libspng]\nto know more about it. You will also find there some documentation that might help you to understand and\nfollow the code examples exposed here.\n\n[^libspng]: \n\n\nFirst of all, remember to build and install this `libspng` into your system. Because\nif you don't do this step, the `zig` compiler will not be able to find the files and resources of\nthis library in your computer, and link them with the Zig source code that we are writing together here.\nThere is good information about how to build and install the library at the\n[build section of the library documentation](https://libspng.org/docs/build/)[^lib-build].\n\n[^lib-build]: \n\n\n\n\n## Reading the PNG file\n\nIn order to extract the pixel data from the PNG file, we need to read and decode the file.\nA PNG file is just a binary file written in the \"PNG format\". Luckily, the `libspng` library offers\na function called `spng_decode_image()` that does all this heavy work for us.\n\nNow, since `libspng` is a C library, most of the file and I/O operations in this library are made by using\na `FILE` C pointer. Because of that, is probably a better idea to use the `fopen()` C function\nto open our PNG file, instead of using the `openFile()` method that I introduced in @sec-filesystem.\nThat is why I'm importing the `stdio.h` C header in this project, and using the `fopen()` C function to open the file.\n\nIf you look at the snippet below, you can see that we are:\n\n1. opening the PNG file with `fopen()`.\n1. creating the `libspng` context with `spng_ctx_new()`.\n1. using `spng_set_png_file()` to specify the `FILE` object that reads the PNG file that we are going to use.\n\nEvery operation in `libspng` is made through a \"context object\". In our snippet below, this object is `ctx`.\nAlso, to perform an operation over a PNG file, we need to specify which exact PNG file we are referring to.\nThis is the job of `spng_set_png_file()`. We are using this function to specify the file descriptor\nobject that reads the PNG file that we want to use.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cDefine(\"_NO_CRT_STDIO_INLINE\", \"1\");\n @cInclude(\"stdio.h\");\n @cInclude(\"spng.h\");\n});\n\nconst path = \"pedro_pascal.png\";\nconst file_descriptor = c.fopen(path, \"rb\");\nif (file_descriptor == null) {\n @panic(\"Could not open file!\");\n}\nconst ctx = c.spng_ctx_new(0) orelse unreachable;\n_ = c.spng_set_png_file(\n ctx, @ptrCast(file_descriptor)\n);\n```\n:::\n\n\n\nBefore we continue, is important to emphasize the following: since we have opened the file with `fopen()`,\nwe have to remember to close the file at the end of the program, with `fclose()`.\nIn other words, after we have done everything that we wanted to do with the PNG file\n`pedro_pascal.png`, we need to close this file, by applying `fclose()` over the file descriptor object.\nWe could use also the `defer` keyword to help us in this task, if we want to.\nThis code snippet below demonstrates this step:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (c.fclose(file_descriptor) != 0) {\n return error.CouldNotCloseFileDescriptor;\n}\n```\n:::\n\n\n\n\n\n\n### Reading the image header section\n\nNow, the context object `ctx` is aware of our PNG file `pedro_pascal.png`, because it has access to\na file descriptor object to this file. The first thing that we are going to do is to read the\n\"image header section\" of the PNG file. This \"image header section\" is the section\nof the file that contains some basic information about the PNG file, like, the bit depth of the pixel data\nof the image, the color model used in the file, the dimensions of the image (height and width in number of pixels),\netc.\n\nTo make things easier, I will encapsulate this \"read image header\" operation into a\nnice and small function called `get_image_header()`. All that this function needs to do\nis to call the `spng_get_ihdr()` function. This function from `libspng` is responsible\nfor reading the image header data, and storing it into a C struct named `spng_ihdr`.\nThus, an object of type `spng_ihdr` is a C struct that contains the data from the\nimage header section of the PNG file.\n\nSince this Zig function is receiving a C object (the `libspng` context object) as input, I marked\nthe function argument `ctx` as \"a pointer to the context object\" (`*c.spng_ctx`), following the recommendations\nthat we have discussed in @sec-pass-c-structs.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn get_image_header(ctx: *c.spng_ctx) !c.spng_ihdr {\n var image_header: c.spng_ihdr = undefined;\n if (c.spng_get_ihdr(ctx, &image_header) != 0) {\n return error.CouldNotGetImageHeader;\n }\n\n return image_header;\n}\n\nvar image_header = try get_image_header(ctx);\n```\n:::\n\n\n\nAlso notice in this function, that I'm checking if the `spng_get_ihdr()` function call have\nreturned or not an integer value that is different than zero. Most functions from the\n`libspng` library return a code status as result, and the code status \"zero\" means\n\"success\". So any code status that is different than zero means that an error\noccurred while running `spng_get_ihdr()`. This is why I'm returning an error value from\nthe function in case the code status returned by the function is different than zero.\n\n\n### Allocating space for the pixel data\n\nBefore we read the pixel data from the PNG file, we need to allocate enough space to hold this data.\nBut in order to allocate such space, we first need to know how much space we need to allocate.\nThe dimensions of the image are obviously needed to calculate the size of this space. But there are\nother elements that also affect this number, such as the color model used in the image, the bit depth, and others.\n\nAnyway, all of this means that calculating the size of the space that we need, is not a simple task.\nThat is why the `libspng` library offers an utility function named\n`spng_decoded_image_size()` to calculate this size for us. Once again, I'm going\nto encapsulate the logic around this C function into a nice and small Zig function\nnamed `calc_output_size()`. You can see below that this function returns a nice\ninteger value as result, informing the size of the space that we need to allocate.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn calc_output_size(ctx: *c.spng_ctx) !u64 {\n var output_size: u64 = 0;\n const status = c.spng_decoded_image_size(\n ctx, c.SPNG_FMT_RGBA8, &output_size\n );\n if (status != 0) {\n return error.CouldNotCalcOutputSize;\n }\n return output_size;\n}\n```\n:::\n\n\n\n\n\nYou might quest yourself what the value `SPNG_FMT_RGBA8` means. This value is actually an enum\nvalue defined in the `spng.h` C header file. This enum is used to identify a \"PNG format\".\nMore precisely, it identifies a PNG file that uses the RGBA color model and 8 bit depth.\nSo, by providing this enum value as input to the `spng_decoded_image_size()` function,\nwe are saying to this function to calculate the size of the decoded pixel data, by considering\na PNG file that follows this \"RGBA color model with 8 bit depth\" format.\n\nHaving this function, we can use it in conjunction with an allocator object, to allocate an\narray of bytes (`u8` values) that is big enough to store the decoded pixel data of the image.\nNotice that I'm using `@memset()` to initialize the entire array to zero.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst output_size = try calc_output_size(ctx);\nvar buffer = try allocator.alloc(u8, output_size);\n@memset(buffer[0..], 0);\n```\n:::\n\n\n\n\n### Decoding the image data\n\nNow that we have the necessary space to store the decoded pixel data of the image,\nwe can start to actually decode and extract this pixel data from the image,\nby using the `spng_decode_image()` C function.\n\nThe `read_data_to_buffer()` Zig function exposed below summarises the necessary\nsteps to read this decoded pixel data, and store it into an input buffer.\nNotice that this function is encapsulating the logic around the `spng_decode_image()` function.\nAlso, we are using the `SPNG_FMT_RGBA8` enum value once again to inform the corresponding function,\nthat the PNG image being decoded, uses the RGBA color model and 8 bit depth.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn read_data_to_buffer(ctx: *c.spng_ctx, buffer: []u8) !void {\n const status = c.spng_decode_image(\n ctx,\n buffer.ptr,\n buffer.len,\n c.SPNG_FMT_RGBA8,\n 0\n );\n\n if (status != 0) {\n return error.CouldNotDecodeImage;\n }\n}\n```\n:::\n\n\n\nHaving this function at hand, we can apply it over our context object, and also, over\nthe buffer object that we have allocated in the previous section to hold the decoded pixel data\nof the image:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry read_data_to_buffer(ctx, buffer[0..]);\n```\n:::\n\n\n\n\n### Looking at the pixel data\n\nNow that we have the pixel data stored in our \"buffer object\", we can take\na quick look at the bytes. In the example below, we are looking at the first\n12 bytes in the decoded pixel data.\n\nIf you take a close look at these values, you might notice that every 4 bytes\nin the sequence is 255. Which, coincidentally is the maximum possible integer value\nto be represented by a `u8` value. So, if the range from 0 to 255, which is the range\nof integer values that can be represented by an `u8` value, can be represented as a scale from 0% to 100%,\nthese 255 values are essentially 100% in that scale.\n\nIf you recall from @sec-pixel-repr, I have\ndescribed in that section that our `pedro_pascal.png` PNG file uses the RGBA color model,\nwhich adds an alpha (or transparency) byte to each pixel in the image.\nAs consequence, each pixel in the image is represented by 4 bytes. Since we are looking\nhere are the first 12 bytes in the image, it means that we are looking at the data from\nthe first $12 / 4 = 3$ pixels in the image.\n\nSo, based on how these first 12 bytes (or these 3 pixels) look, with these 255 values at every 4 bytes, we can say that is likely\nthat every pixel in the image have alpha (or transparency) setted to 100%. This might not be true,\nbut, is the most likely possibility. Also, if we look at the image itself, which if your recall is\nexposed in @fig-pascal, we can see that the transparency does not change across the image,\nwhich enforces this theory.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry stdout.print(\"{any}\\n\", .{buffer[0..12]});\n```\n:::\n\n\n\n```\n{\n 200, 194, 216, 255, 203, 197,\n 219, 255, 206, 200, 223, 255\n}\n```\n\n\nWe can see in the above result that the first pixel in this image have 200 of red, 194 of green, and 216 of blue.\nHow do I know the order in which the colors appears in the sequence? If you have not guessed that yet,\nis because of the acronym RGB. First RED, then GREEN, then BLUE. If we scale these integer values\naccording to our scale of 0% to 100% (0 to 255), we get 78% of red, 76% of green and 85% of blue.\n\n\n\n## Applying the image filter\n\nNow that we have the data of each pixel in the image, we can focus on applying our image\nfilter over these pixels. Remember, our objective here is to apply a grayscale filter over\nthe image. A grayscale filter is a filter that transforms a colored image into a grayscale image.\n\nThere are different formulas and strategies to transform a colored image into a grayscale image.\nBut all of these different strategies normally involve applying some math over the colors of each pixel.\nIn this project, we are going to use the most general formula, which is exposed below.\nThis formula considers $r$ as the red of the pixel, $g$ as the green, $b$ as the blue, and $p'$ as the\nlinear luminance of the pixel.\n\n$$\n p' = (0.2126 \\times r) + (0.7152 \\times g) + (0.0722 \\times b)\n$${#eq-grayscale}\n\nThis @eq-grayscale is the formula to calculate the linear luminance of a pixel. It's worth noting that this formula\nworks only for images whose pixels are using the sRGB color space, which is the standard color space\nfor the web. Thus, ideally, all images on the web should use this color space. Luckily,\nthis is our case here, i.e., the `pedro_pascal.png` image is using this sRGB color space, and, as consequence,\nwe can use the @eq-grayscale. You can read more about this formula at the Wikipedia page for grayscale [@wiki_grayscale].\n\nThe `apply_image_filter()` function exposed below summarises the necessary steps to\napply @eq-grayscale over the pixels in the image. We just apply this function\nover our buffer object that contains our pixel data, and, as result, the pixel\ndata stored in this buffer object should now represent the grayscale version of our image.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn apply_image_filter(buffer:[]u8) !void {\n const len = buffer.len;\n const red_factor: f16 = 0.2126;\n const green_factor: f16 = 0.7152;\n const blue_factor: f16 = 0.0722;\n var index: u64 = 0;\n while (index < len) : (index += 4) {\n const rf: f16 = @floatFromInt(buffer[index]);\n const gf: f16 = @floatFromInt(buffer[index + 1]);\n const bf: f16 = @floatFromInt(buffer[index + 2]);\n const y_linear: f16 = (\n (rf * red_factor) + (gf * green_factor)\n + (bf * blue_factor)\n );\n buffer[index] = @intFromFloat(y_linear);\n buffer[index + 1] = @intFromFloat(y_linear);\n buffer[index + 2] = @intFromFloat(y_linear);\n }\n}\n\ntry apply_image_filter(buffer[0..]);\n```\n:::\n\n\n\n\n\n## Saving the grayscale version of the image\n\nSince we have now the grayscale version of our image stored in our buffer object,\nwe need to encode this buffer object back into the \"PNG format\", and save the encoded data into\na new PNG file in our filesystem, so that we can access and see the grayscale version of our image\nthat was produced by our small program.\n\nTo do that, the `libspng` library help us once again by offering an \"encode data to PNG\" type of function,\nwhich is the `spng_encode_image()` function. But in order to \"encode data to PNG\" with `libspng`, we need\nto create a new context object. This new context object must use an \"encoder context\", which\nis identified by the enum value `SPNG_CTX_ENCODER`.\n\nThe `save_png()` function exposed below, summarises all the necessary steps to save the\ngrayscale version of our image into a new PNG file in the filesystem. By default, this\nfunction will save the grayscale image into a file named `pedro_pascal_filter.png` in the CWD.\n\nNotice in this code example that we are using the same image header object (`image_header`) that we have\ncollected previously with the `get_image_header()` function. Remember, this image header object\nis a C struct (`spng_ihdr`) that contains basic information about our PNG file, such as\nthe dimensions of the image, the color model used, etc.\n\nIf we wanted to save a very different image in this new PNG file, e.g. an image\nwith different dimensions, or, an image that uses a different color model, a different bit depth, etc.\nwe would have to create a new image header (`spng_ihdr`) object that describes the properties\nof this new image.\n\nBut we are essentially saving the same image that we have begin with here (the dimensions of\nthe image, the color model, etc. are all still the same). The only difference\nbetween the two images are the colors of the pixels, which are now \"shades of gray\".\nAs consequence, we can safely use the exact same image header data in this new PNG file.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn save_png(image_header: *c.spng_ihdr, buffer: []u8) !void {\n const path = \"pedro_pascal_filter.png\";\n const file_descriptor = c.fopen(path.ptr, \"wb\");\n if (file_descriptor == null) {\n return error.CouldNotOpenFile;\n }\n const ctx = (\n c.spng_ctx_new(c.SPNG_CTX_ENCODER)\n orelse unreachable\n );\n defer c.spng_ctx_free(ctx);\n _ = c.spng_set_png_file(ctx, @ptrCast(file_descriptor));\n _ = c.spng_set_ihdr(ctx, image_header);\n\n const encode_status = c.spng_encode_image(\n ctx,\n buffer.ptr,\n buffer.len,\n c.SPNG_FMT_PNG,\n c.SPNG_ENCODE_FINALIZE\n );\n if (encode_status != 0) {\n return error.CouldNotEncodeImage;\n }\n if (c.fclose(file_descriptor) != 0) {\n return error.CouldNotCloseFileDescriptor;\n }\n}\n\ntry save_png(&image_header, buffer[0..]);\n```\n:::\n\n\n\nAfter we execute this `save_png()` function, we should have a new PNG file\ninside our CWD, named `pedro_pascal_filter.png`. If we open this PNG file,\nwe will see the same image exposed in @fig-pascal-gray.\n\n\n## Building our project\n\nNow that we have written the code, let's discuss how can we build/compile this project.\nTo do that, I'm going to create a `build.zig` file in the root directory of our project,\nand start writing the necessary code to compile the project, using the knowledge\nthat we have acquired from @sec-build-system.\n\n\nWe first create the build target for our executable file, that executes our\nZig code. Let's suppose that all of our Zig code was written into a Zig module\nnamed `image_filter.zig`. The `exe` object exposed in the build script below\ndescribes the build target for our executable file.\n\nSince we have used some C code from the `libspng` library in our Zig code,\nwe need to link our Zig code (which is in the `exe` build target) to both\nthe C Standard Library, and, to the `libspng` library. We do that, by calling\nthe `linkLibC()` and `linkSystemLibrary()` methods from our `exe` build target.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const target = b.standardTargetOptions(.{});\n const optimize = b.standardOptimizeOption(.{});\n const exe = b.addExecutable(.{\n .name = \"image_filter\",\n .root_source_file = b.path(\"src/image_filter.zig\"),\n .target = target,\n .optimize = optimize,\n });\n exe.linkLibC();\n // Link to libspng library:\n exe.linkSystemLibrary(\"spng\");\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\nSince we are using the `linkSystemLibrary()` method, it means that the library\nfiles for `libspng` are searched in your system to be linked with the `exe` build target.\nIf you have not yet built and installed the `libspng` library into your system, this\nlinkage step will likely not work. Because it will not find the library files in your system.\n\nSo, just remember to install `libspng` in your system, if you want to build this project.\nHaving this build script above written, we can finally build our project by\nrunning the `zig build` command in the terminal.\n\n```bash\nzig build\n```\n", - "supporting": [ - "13-image-filter_files" - ], - "filters": [ - "rmarkdown/pagebreak.lua" - ], - "includes": {}, - "engineDependencies": { - "knitr": [ - "{\"type\":\"list\",\"attributes\":{},\"value\":[]}" - ] - }, - "preserve": null, - "postProcess": false - } -} \ No newline at end of file diff --git a/_freeze/Chapters/13-image-filter/execute-results/html.json b/_freeze/Chapters/13-image-filter/execute-results/html.json index 5564dfd4..2fd55048 100644 --- a/_freeze/Chapters/13-image-filter/execute-results/html.json +++ b/_freeze/Chapters/13-image-filter/execute-results/html.json @@ -2,10 +2,8 @@ "hash": "99b3cf5d4ae363f25838f780686e3234", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Project 4 - Developing an image filter\n\nIn this chapter we are going to build a new project. The objective of\nthis project is to write a program that applies a filter over an image.\nMore specifically, a \"grayscale filter\", which transforms\nany color image into a grayscale image.\n\nWe are going to use the image displayed in @fig-pascal in this project.\nIn other words, we want to transform this colored image into a grayscale image,\nby using our \"image filter program\" written in Zig.\n\n![A photo of the chilean-american actor Pedro Pascal. Source: Google Images.](../ZigExamples/image_filter/pedro_pascal.png){#fig-pascal}\n\nWe don't need to write a lot of code to build such \"image filter program\". However, we first need\nto understand how digital images work. That is why we begin this chapter\nby explaining the theory behind digital images and how colors are represented in modern computers.\nWe also give a brief explanation about the PNG (Portable Network Graphics) file format, which is the format used\nin the example images.\n\nAt the end of this chapter, we should have a full example of a program that takes the PNG image displayed in @fig-pascal\nas input, and writes a new image to the current working directory that is the grayscale version of this input image.\nThis grayscale version of @fig-pascal is exposed in @fig-pascal-gray.\nYou can find the full source code of this small project at the `ZigExamples/image_filter`\n[folder at the official repository of this book](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/image_filter)[^img-filter-folder].\n\n\n![The grayscale version of the photo.](../ZigExamples/image_filter/pedro_pascal_filter.png){#fig-pascal-gray}\n\n\n## How we see things? {#sec-eyes}\n\nIn this section, I want to briefly describe to you how we (humans) actually see things with our own eyes.\nI mean, how our eyes work? If you do have a very basic understanding of how our eyes work, you will understand\nmore easily how digital images are made. Because the techniques behind digital images\nwere developed by taking a lot of inspiration from how our human eyes work.\n\nYou can interpret a human eye as a light sensor, or, a light receptor. The eye receives some amount of light as input,\nand it interprets the colors that are present in this \"amount of light\".\nIf no amount of light hits the eye, then, the eye cannot extract color from it, and as result,\nwe end up seeing nothing, or, more precisely, we see complete blackness.\n\nTherefore, everything depends on light. What we actually see are the colors (blue, red, orange, green, purple, yellow, etc.) that\nare being reflected from the light that is hitting our eyes. **Light is the source of all colors!**\nThis is what Isaac Newton discovered on his famous prism experiment[^newton] in the 1660s.\n\n[^newton]: \n\nInside our eyes, we have a specific type of cell called the \"cone cell\".\nOur eye have three different types, or, three different versions of these \"cone cells\".\nEach type of cone cell is very sensitive to a specific spectrum of the light. More specifically,\nto the spectrums that define the colors red, green and blue.\nSo, in summary, our eyes have specific types of cells that\nare highly sensitive to these three colors (red, green and blue).\n\nThese are the cells responsible for perceiving the color present in the light that hits our eyes.\nAs a result, our eyes perceives color as a mixture of these three colors (red, green and blue). By having an amount\nof each one of these three colors, and mixing them together, we can get any other visible color\nthat we want. So every color that we see is perceived as a specific mixture of blues, greens and reds,\nlike 30% of red, plus 20% of green, plus 50% of blue.\n\nWhen these cone cells perceive (or, detect) the colors that are found in the\nlight that is hitting our eyes, these cells produce electrical signals, which are sent to the brain.\nOur brain interprets these electrical signals, and use them to form the image that we are seeing\ninside our head.\n\nBased on what we have discussed here, the bullet points exposed below describes the sequence of events that\ncomposes this very simplified version of how our human eyes work:\n\n1. Light hits our eyes.\n1. The cone cells perceive the colors that are present in this light.\n1. Cone cells produce electrical signals that describes the colors that were perceived in the light.\n1. The electrical signals are sent to the brain.\n1. Brain interprets these signals, and form the image based on the colors identified by these electrical signals.\n\n\n## How digital images work? {#sec-digital-img}\n\nA digital image is a \"digital representation\" of an image that we see with our eyes.\nIn other words, a digital image is a \"digital representation\" of the colors that we see\nand perceive through the light.\nIn the digital world, we have two types of images, which are: vector images and raster images.\nVector images are not described here. So just remember that the content discussed here\n**is related solely to raster images**, and not vector images.\n\nA raster image is a type of digital image that is represented as a 2D (two dimensional) matrix\nof pixels. In other words, every raster image is basically a rectangle of pixels, and each pixel have a particular color.\nSo, a raster image is just a rectangle of pixels, and each of these pixels are displayed in the screen of your computer (or the screen\nof any other device, e.g. laptop, tablet, smartphone, etc.) as a color.\n\n@fig-raster demonstrates this idea. If you take any raster image, and you zoom into it very hard,\nyou will see the actual pixels of the image. JPEG, TIFF and PNG are file formats that are commonly\nused to store raster images.\n\n![Zooming over a raster image to see the pixels. Source: Google Images.](../Figures/imagem-raster.png){#fig-raster}\n\nThe more pixels the image has, the more information and detail we can include in the image.\nThe more accurate, sharp and pretty the image will look. This is why photographic cameras\nusually produce big raster images, with several megapixels of resolution, to include as much detail as possible into the final image.\nAs an example, a digital image with dimensions of 1920 pixels wide and 1080 pixels high, would be a image that\ncontains $1920 \\times 1080 = 2073600$ pixels in total. You could also say that the \"total area\" of the image is\nof 2073600 pixels, although the concept of \"area\" is not really used here in computer graphics.\n\nMost digital images we see in our modern world uses the RGB color model. RGB stands for (red, green and blue).\nSo the color of each pixel in these raster images are usually represented as a mixture of red, green and blue,\njust like in our eyes. That is, the color of each pixel is identified by a set of\nthree different integer values. Each integer value identifies the \"amount\" of each color (red, green and blue).\nFor example, the set `(199, 78, 70)` identifies a color that is more close to red. We have 199 of red, 78 of green,\nand 70 of blue. In contrast, the set `(129, 77, 250)` describes a color that is more close to purple. Et cetera.\n\n\n\n### Images are displayed from top to bottom\n\nThis is not a rule written in stone, but the big majority of digital images are displayed from top\nto bottom and left to right. Most computers screens also follow this pattern. So, the first pixels\nin the image are the ones that are at the top and left corner of the image. You can find a visual representation\nof this logic in @fig-img-display.\n\nAlso notice in @fig-img-display that, because a raster image is essentially a 2D matrix of pixels,\nthe image is organized into rows and columns of pixels. The columns are defined by the horizontal x axis,\nwhile the rows are defined by the vertical y axis.\n\nEach pixel (i.e., the gray rectangles) exposed in @fig-img-display contains a number inside of it.\nThese numbers are the indexes of the pixels. You can notice that the first pixels are in the top and left\ncorner, and also, that the indexes of these pixels \"grow to the sides\", or, in other words, they grow in the direction of the horizontal x axis.\nMost raster images are organized as rows of pixels. Thus, when these digital images are\ndisplayed, the screen display the first row of pixels, then, the second row, then, the third row, etc.\n\n![How the pixels of raster images are displayed.](./../Figures/image-display.png){#fig-img-display}\n\n\n\n\n\n\n### Representing the matrix of pixels in code {#sec-pixel-repr}\n\nOk, we know already that raster images are represented as 2D matrices of pixels.\nBut we do not have a notion of a 2D matrix in Zig. Actually, most low-level languages in general\n(Zig, C, Rust, etc.) do not have such notion.\nSo how can we represent such matrix of pixels in Zig, or any other low-level language?\nThe strategy that most programmers choose in this situation is to just use a normal 1D array to store the values of\nthis 2D matrix. In other words, you just create an normal 1D array, and store all values from both dimensions into this 1D array.\n\nAs an example, suppose we have a very small image of dimensions 4x3.\nSince a raster image is represented as a 2D matrix of pixels, and each pixel\nis represented by 3 \"unsigned 8-bit\" integer values, we have 12 pixels in\ntotal in this image, which are represented by $3 \\times 12 = 36$ integer values.\nTherefore, we need to create an array of 36 `u8` values to store this small image.\n\nThe reason why unsigned 8-bit integer (`u8`) values are used to represent the amounts of each color,\ninstead of any other integer type, is because they take the minimum amount of space as possible, or,\nthe minimum amount of bits as possible. Which helps to reduces the binary size of the image, i.e., the 2D matrix.\nAlso, they convey a good amount of precision and detail about the colors, even though they can represent\na relatively small range (from 0 to 255) of \"color amounts\".\n\nComing back to our initial example of a 4x3 image,\nthe `matrix` object exposed below could be an example of an 1D array that stores\nthe data that represents this 4x3 image.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst matrix = [_]u8{\n 201, 10, 25, 185, 65, 70,\n 65, 120, 110, 65, 120, 117,\n 98, 95, 12, 213, 26, 88,\n 143, 112, 65, 97, 99, 205,\n 234, 105, 56, 43, 44, 216,\n 45, 59, 243, 211, 209, 54,\n};\n```\n:::\n\n\n\n\nThe first three integer values in this array are the color amounts of the first pixel in the image.\nThe next three integers are the colors amounts for the second pixel.\nAnd the sequence goes on in this pattern. Having that in mind, the size of the array that stores\na raster image is usually a multiple of 3. In this case, the array have a size of 36.\n\nI mean, the size of the array is **usually** a multiple of 3, because in specific circumstances,\nit can also be a multiple of 4. This happens when a transparency amount is\nalso included into the raster image. In other words, there are some types of raster images\nthat uses a different color model, which is the RGBA (red, green, blue and alpha)\ncolor model. The \"alpha\" corresponds to an amount of transparency in the pixel.\nSo every pixel in a RGBA image is represented by a red, green, blue and alpha values.\n\nMost raster images uses the standard RGB model, so, for the most part, you will\nsee arrays sizes that are multiples of 3. But some images, especially the ones\nthat are stored in PNG files, might be using the RGBA model, and, therefore, are\nrepresented by an array whose size is a multiple of 4.\n\nIn our case here, the example image of our project (@fig-pascal) is a raster image\nstored in a PNG file, and this specific image is using the RGBA color model. Therefore,\neach pixel in the image is represented by 4 different integer values, and, as consequence,\nto store this image in our Zig code, we need to create an array whose size is a multiple of 4.\n\n\n## The PNG library that we are going to use\n\nLet's begin our project by focusing on writing the necessary Zig code to\nread the data from the PNG file. In other words, we want to read the PNG file exposed\nin @fig-pascal, and parse its data to extract the 2D matrix of pixels that represents the image.\n\nAs we have discussed in @sec-pixel-repr, the image that we are using as example here\nis a PNG file that uses the RGBA color model, and, therefore, each pixel of the image\nis represented by 4 integer values. You can download this image by visiting the `ZigExamples/image_filter`\n[folder at the official repository of this book](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/image_filter)[^img-filter-folder].\nYou can also find in this folder the complete source code of this small project that we\nare developing here.\n\n[^img-filter-folder]: \n\nThere are some C libraries available that we can use to read and parse PNG files.\nThe most famous and used of all is `libpng`, which is the \"official library\" for reading and writing\nPNG files. Although this library is available on most operating system, it's well known\nfor being complex and hard to use.\n\nThat is why, I'm going to use a more modern alternative here in this project, which is the `libspng` library.\nI choose to use this C library here, because it's much, much simpler to use than `libpng`,\nand it also offers very good performance for all operations. You can checkout the\n[official website of the library](https://libspng.org/)[^libspng]\nto know more about it. You will also find there some documentation that might help you to understand and\nfollow the code examples exposed here.\n\n[^libspng]: \n\n\nFirst of all, remember to build and install this `libspng` into your system. Because\nif you don't do this step, the `zig` compiler will not be able to find the files and resources of\nthis library in your computer, and link them with the Zig source code that we are writing together here.\nThere is good information about how to build and install the library at the\n[build section of the library documentation](https://libspng.org/docs/build/)[^lib-build].\n\n[^lib-build]: \n\n\n\n\n## Reading the PNG file\n\nIn order to extract the pixel data from the PNG file, we need to read and decode the file.\nA PNG file is just a binary file written in the \"PNG format\". Luckily, the `libspng` library offers\na function called `spng_decode_image()` that does all this heavy work for us.\n\nNow, since `libspng` is a C library, most of the file and I/O operations in this library are made by using\na `FILE` C pointer. Because of that, is probably a better idea to use the `fopen()` C function\nto open our PNG file, instead of using the `openFile()` method that I introduced in @sec-filesystem.\nThat is why I'm importing the `stdio.h` C header in this project, and using the `fopen()` C function to open the file.\n\nIf you look at the snippet below, you can see that we are:\n\n1. opening the PNG file with `fopen()`.\n1. creating the `libspng` context with `spng_ctx_new()`.\n1. using `spng_set_png_file()` to specify the `FILE` object that reads the PNG file that we are going to use.\n\nEvery operation in `libspng` is made through a \"context object\". In our snippet below, this object is `ctx`.\nAlso, to perform an operation over a PNG file, we need to specify which exact PNG file we are referring to.\nThis is the job of `spng_set_png_file()`. We are using this function to specify the file descriptor\nobject that reads the PNG file that we want to use.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cDefine(\"_NO_CRT_STDIO_INLINE\", \"1\");\n @cInclude(\"stdio.h\");\n @cInclude(\"spng.h\");\n});\n\nconst path = \"pedro_pascal.png\";\nconst file_descriptor = c.fopen(path, \"rb\");\nif (file_descriptor == null) {\n @panic(\"Could not open file!\");\n}\nconst ctx = c.spng_ctx_new(0) orelse unreachable;\n_ = c.spng_set_png_file(\n ctx, @ptrCast(file_descriptor)\n);\n```\n:::\n\n\n\n\nBefore we continue, is important to emphasize the following: since we have opened the file with `fopen()`,\nwe have to remember to close the file at the end of the program, with `fclose()`.\nIn other words, after we have done everything that we wanted to do with the PNG file\n`pedro_pascal.png`, we need to close this file, by applying `fclose()` over the file descriptor object.\nWe could use also the `defer` keyword to help us in this task, if we want to.\nThis code snippet below demonstrates this step:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (c.fclose(file_descriptor) != 0) {\n return error.CouldNotCloseFileDescriptor;\n}\n```\n:::\n\n\n\n\n\n\n\n### Reading the image header section\n\nNow, the context object `ctx` is aware of our PNG file `pedro_pascal.png`, because it has access to\na file descriptor object to this file. The first thing that we are going to do is to read the\n\"image header section\" of the PNG file. This \"image header section\" is the section\nof the file that contains some basic information about the PNG file, like, the bit depth of the pixel data\nof the image, the color model used in the file, the dimensions of the image (height and width in number of pixels),\netc.\n\nTo make things easier, I will encapsulate this \"read image header\" operation into a\nnice and small function called `get_image_header()`. All that this function needs to do\nis to call the `spng_get_ihdr()` function. This function from `libspng` is responsible\nfor reading the image header data, and storing it into a C struct named `spng_ihdr`.\nThus, an object of type `spng_ihdr` is a C struct that contains the data from the\nimage header section of the PNG file.\n\nSince this Zig function is receiving a C object (the `libspng` context object) as input, I marked\nthe function argument `ctx` as \"a pointer to the context object\" (`*c.spng_ctx`), following the recommendations\nthat we have discussed in @sec-pass-c-structs.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn get_image_header(ctx: *c.spng_ctx) !c.spng_ihdr {\n var image_header: c.spng_ihdr = undefined;\n if (c.spng_get_ihdr(ctx, &image_header) != 0) {\n return error.CouldNotGetImageHeader;\n }\n\n return image_header;\n}\n\nvar image_header = try get_image_header(ctx);\n```\n:::\n\n\n\n\nAlso notice in this function, that I'm checking if the `spng_get_ihdr()` function call have\nreturned or not an integer value that is different than zero. Most functions from the\n`libspng` library return a code status as result, and the code status \"zero\" means\n\"success\". So any code status that is different than zero means that an error\noccurred while running `spng_get_ihdr()`. This is why I'm returning an error value from\nthe function in case the code status returned by the function is different than zero.\n\n\n### Allocating space for the pixel data\n\nBefore we read the pixel data from the PNG file, we need to allocate enough space to hold this data.\nBut in order to allocate such space, we first need to know how much space we need to allocate.\nThe dimensions of the image are obviously needed to calculate the size of this space. But there are\nother elements that also affect this number, such as the color model used in the image, the bit depth, and others.\n\nAnyway, all of this means that calculating the size of the space that we need, is not a simple task.\nThat is why the `libspng` library offers an utility function named\n`spng_decoded_image_size()` to calculate this size for us. Once again, I'm going\nto encapsulate the logic around this C function into a nice and small Zig function\nnamed `calc_output_size()`. You can see below that this function returns a nice\ninteger value as result, informing the size of the space that we need to allocate.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn calc_output_size(ctx: *c.spng_ctx) !u64 {\n var output_size: u64 = 0;\n const status = c.spng_decoded_image_size(\n ctx, c.SPNG_FMT_RGBA8, &output_size\n );\n if (status != 0) {\n return error.CouldNotCalcOutputSize;\n }\n return output_size;\n}\n```\n:::\n\n\n\n\n\n\nYou might quest yourself what the value `SPNG_FMT_RGBA8` means. This value is actually an enum\nvalue defined in the `spng.h` C header file. This enum is used to identify a \"PNG format\".\nMore precisely, it identifies a PNG file that uses the RGBA color model and 8 bit depth.\nSo, by providing this enum value as input to the `spng_decoded_image_size()` function,\nwe are saying to this function to calculate the size of the decoded pixel data, by considering\na PNG file that follows this \"RGBA color model with 8 bit depth\" format.\n\nHaving this function, we can use it in conjunction with an allocator object, to allocate an\narray of bytes (`u8` values) that is big enough to store the decoded pixel data of the image.\nNotice that I'm using `@memset()` to initialize the entire array to zero.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst output_size = try calc_output_size(ctx);\nvar buffer = try allocator.alloc(u8, output_size);\n@memset(buffer[0..], 0);\n```\n:::\n\n\n\n\n\n### Decoding the image data\n\nNow that we have the necessary space to store the decoded pixel data of the image,\nwe can start to actually decode and extract this pixel data from the image,\nby using the `spng_decode_image()` C function.\n\nThe `read_data_to_buffer()` Zig function exposed below summarises the necessary\nsteps to read this decoded pixel data, and store it into an input buffer.\nNotice that this function is encapsulating the logic around the `spng_decode_image()` function.\nAlso, we are using the `SPNG_FMT_RGBA8` enum value once again to inform the corresponding function,\nthat the PNG image being decoded, uses the RGBA color model and 8 bit depth.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn read_data_to_buffer(ctx: *c.spng_ctx, buffer: []u8) !void {\n const status = c.spng_decode_image(\n ctx,\n buffer.ptr,\n buffer.len,\n c.SPNG_FMT_RGBA8,\n 0\n );\n\n if (status != 0) {\n return error.CouldNotDecodeImage;\n }\n}\n```\n:::\n\n\n\n\nHaving this function at hand, we can apply it over our context object, and also, over\nthe buffer object that we have allocated in the previous section to hold the decoded pixel data\nof the image:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry read_data_to_buffer(ctx, buffer[0..]);\n```\n:::\n\n\n\n\n\n### Looking at the pixel data\n\nNow that we have the pixel data stored in our \"buffer object\", we can take\na quick look at the bytes. In the example below, we are looking at the first\n12 bytes in the decoded pixel data.\n\nIf you take a close look at these values, you might notice that every 4 bytes\nin the sequence is 255. Which, coincidentally is the maximum possible integer value\nto be represented by a `u8` value. So, if the range from 0 to 255, which is the range\nof integer values that can be represented by an `u8` value, can be represented as a scale from 0% to 100%,\nthese 255 values are essentially 100% in that scale.\n\nIf you recall from @sec-pixel-repr, I have\ndescribed in that section that our `pedro_pascal.png` PNG file uses the RGBA color model,\nwhich adds an alpha (or transparency) byte to each pixel in the image.\nAs consequence, each pixel in the image is represented by 4 bytes. Since we are looking\nhere are the first 12 bytes in the image, it means that we are looking at the data from\nthe first $12 / 4 = 3$ pixels in the image.\n\nSo, based on how these first 12 bytes (or these 3 pixels) look, with these 255 values at every 4 bytes, we can say that is likely\nthat every pixel in the image have alpha (or transparency) setted to 100%. This might not be true,\nbut, is the most likely possibility. Also, if we look at the image itself, which if your recall is\nexposed in @fig-pascal, we can see that the transparency does not change across the image,\nwhich enforces this theory.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry stdout.print(\"{any}\\n\", .{buffer[0..12]});\n```\n:::\n\n\n\n\n```\n{\n 200, 194, 216, 255, 203, 197,\n 219, 255, 206, 200, 223, 255\n}\n```\n\n\nWe can see in the above result that the first pixel in this image have 200 of red, 194 of green, and 216 of blue.\nHow do I know the order in which the colors appears in the sequence? If you have not guessed that yet,\nis because of the acronym RGB. First RED, then GREEN, then BLUE. If we scale these integer values\naccording to our scale of 0% to 100% (0 to 255), we get 78% of red, 76% of green and 85% of blue.\n\n\n\n## Applying the image filter\n\nNow that we have the data of each pixel in the image, we can focus on applying our image\nfilter over these pixels. Remember, our objective here is to apply a grayscale filter over\nthe image. A grayscale filter is a filter that transforms a colored image into a grayscale image.\n\nThere are different formulas and strategies to transform a colored image into a grayscale image.\nBut all of these different strategies normally involve applying some math over the colors of each pixel.\nIn this project, we are going to use the most general formula, which is exposed below.\nThis formula considers $r$ as the red of the pixel, $g$ as the green, $b$ as the blue, and $p'$ as the\nlinear luminance of the pixel.\n\n$$\n p' = (0.2126 \\times r) + (0.7152 \\times g) + (0.0722 \\times b)\n$${#eq-grayscale}\n\nThis @eq-grayscale is the formula to calculate the linear luminance of a pixel. It's worth noting that this formula\nworks only for images whose pixels are using the sRGB color space, which is the standard color space\nfor the web. Thus, ideally, all images on the web should use this color space. Luckily,\nthis is our case here, i.e., the `pedro_pascal.png` image is using this sRGB color space, and, as consequence,\nwe can use the @eq-grayscale. You can read more about this formula at the Wikipedia page for grayscale [@wiki_grayscale].\n\nThe `apply_image_filter()` function exposed below summarises the necessary steps to\napply @eq-grayscale over the pixels in the image. We just apply this function\nover our buffer object that contains our pixel data, and, as result, the pixel\ndata stored in this buffer object should now represent the grayscale version of our image.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn apply_image_filter(buffer:[]u8) !void {\n const len = buffer.len;\n const red_factor: f16 = 0.2126;\n const green_factor: f16 = 0.7152;\n const blue_factor: f16 = 0.0722;\n var index: u64 = 0;\n while (index < len) : (index += 4) {\n const rf: f16 = @floatFromInt(buffer[index]);\n const gf: f16 = @floatFromInt(buffer[index + 1]);\n const bf: f16 = @floatFromInt(buffer[index + 2]);\n const y_linear: f16 = (\n (rf * red_factor) + (gf * green_factor)\n + (bf * blue_factor)\n );\n buffer[index] = @intFromFloat(y_linear);\n buffer[index + 1] = @intFromFloat(y_linear);\n buffer[index + 2] = @intFromFloat(y_linear);\n }\n}\n\ntry apply_image_filter(buffer[0..]);\n```\n:::\n\n\n\n\n\n\n## Saving the grayscale version of the image\n\nSince we have now the grayscale version of our image stored in our buffer object,\nwe need to encode this buffer object back into the \"PNG format\", and save the encoded data into\na new PNG file in our filesystem, so that we can access and see the grayscale version of our image\nthat was produced by our small program.\n\nTo do that, the `libspng` library help us once again by offering an \"encode data to PNG\" type of function,\nwhich is the `spng_encode_image()` function. But in order to \"encode data to PNG\" with `libspng`, we need\nto create a new context object. This new context object must use an \"encoder context\", which\nis identified by the enum value `SPNG_CTX_ENCODER`.\n\nThe `save_png()` function exposed below, summarises all the necessary steps to save the\ngrayscale version of our image into a new PNG file in the filesystem. By default, this\nfunction will save the grayscale image into a file named `pedro_pascal_filter.png` in the CWD.\n\nNotice in this code example that we are using the same image header object (`image_header`) that we have\ncollected previously with the `get_image_header()` function. Remember, this image header object\nis a C struct (`spng_ihdr`) that contains basic information about our PNG file, such as\nthe dimensions of the image, the color model used, etc.\n\nIf we wanted to save a very different image in this new PNG file, e.g. an image\nwith different dimensions, or, an image that uses a different color model, a different bit depth, etc.\nwe would have to create a new image header (`spng_ihdr`) object that describes the properties\nof this new image.\n\nBut we are essentially saving the same image that we have begin with here (the dimensions of\nthe image, the color model, etc. are all still the same). The only difference\nbetween the two images are the colors of the pixels, which are now \"shades of gray\".\nAs consequence, we can safely use the exact same image header data in this new PNG file.\n\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn save_png(image_header: *c.spng_ihdr, buffer: []u8) !void {\n const path = \"pedro_pascal_filter.png\";\n const file_descriptor = c.fopen(path.ptr, \"wb\");\n if (file_descriptor == null) {\n return error.CouldNotOpenFile;\n }\n const ctx = (\n c.spng_ctx_new(c.SPNG_CTX_ENCODER)\n orelse unreachable\n );\n defer c.spng_ctx_free(ctx);\n _ = c.spng_set_png_file(ctx, @ptrCast(file_descriptor));\n _ = c.spng_set_ihdr(ctx, image_header);\n\n const encode_status = c.spng_encode_image(\n ctx,\n buffer.ptr,\n buffer.len,\n c.SPNG_FMT_PNG,\n c.SPNG_ENCODE_FINALIZE\n );\n if (encode_status != 0) {\n return error.CouldNotEncodeImage;\n }\n if (c.fclose(file_descriptor) != 0) {\n return error.CouldNotCloseFileDescriptor;\n }\n}\n\ntry save_png(&image_header, buffer[0..]);\n```\n:::\n\n\n\n\nAfter we execute this `save_png()` function, we should have a new PNG file\ninside our CWD, named `pedro_pascal_filter.png`. If we open this PNG file,\nwe will see the same image exposed in @fig-pascal-gray.\n\n\n## Building our project\n\nNow that we have written the code, let's discuss how can we build/compile this project.\nTo do that, I'm going to create a `build.zig` file in the root directory of our project,\nand start writing the necessary code to compile the project, using the knowledge\nthat we have acquired from @sec-build-system.\n\n\nWe first create the build target for our executable file, that executes our\nZig code. Let's suppose that all of our Zig code was written into a Zig module\nnamed `image_filter.zig`. The `exe` object exposed in the build script below\ndescribes the build target for our executable file.\n\nSince we have used some C code from the `libspng` library in our Zig code,\nwe need to link our Zig code (which is in the `exe` build target) to both\nthe C Standard Library, and, to the `libspng` library. We do that, by calling\nthe `linkLibC()` and `linkSystemLibrary()` methods from our `exe` build target.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const target = b.standardTargetOptions(.{});\n const optimize = b.standardOptimizeOption(.{});\n const exe = b.addExecutable(.{\n .name = \"image_filter\",\n .root_source_file = b.path(\"src/image_filter.zig\"),\n .target = target,\n .optimize = optimize,\n });\n exe.linkLibC();\n // Link to libspng library:\n exe.linkSystemLibrary(\"spng\");\n b.installArtifact(exe);\n}\n```\n:::\n\n\n\n\nSince we are using the `linkSystemLibrary()` method, it means that the library\nfiles for `libspng` are searched in your system to be linked with the `exe` build target.\nIf you have not yet built and installed the `libspng` library into your system, this\nlinkage step will likely not work. Because it will not find the library files in your system.\n\nSo, just remember to install `libspng` in your system, if you want to build this project.\nHaving this build script above written, we can finally build our project by\nrunning the `zig build` command in the terminal.\n\n```bash\nzig build\n```\n", - "supporting": [ - "13-image-filter_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n# Project 4 - Developing an image filter\n\nIn this chapter we are going to build a new project. The objective of\nthis project is to write a program that applies a filter over an image.\nMore specifically, a \"grayscale filter\", which transforms\nany color image into a grayscale image.\n\nWe are going to use the image displayed in @fig-pascal in this project.\nIn other words, we want to transform this colored image into a grayscale image,\nby using our \"image filter program\" written in Zig.\n\n![A photo of the chilean-american actor Pedro Pascal. Source: Google Images.](../ZigExamples/image_filter/pedro_pascal.png){#fig-pascal}\n\nWe don't need to write a lot of code to build such \"image filter program\". However, we first need\nto understand how digital images work. That is why we begin this chapter\nby explaining the theory behind digital images and how colors are represented in modern computers.\nWe also give a brief explanation about the PNG (Portable Network Graphics) file format, which is the format used\nin the example images.\n\nAt the end of this chapter, we should have a full example of a program that takes the PNG image displayed in @fig-pascal\nas input, and writes a new image to the current working directory that is the grayscale version of this input image.\nThis grayscale version of @fig-pascal is exposed in @fig-pascal-gray.\nYou can find the full source code of this small project at the `ZigExamples/image_filter`\n[folder at the official repository of this book](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/image_filter)[^img-filter-folder].\n\n\n![The grayscale version of the photo.](../ZigExamples/image_filter/pedro_pascal_filter.png){#fig-pascal-gray}\n\n\n## How we see things? {#sec-eyes}\n\nIn this section, I want to briefly describe to you how we (humans) actually see things with our own eyes.\nI mean, how our eyes work? If you do have a very basic understanding of how our eyes work, you will understand\nmore easily how digital images are made. Because the techniques behind digital images\nwere developed by taking a lot of inspiration from how our human eyes work.\n\nYou can interpret a human eye as a light sensor, or, a light receptor. The eye receives some amount of light as input,\nand it interprets the colors that are present in this \"amount of light\".\nIf no amount of light hits the eye, then, the eye cannot extract color from it, and as result,\nwe end up seeing nothing, or, more precisely, we see complete blackness.\n\nTherefore, everything depends on light. What we actually see are the colors (blue, red, orange, green, purple, yellow, etc.) that\nare being reflected from the light that is hitting our eyes. **Light is the source of all colors!**\nThis is what Isaac Newton discovered on his famous prism experiment[^newton] in the 1660s.\n\n[^newton]: \n\nInside our eyes, we have a specific type of cell called the \"cone cell\".\nOur eye have three different types, or, three different versions of these \"cone cells\".\nEach type of cone cell is very sensitive to a specific spectrum of the light. More specifically,\nto the spectrums that define the colors red, green and blue.\nSo, in summary, our eyes have specific types of cells that\nare highly sensitive to these three colors (red, green and blue).\n\nThese are the cells responsible for perceiving the color present in the light that hits our eyes.\nAs a result, our eyes perceives color as a mixture of these three colors (red, green and blue). By having an amount\nof each one of these three colors, and mixing them together, we can get any other visible color\nthat we want. So every color that we see is perceived as a specific mixture of blues, greens and reds,\nlike 30% of red, plus 20% of green, plus 50% of blue.\n\nWhen these cone cells perceive (or, detect) the colors that are found in the\nlight that is hitting our eyes, these cells produce electrical signals, which are sent to the brain.\nOur brain interprets these electrical signals, and use them to form the image that we are seeing\ninside our head.\n\nBased on what we have discussed here, the bullet points exposed below describes the sequence of events that\ncomposes this very simplified version of how our human eyes work:\n\n1. Light hits our eyes.\n1. The cone cells perceive the colors that are present in this light.\n1. Cone cells produce electrical signals that describes the colors that were perceived in the light.\n1. The electrical signals are sent to the brain.\n1. Brain interprets these signals, and form the image based on the colors identified by these electrical signals.\n\n\n## How digital images work? {#sec-digital-img}\n\nA digital image is a \"digital representation\" of an image that we see with our eyes.\nIn other words, a digital image is a \"digital representation\" of the colors that we see\nand perceive through the light.\nIn the digital world, we have two types of images, which are: vector images and raster images.\nVector images are not described here. So just remember that the content discussed here\n**is related solely to raster images**, and not vector images.\n\nA raster image is a type of digital image that is represented as a 2D (two dimensional) matrix\nof pixels. In other words, every raster image is basically a rectangle of pixels, and each pixel have a particular color.\nSo, a raster image is just a rectangle of pixels, and each of these pixels are displayed in the screen of your computer (or the screen\nof any other device, e.g. laptop, tablet, smartphone, etc.) as a color.\n\n@fig-raster demonstrates this idea. If you take any raster image, and you zoom into it very hard,\nyou will see the actual pixels of the image. JPEG, TIFF and PNG are file formats that are commonly\nused to store raster images.\n\n![Zooming over a raster image to see the pixels. Source: Google Images.](../Figures/imagem-raster.png){#fig-raster}\n\nThe more pixels the image has, the more information and detail we can include in the image.\nThe more accurate, sharp and pretty the image will look. This is why photographic cameras\nusually produce big raster images, with several megapixels of resolution, to include as much detail as possible into the final image.\nAs an example, a digital image with dimensions of 1920 pixels wide and 1080 pixels high, would be a image that\ncontains $1920 \\times 1080 = 2073600$ pixels in total. You could also say that the \"total area\" of the image is\nof 2073600 pixels, although the concept of \"area\" is not really used here in computer graphics.\n\nMost digital images we see in our modern world uses the RGB color model. RGB stands for (red, green and blue).\nSo the color of each pixel in these raster images are usually represented as a mixture of red, green and blue,\njust like in our eyes. That is, the color of each pixel is identified by a set of\nthree different integer values. Each integer value identifies the \"amount\" of each color (red, green and blue).\nFor example, the set `(199, 78, 70)` identifies a color that is more close to red. We have 199 of red, 78 of green,\nand 70 of blue. In contrast, the set `(129, 77, 250)` describes a color that is more close to purple. Et cetera.\n\n\n\n### Images are displayed from top to bottom\n\nThis is not a rule written in stone, but the big majority of digital images are displayed from top\nto bottom and left to right. Most computers screens also follow this pattern. So, the first pixels\nin the image are the ones that are at the top and left corner of the image. You can find a visual representation\nof this logic in @fig-img-display.\n\nAlso notice in @fig-img-display that, because a raster image is essentially a 2D matrix of pixels,\nthe image is organized into rows and columns of pixels. The columns are defined by the horizontal x axis,\nwhile the rows are defined by the vertical y axis.\n\nEach pixel (i.e., the gray rectangles) exposed in @fig-img-display contains a number inside of it.\nThese numbers are the indexes of the pixels. You can notice that the first pixels are in the top and left\ncorner, and also, that the indexes of these pixels \"grow to the sides\", or, in other words, they grow in the direction of the horizontal x axis.\nMost raster images are organized as rows of pixels. Thus, when these digital images are\ndisplayed, the screen display the first row of pixels, then, the second row, then, the third row, etc.\n\n![How the pixels of raster images are displayed.](./../Figures/image-display.png){#fig-img-display}\n\n\n\n\n\n\n### Representing the matrix of pixels in code {#sec-pixel-repr}\n\nOk, we know already that raster images are represented as 2D matrices of pixels.\nBut we do not have a notion of a 2D matrix in Zig. Actually, most low-level languages in general\n(Zig, C, Rust, etc.) do not have such notion.\nSo how can we represent such matrix of pixels in Zig, or any other low-level language?\nThe strategy that most programmers choose in this situation is to just use a normal 1D array to store the values of\nthis 2D matrix. In other words, you just create an normal 1D array, and store all values from both dimensions into this 1D array.\n\nAs an example, suppose we have a very small image of dimensions 4x3.\nSince a raster image is represented as a 2D matrix of pixels, and each pixel\nis represented by 3 \"unsigned 8-bit\" integer values, we have 12 pixels in\ntotal in this image, which are represented by $3 \\times 12 = 36$ integer values.\nTherefore, we need to create an array of 36 `u8` values to store this small image.\n\nThe reason why unsigned 8-bit integer (`u8`) values are used to represent the amounts of each color,\ninstead of any other integer type, is because they take the minimum amount of space as possible, or,\nthe minimum amount of bits as possible. Which helps to reduces the binary size of the image, i.e., the 2D matrix.\nAlso, they convey a good amount of precision and detail about the colors, even though they can represent\na relatively small range (from 0 to 255) of \"color amounts\".\n\nComing back to our initial example of a 4x3 image,\nthe `matrix` object exposed below could be an example of an 1D array that stores\nthe data that represents this 4x3 image.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst matrix = [_]u8{\n 201, 10, 25, 185, 65, 70,\n 65, 120, 110, 65, 120, 117,\n 98, 95, 12, 213, 26, 88,\n 143, 112, 65, 97, 99, 205,\n 234, 105, 56, 43, 44, 216,\n 45, 59, 243, 211, 209, 54,\n};\n```\n:::\n\n\nThe first three integer values in this array are the color amounts of the first pixel in the image.\nThe next three integers are the colors amounts for the second pixel.\nAnd the sequence goes on in this pattern. Having that in mind, the size of the array that stores\na raster image is usually a multiple of 3. In this case, the array have a size of 36.\n\nI mean, the size of the array is **usually** a multiple of 3, because in specific circumstances,\nit can also be a multiple of 4. This happens when a transparency amount is\nalso included into the raster image. In other words, there are some types of raster images\nthat uses a different color model, which is the RGBA (red, green, blue and alpha)\ncolor model. The \"alpha\" corresponds to an amount of transparency in the pixel.\nSo every pixel in a RGBA image is represented by a red, green, blue and alpha values.\n\nMost raster images uses the standard RGB model, so, for the most part, you will\nsee arrays sizes that are multiples of 3. But some images, especially the ones\nthat are stored in PNG files, might be using the RGBA model, and, therefore, are\nrepresented by an array whose size is a multiple of 4.\n\nIn our case here, the example image of our project (@fig-pascal) is a raster image\nstored in a PNG file, and this specific image is using the RGBA color model. Therefore,\neach pixel in the image is represented by 4 different integer values, and, as consequence,\nto store this image in our Zig code, we need to create an array whose size is a multiple of 4.\n\n\n## The PNG library that we are going to use\n\nLet's begin our project by focusing on writing the necessary Zig code to\nread the data from the PNG file. In other words, we want to read the PNG file exposed\nin @fig-pascal, and parse its data to extract the 2D matrix of pixels that represents the image.\n\nAs we have discussed in @sec-pixel-repr, the image that we are using as example here\nis a PNG file that uses the RGBA color model, and, therefore, each pixel of the image\nis represented by 4 integer values. You can download this image by visiting the `ZigExamples/image_filter`\n[folder at the official repository of this book](https://github.com/pedropark99/zig-book/tree/main/ZigExamples/image_filter)[^img-filter-folder].\nYou can also find in this folder the complete source code of this small project that we\nare developing here.\n\n[^img-filter-folder]: \n\nThere are some C libraries available that we can use to read and parse PNG files.\nThe most famous and used of all is `libpng`, which is the \"official library\" for reading and writing\nPNG files. Although this library is available on most operating system, it's well known\nfor being complex and hard to use.\n\nThat is why, I'm going to use a more modern alternative here in this project, which is the `libspng` library.\nI choose to use this C library here, because it's much, much simpler to use than `libpng`,\nand it also offers very good performance for all operations. You can checkout the\n[official website of the library](https://libspng.org/)[^libspng]\nto know more about it. You will also find there some documentation that might help you to understand and\nfollow the code examples exposed here.\n\n[^libspng]: \n\n\nFirst of all, remember to build and install this `libspng` into your system. Because\nif you don't do this step, the `zig` compiler will not be able to find the files and resources of\nthis library in your computer, and link them with the Zig source code that we are writing together here.\nThere is good information about how to build and install the library at the\n[build section of the library documentation](https://libspng.org/docs/build/)[^lib-build].\n\n[^lib-build]: \n\n\n\n\n## Reading the PNG file\n\nIn order to extract the pixel data from the PNG file, we need to read and decode the file.\nA PNG file is just a binary file written in the \"PNG format\". Luckily, the `libspng` library offers\na function called `spng_decode_image()` that does all this heavy work for us.\n\nNow, since `libspng` is a C library, most of the file and I/O operations in this library are made by using\na `FILE` C pointer. Because of that, is probably a better idea to use the `fopen()` C function\nto open our PNG file, instead of using the `openFile()` method that I introduced in @sec-filesystem.\nThat is why I'm importing the `stdio.h` C header in this project, and using the `fopen()` C function to open the file.\n\nIf you look at the snippet below, you can see that we are:\n\n1. opening the PNG file with `fopen()`.\n1. creating the `libspng` context with `spng_ctx_new()`.\n1. using `spng_set_png_file()` to specify the `FILE` object that reads the PNG file that we are going to use.\n\nEvery operation in `libspng` is made through a \"context object\". In our snippet below, this object is `ctx`.\nAlso, to perform an operation over a PNG file, we need to specify which exact PNG file we are referring to.\nThis is the job of `spng_set_png_file()`. We are using this function to specify the file descriptor\nobject that reads the PNG file that we want to use.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cDefine(\"_NO_CRT_STDIO_INLINE\", \"1\");\n @cInclude(\"stdio.h\");\n @cInclude(\"spng.h\");\n});\n\nconst path = \"pedro_pascal.png\";\nconst file_descriptor = c.fopen(path, \"rb\");\nif (file_descriptor == null) {\n @panic(\"Could not open file!\");\n}\nconst ctx = c.spng_ctx_new(0) orelse unreachable;\n_ = c.spng_set_png_file(\n ctx, @ptrCast(file_descriptor)\n);\n```\n:::\n\n\nBefore we continue, is important to emphasize the following: since we have opened the file with `fopen()`,\nwe have to remember to close the file at the end of the program, with `fclose()`.\nIn other words, after we have done everything that we wanted to do with the PNG file\n`pedro_pascal.png`, we need to close this file, by applying `fclose()` over the file descriptor object.\nWe could use also the `defer` keyword to help us in this task, if we want to.\nThis code snippet below demonstrates this step:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nif (c.fclose(file_descriptor) != 0) {\n return error.CouldNotCloseFileDescriptor;\n}\n```\n:::\n\n\n\n\n\n### Reading the image header section\n\nNow, the context object `ctx` is aware of our PNG file `pedro_pascal.png`, because it has access to\na file descriptor object to this file. The first thing that we are going to do is to read the\n\"image header section\" of the PNG file. This \"image header section\" is the section\nof the file that contains some basic information about the PNG file, like, the bit depth of the pixel data\nof the image, the color model used in the file, the dimensions of the image (height and width in number of pixels),\netc.\n\nTo make things easier, I will encapsulate this \"read image header\" operation into a\nnice and small function called `get_image_header()`. All that this function needs to do\nis to call the `spng_get_ihdr()` function. This function from `libspng` is responsible\nfor reading the image header data, and storing it into a C struct named `spng_ihdr`.\nThus, an object of type `spng_ihdr` is a C struct that contains the data from the\nimage header section of the PNG file.\n\nSince this Zig function is receiving a C object (the `libspng` context object) as input, I marked\nthe function argument `ctx` as \"a pointer to the context object\" (`*c.spng_ctx`), following the recommendations\nthat we have discussed in @sec-pass-c-structs.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn get_image_header(ctx: *c.spng_ctx) !c.spng_ihdr {\n var image_header: c.spng_ihdr = undefined;\n if (c.spng_get_ihdr(ctx, &image_header) != 0) {\n return error.CouldNotGetImageHeader;\n }\n\n return image_header;\n}\n\nvar image_header = try get_image_header(ctx);\n```\n:::\n\n\nAlso notice in this function, that I'm checking if the `spng_get_ihdr()` function call have\nreturned or not an integer value that is different than zero. Most functions from the\n`libspng` library return a code status as result, and the code status \"zero\" means\n\"success\". So any code status that is different than zero means that an error\noccurred while running `spng_get_ihdr()`. This is why I'm returning an error value from\nthe function in case the code status returned by the function is different than zero.\n\n\n### Allocating space for the pixel data\n\nBefore we read the pixel data from the PNG file, we need to allocate enough space to hold this data.\nBut in order to allocate such space, we first need to know how much space we need to allocate.\nThe dimensions of the image are obviously needed to calculate the size of this space. But there are\nother elements that also affect this number, such as the color model used in the image, the bit depth, and others.\n\nAnyway, all of this means that calculating the size of the space that we need, is not a simple task.\nThat is why the `libspng` library offers an utility function named\n`spng_decoded_image_size()` to calculate this size for us. Once again, I'm going\nto encapsulate the logic around this C function into a nice and small Zig function\nnamed `calc_output_size()`. You can see below that this function returns a nice\ninteger value as result, informing the size of the space that we need to allocate.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn calc_output_size(ctx: *c.spng_ctx) !u64 {\n var output_size: u64 = 0;\n const status = c.spng_decoded_image_size(\n ctx, c.SPNG_FMT_RGBA8, &output_size\n );\n if (status != 0) {\n return error.CouldNotCalcOutputSize;\n }\n return output_size;\n}\n```\n:::\n\n\n\n\nYou might quest yourself what the value `SPNG_FMT_RGBA8` means. This value is actually an enum\nvalue defined in the `spng.h` C header file. This enum is used to identify a \"PNG format\".\nMore precisely, it identifies a PNG file that uses the RGBA color model and 8 bit depth.\nSo, by providing this enum value as input to the `spng_decoded_image_size()` function,\nwe are saying to this function to calculate the size of the decoded pixel data, by considering\na PNG file that follows this \"RGBA color model with 8 bit depth\" format.\n\nHaving this function, we can use it in conjunction with an allocator object, to allocate an\narray of bytes (`u8` values) that is big enough to store the decoded pixel data of the image.\nNotice that I'm using `@memset()` to initialize the entire array to zero.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst output_size = try calc_output_size(ctx);\nvar buffer = try allocator.alloc(u8, output_size);\n@memset(buffer[0..], 0);\n```\n:::\n\n\n\n### Decoding the image data\n\nNow that we have the necessary space to store the decoded pixel data of the image,\nwe can start to actually decode and extract this pixel data from the image,\nby using the `spng_decode_image()` C function.\n\nThe `read_data_to_buffer()` Zig function exposed below summarises the necessary\nsteps to read this decoded pixel data, and store it into an input buffer.\nNotice that this function is encapsulating the logic around the `spng_decode_image()` function.\nAlso, we are using the `SPNG_FMT_RGBA8` enum value once again to inform the corresponding function,\nthat the PNG image being decoded, uses the RGBA color model and 8 bit depth.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn read_data_to_buffer(ctx: *c.spng_ctx, buffer: []u8) !void {\n const status = c.spng_decode_image(\n ctx,\n buffer.ptr,\n buffer.len,\n c.SPNG_FMT_RGBA8,\n 0\n );\n\n if (status != 0) {\n return error.CouldNotDecodeImage;\n }\n}\n```\n:::\n\n\nHaving this function at hand, we can apply it over our context object, and also, over\nthe buffer object that we have allocated in the previous section to hold the decoded pixel data\nof the image:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry read_data_to_buffer(ctx, buffer[0..]);\n```\n:::\n\n\n\n### Looking at the pixel data\n\nNow that we have the pixel data stored in our \"buffer object\", we can take\na quick look at the bytes. In the example below, we are looking at the first\n12 bytes in the decoded pixel data.\n\nIf you take a close look at these values, you might notice that every 4 bytes\nin the sequence is 255. Which, coincidentally is the maximum possible integer value\nto be represented by a `u8` value. So, if the range from 0 to 255, which is the range\nof integer values that can be represented by an `u8` value, can be represented as a scale from 0% to 100%,\nthese 255 values are essentially 100% in that scale.\n\nIf you recall from @sec-pixel-repr, I have\ndescribed in that section that our `pedro_pascal.png` PNG file uses the RGBA color model,\nwhich adds an alpha (or transparency) byte to each pixel in the image.\nAs consequence, each pixel in the image is represented by 4 bytes. Since we are looking\nhere are the first 12 bytes in the image, it means that we are looking at the data from\nthe first $12 / 4 = 3$ pixels in the image.\n\nSo, based on how these first 12 bytes (or these 3 pixels) look, with these 255 values at every 4 bytes, we can say that is likely\nthat every pixel in the image have alpha (or transparency) setted to 100%. This might not be true,\nbut, is the most likely possibility. Also, if we look at the image itself, which if your recall is\nexposed in @fig-pascal, we can see that the transparency does not change across the image,\nwhich enforces this theory.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\ntry stdout.print(\"{any}\\n\", .{buffer[0..12]});\n```\n:::\n\n\n```\n{\n 200, 194, 216, 255, 203, 197,\n 219, 255, 206, 200, 223, 255\n}\n```\n\n\nWe can see in the above result that the first pixel in this image have 200 of red, 194 of green, and 216 of blue.\nHow do I know the order in which the colors appears in the sequence? If you have not guessed that yet,\nis because of the acronym RGB. First RED, then GREEN, then BLUE. If we scale these integer values\naccording to our scale of 0% to 100% (0 to 255), we get 78% of red, 76% of green and 85% of blue.\n\n\n\n## Applying the image filter\n\nNow that we have the data of each pixel in the image, we can focus on applying our image\nfilter over these pixels. Remember, our objective here is to apply a grayscale filter over\nthe image. A grayscale filter is a filter that transforms a colored image into a grayscale image.\n\nThere are different formulas and strategies to transform a colored image into a grayscale image.\nBut all of these different strategies normally involve applying some math over the colors of each pixel.\nIn this project, we are going to use the most general formula, which is exposed below.\nThis formula considers $r$ as the red of the pixel, $g$ as the green, $b$ as the blue, and $p'$ as the\nlinear luminance of the pixel.\n\n$$\n p' = (0.2126 \\times r) + (0.7152 \\times g) + (0.0722 \\times b)\n$${#eq-grayscale}\n\nThis @eq-grayscale is the formula to calculate the linear luminance of a pixel. It's worth noting that this formula\nworks only for images whose pixels are using the sRGB color space, which is the standard color space\nfor the web. Thus, ideally, all images on the web should use this color space. Luckily,\nthis is our case here, i.e., the `pedro_pascal.png` image is using this sRGB color space, and, as consequence,\nwe can use the @eq-grayscale. You can read more about this formula at the Wikipedia page for grayscale [@wiki_grayscale].\n\nThe `apply_image_filter()` function exposed below summarises the necessary steps to\napply @eq-grayscale over the pixels in the image. We just apply this function\nover our buffer object that contains our pixel data, and, as result, the pixel\ndata stored in this buffer object should now represent the grayscale version of our image.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn apply_image_filter(buffer:[]u8) !void {\n const len = buffer.len;\n const red_factor: f16 = 0.2126;\n const green_factor: f16 = 0.7152;\n const blue_factor: f16 = 0.0722;\n var index: u64 = 0;\n while (index < len) : (index += 4) {\n const rf: f16 = @floatFromInt(buffer[index]);\n const gf: f16 = @floatFromInt(buffer[index + 1]);\n const bf: f16 = @floatFromInt(buffer[index + 2]);\n const y_linear: f16 = (\n (rf * red_factor) + (gf * green_factor)\n + (bf * blue_factor)\n );\n buffer[index] = @intFromFloat(y_linear);\n buffer[index + 1] = @intFromFloat(y_linear);\n buffer[index + 2] = @intFromFloat(y_linear);\n }\n}\n\ntry apply_image_filter(buffer[0..]);\n```\n:::\n\n\n\n\n## Saving the grayscale version of the image\n\nSince we have now the grayscale version of our image stored in our buffer object,\nwe need to encode this buffer object back into the \"PNG format\", and save the encoded data into\na new PNG file in our filesystem, so that we can access and see the grayscale version of our image\nthat was produced by our small program.\n\nTo do that, the `libspng` library help us once again by offering an \"encode data to PNG\" type of function,\nwhich is the `spng_encode_image()` function. But in order to \"encode data to PNG\" with `libspng`, we need\nto create a new context object. This new context object must use an \"encoder context\", which\nis identified by the enum value `SPNG_CTX_ENCODER`.\n\nThe `save_png()` function exposed below, summarises all the necessary steps to save the\ngrayscale version of our image into a new PNG file in the filesystem. By default, this\nfunction will save the grayscale image into a file named `pedro_pascal_filter.png` in the CWD.\n\nNotice in this code example that we are using the same image header object (`image_header`) that we have\ncollected previously with the `get_image_header()` function. Remember, this image header object\nis a C struct (`spng_ihdr`) that contains basic information about our PNG file, such as\nthe dimensions of the image, the color model used, etc.\n\nIf we wanted to save a very different image in this new PNG file, e.g. an image\nwith different dimensions, or, an image that uses a different color model, a different bit depth, etc.\nwe would have to create a new image header (`spng_ihdr`) object that describes the properties\nof this new image.\n\nBut we are essentially saving the same image that we have begin with here (the dimensions of\nthe image, the color model, etc. are all still the same). The only difference\nbetween the two images are the colors of the pixels, which are now \"shades of gray\".\nAs consequence, we can safely use the exact same image header data in this new PNG file.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn save_png(image_header: *c.spng_ihdr, buffer: []u8) !void {\n const path = \"pedro_pascal_filter.png\";\n const file_descriptor = c.fopen(path.ptr, \"wb\");\n if (file_descriptor == null) {\n return error.CouldNotOpenFile;\n }\n const ctx = (\n c.spng_ctx_new(c.SPNG_CTX_ENCODER)\n orelse unreachable\n );\n defer c.spng_ctx_free(ctx);\n _ = c.spng_set_png_file(ctx, @ptrCast(file_descriptor));\n _ = c.spng_set_ihdr(ctx, image_header);\n\n const encode_status = c.spng_encode_image(\n ctx,\n buffer.ptr,\n buffer.len,\n c.SPNG_FMT_PNG,\n c.SPNG_ENCODE_FINALIZE\n );\n if (encode_status != 0) {\n return error.CouldNotEncodeImage;\n }\n if (c.fclose(file_descriptor) != 0) {\n return error.CouldNotCloseFileDescriptor;\n }\n}\n\ntry save_png(&image_header, buffer[0..]);\n```\n:::\n\n\nAfter we execute this `save_png()` function, we should have a new PNG file\ninside our CWD, named `pedro_pascal_filter.png`. If we open this PNG file,\nwe will see the same image exposed in @fig-pascal-gray.\n\n\n## Building our project\n\nNow that we have written the code, let's discuss how can we build/compile this project.\nTo do that, I'm going to create a `build.zig` file in the root directory of our project,\nand start writing the necessary code to compile the project, using the knowledge\nthat we have acquired from @sec-build-system.\n\n\nWe first create the build target for our executable file, that executes our\nZig code. Let's suppose that all of our Zig code was written into a Zig module\nnamed `image_filter.zig`. The `exe` object exposed in the build script below\ndescribes the build target for our executable file.\n\nSince we have used some C code from the `libspng` library in our Zig code,\nwe need to link our Zig code (which is in the `exe` build target) to both\nthe C Standard Library, and, to the `libspng` library. We do that, by calling\nthe `linkLibC()` and `linkSystemLibrary()` methods from our `exe` build target.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\npub fn build(b: *std.Build) void {\n const target = b.standardTargetOptions(.{});\n const optimize = b.standardOptimizeOption(.{});\n const exe = b.addExecutable(.{\n .name = \"image_filter\",\n .root_source_file = b.path(\"src/image_filter.zig\"),\n .target = target,\n .optimize = optimize,\n });\n exe.linkLibC();\n // Link to libspng library:\n exe.linkSystemLibrary(\"spng\");\n b.installArtifact(exe);\n}\n```\n:::\n\n\nSince we are using the `linkSystemLibrary()` method, it means that the library\nfiles for `libspng` are searched in your system to be linked with the `exe` build target.\nIf you have not yet built and installed the `libspng` library into your system, this\nlinkage step will likely not work. Because it will not find the library files in your system.\n\nSo, just remember to install `libspng` in your system, if you want to build this project.\nHaving this build script above written, we can finally build our project by\nrunning the `zig build` command in the terminal.\n\n```bash\nzig build\n```\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/14-threads/execute-results/epub.json b/_freeze/Chapters/14-threads/execute-results/epub.json deleted file mode 100644 index 430a96bc..00000000 --- a/_freeze/Chapters/14-threads/execute-results/epub.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "hash": "5330e6bae2255d3ad46893b0641f0683", - "result": { - "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n# Introducing threads and parallelism in Zig {#sec-thread}\n\nThreads are available in Zig through the `Thread` struct from the Zig Standard Library.\nThis struct represents a kernel thread, and it follows a POSIX Thread pattern,\nmeaning that, it works similarly to a thread from the `pthread` C library, which is usually available on any distribution\nof the GNU C Compiler (`gcc`). If you are not familiar with threads, I will give you some theory behind it first, shall we?\n\n\n## What are threads? {#sec-what-thread}\n\nA thread is basically a separate context of execution.\nWe use threads to introduce parallelism into our program,\nwhich in most cases, makes the program run faster, because we have multiple tasks\nbeing performed at the same time, parallel to each other.\n\nPrograms are normally single-threaded by default. Which means that each program\nusually runs on a single thread, or, a single context of execution. When we have only one thread running, we have no\nparallelism. And when we don't have parallelism, the commands are executed sequentially, that is,\nonly one command is executed at a time, one after another. By creating multiple threads inside our program,\nwe start to execute multiple commands at the same time.\n\nPrograms that create multiple threads are very common in the wild. Because many different types\nof applications are well suited for parallelism. Good examples are video and photo-editing applications\n(e.g. Adobe Photoshop or DaVinci Resolve), games (e.g. The Witcher 3), and also web browsers\n(e.g. Google Chrome, Firefox, Microsoft Edge, etc).\nFor example, in web browsers, threads are normally used to implement tabs.\nThe tabs in a web browsers usually run as separate threads in the main process of\nthe web browser. That is, each new tab that you open in your web browser\nusually runs on a separate thread of execution.\n\nBy running each tab in a separate thread, we allow all open tabs in the browser to run at the same time,\nand independently from each other. For example, you might have YouTube or Spotify currently open in\na tab, and you are listening to some podcast in that tab while at the same time\nworking in another tab, writing an essay on Google Docs. Even if you are not looking\ninto the YouTube tab, you can still hear the podcast only because this YouTube tab is running in parallel\nwith the other tab where Google Docs is running.\n\nWithout threads, the other alternative would be to run each tab as a completely separate\nprocess in your computer. But that would be a bad choice because just a few tabs would already consume\ntoo much power and resources from your computer. In other words, it's very expensive to create a completely new process,\ncompared to creating a new thread of execution. Also, the chances of you experiencing lag and overhead\nwhile using the browser would be significant. Threads are faster to create, and they also consume\nmuch, much less resources from the computer, especially because they share some resources\nwith the main process.\n\nTherefore, it's the use of threads in modern web browsers that allow you to hear the podcast\nat the same time while you are writing something on Google Docs.\nWithout threads, a web browser would probably be limited to just one single tab.\n\nThreads are also well-suited for anything that involves serving requests or orders.\nBecause serving a request takes time, and usually involves a lot of \"waiting time\".\nIn other words, we spend a lot of time in idle, waiting for something to complete.\nFor example, consider a restaurant. Serving orders in a restaurant usually involves\nthe following steps:\n\n1. receive order from the client.\n1. pass the order to the kitchen, and wait for the food to be cooked.\n1. start cooking the food in the kitchen.\n1. when the food is fully cooked deliver this food to the client.\n\nIf you think about the bullet points above, you will notice that one big moment of waiting time\nis present in this whole process, which is while the food is being cooked\ninside the kitchen. While the food is being prepped, both the waiter and the client\nthemselves are waiting for the food to be ready and delivered.\n\nIf we write a program to represent this restaurant, more specifically, a single-threaded program, then\nthis program would be very inefficient. Because the program would stay in idle, waiting for a considerable amount\nof time on the \"check if food is ready\" step. Consider the code snippet exposed below that could\npotentially represent such program.\n\nThe problem with this program is the while loop. This program will spend a lot of time\nwaiting on the while loop, doing nothing more than just checking if the food is ready.\nThis is a waste of time. Instead of waiting for something to happen, the waiter\ncould just send the order to the kitchen, and just move on, and continue with receiving\nmore orders from other clients, and sending more orders to the kitchen, instead\nof doing nothing and waiting for the food to be ready.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst order = Order.init(\"Pizza Margherita\", n = 1);\nconst waiter = Waiter.init();\nwaiter.receive_order(order);\nwaiter.ask_kitchen_to_cook();\nvar food_not_ready = true;\nwhile (food_not_ready) {\n food_not_ready = waiter.is_food_ready();\n}\nconst food = waiter.get_food_from_kitchen();\nwaiter.send_food_to_client(food);\n```\n:::\n\n\n\nThis is why threads would be a great fit for this program. We could use threads\nto free the waiters from their \"waiting duties\", so they can go on with their\nother tasks, and receive more orders. Take a look at the next example, where I have re-written the above\nprogram into a different program that uses threads to cook and deliver the orders.\n\nYou can see in this program that when a waiter receives a new order\nfrom a client, this waiter executes the `send_order()` function.\nThe only thing that this function does is to create a new thread\nand detaches it. Since creating a thread is a very fast operation,\nthis `send_order()` function returns almost immediately,\nso the waiter spends almost no time worrying about the order, and just\nmove on and tries to get the next order from the clients.\n\nInside the new thread created, the order gets cooked by a chef, and when the\nfood is ready, it's delivered to the client's table.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn cook_and_deliver_order(order: *Order) void {\n const chef = Chef.init();\n const food = chef.cook(order.*);\n chef.deliver_food(food);\n}\nfn send_order(order: Order) void {\n const cook_thread = Thread.spawn(\n .{}, cook_and_deliver_order, .{&order}\n );\n cook_thread.detach();\n}\n\nconst waiter = Waiter.init();\nwhile (true) {\n const order = waiter.get_new_order();\n if (order) {\n send_order(order);\n }\n}\n```\n:::\n\n\n\n\n\n## Threads versus processes\n\nWhen we run a program, this program is executed as a *process* in the operating system.\nThis is a one to one relationship, each program or application that you execute\nis a separate process in the operating system. But each program, or each process,\ncan create and contain multiple threads inside of it. Therefore,\nprocesses and threads have a one to many relationship.\n\nThis also means that every thread that we create is always associated with a particular process in our computer.\nIn other words, a thread is always a subset (or a children) of an existing process.\nAll threads share some of the resources associated with the process from which they were created.\nAnd because threads share resources with the process, they are very good for making communication\nbetween tasks easier.\n\nFor example, suppose that you were developing a big and complex application\nthat would be much simpler if you could split it in two, and make these two separate pieces talk\nwith each other. Some programmers opt to effectively write these two pieces of the codebase as two\ncompletely separate programs, and then, they use IPC (*inter-process communication*) to make these\ntwo separate programs/processes talk to each other, and make them work together.\n\nHowever, some programmers find IPC hard to deal with, and, as consequence,\nthey prefer to write one piece of the codebase as the \"main part of the program\",\nor, as the part of the code that runs as the process in the operating system,\nwhile the other piece of the codebase is written as a task to be executed in\na new thread. A process and a thread can easily comunicate with each other\nthrough both control flow, and also, through data, because they share and have\naccess to the same standard file descriptors (`stdout`, `stdin`, `stderr`), and also to the\nsame memory space on the heap and global data section.\n\n\nIn more details, each thread that you create have a separate stack frame reserved just for that thread,\nwhich essentially means that each local object that you create inside this thread, is local to that\nthread, i.e., the other threads cannot see this local object. Unless this object that you have created\nis an object that lives on the heap. In other words, if the memory associated with this object\nis on the heap, then, the other threads can potentially access this object.\n\nTherefore, objects that are stored in the stack are local to the thread where they were created.\nBut objects that are stored on the heap are potentially accessible to other threads. All of this means that,\neach thread has its own separate stack frame, but, at the same time, all threads share\nthe same heap, the same standard file descriptors (which means that they share the same `stdout`, `stdin`, `stderr`),\nand the same global data section in the program.\n\n\n\n## Creating a thread\n\nWe create new threads in Zig by first importing the `Thread` struct into\nour current Zig module and then calling the `spawn()` method of this struct,\nwhich creates (or \"spawns\") a new thread of execution from our current process.\nThis method has three arguments, which are, respectively:\n\n1. a `SpawnConfig` object, which contains configurations for the spawn process.\n1. the name of the function that is going to be executed (or that is going to be \"called\") inside this new thread.\n1. a list of arguments (or inputs) to be passed to the function provided in the second argument.\n\nWith these three arguments, you can control how the thread gets created, and also, specify which\nwork (or \"tasks\") will be performed inside this new thread. A thread is just a separate context of execution,\nand we usually create new threads in our code because we want to perform some work inside this\nnew context of execution. And we specify which exact work, or which exact steps that are going to be\nperformed inside this context by providing the name of a function as the second argument of the `spawn()` method.\n\nThus, when this new thread gets created, this function that you provided as input to the `spawn()`\nmethod gets called, or gets executed inside this new thread. You can control the\narguments, or the inputs that are passed to this function when it gets called by providing\na list of arguments (or a list of inputs) in the third argument of the `spawn()` method.\nThese arguments are passed to the function in the same order that they are\nprovided to `spawn()`.\n\nFurthermore, the `SpawnConfig` is a struct object with only two possible fields, or, two possible members, that you\ncan set to tailor the spawn behaviour. These fields are:\n\n- `stack_size`: you can provide a `usize` value to specify the size (in bytes) of the thread's stack frame. By default, this value is: $16 \\times 1024 \\times 1024$.\n- `allocator`: you can provide an allocator object to be used when allocating memory for the thread.\n\nTo use one of these two fields (or \"configs\"), you just have to create a new object of type `SpawnConfig`,\nand provide this object as input to the `spawn()` method. But, if you are not interested in using\none of these configs, and you are ok with using just the defaults, you can just provide an anonymous\nstruct literal (`.{}`) in place of this `SpawnConfig` argument.\n\nAs our first, and very simple example, consider the code exposed below.\nInside the same program, you can create multiple threads of execution if you want to.\nBut, in this first example, we are creating just a single thread of execution, because\nwe call `spawn()` only once.\n\nAlso, notice in this example that we are executing the function `do_some_work()`\ninside the new thread. Since this function receives no inputs, because it has\nno arguments, we have passed an empty list in this instance, or more precisely,\nan empty, anonymous struct (`.{}`) in the third argument of `spawn()`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Thread = std.Thread;\nfn do_some_work() !void {\n _ = try stdout.write(\"Starting the work.\\n\");\n std.time.sleep(100 * std.time.ns_per_ms);\n _ = try stdout.write(\"Finishing the work.\\n\");\n}\n\npub fn main() !void {\n const thread = try Thread.spawn(.{}, do_some_work, .{});\n thread.join();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nStarting the work.Finishing the work.\n```\n\n\n:::\n:::\n\n\n\nNotice the use of `try` when calling the `spawn()` method. This means\nthat this method can return an error in some circumstances. One circumstance\nin particular is when you attempt to create a new thread, when you have already\ncreated too much (i.e., you have exceeded the quota of concurrent threads in your system).\n\nBut, if the new thread is successfully created, the `spawn()` method returns a handler\nobject (which is just an object of type `Thread`) to this new thread. You can use\nthis handler object to effectively control all aspects of the thread.\n\nWhen the thread gets created, the function that you provided as input to `spawn()`\ngets invoked (i.e., gets called) to start the execution on this new thread.\nIn other words, every time you call `spawn()`, not only is a new thread created,\nbut the \"start work button\" of this thread is also automatically pressed.\nSo the work being performed in this thread starts as soon as the thread is created.\nThis is similar to how `pthread_create()` from the `pthreads` library in C works,\nwhich also starts the execution as soon as the thread is created.\n\n\n## Returning from a thread\n\nWe have learned in the previous section that the execution of the thread starts as soon as\nthe thread is created. Now, we will learn how to \"join\" or \"detach\" a thread in Zig.\n\"Join\" and \"detach\" are operations that control how the thread returns to\nthe main thread, or to the main process in our program.\n\nWe perform these operations by using the methods `join()` and `detach()` from the thread handler object.\nEvery thread that you create can be marked as either *joinable* or *detached* [@linux_pthread_create].\nYou can turn a thread into a *detached* thread by calling the `detach()` method\nfrom the thread handler object. But if you call the `join()` method instead, then this thread\nbecomes a *joinable* thread.\n\nA thread cannot be both *joinable* and *detached*. Which in general means\nthat you cannot call both `join()` and `detach()` on the same thread.\nBut a thread must be one of the two, meaning that, you should always call\neither `join()` or `detach()` over a thread. If you don't call\none of these two methods over your thread, you introduce undefined behaviour into your program,\nwhich is described in @sec-not-call-join-detach.\n\nNow, let's describe what each of these two methods do to your thread.\n\n\n### Joining a thread\n\nWhen you join a thread, you are essentially saying: \"Hey! Could you please wait for the thread to finish,\nbefore you continue with your execution?\". For example, if we come back to our first and simplest example\nof a thread in Zig, we created a single thread inside the `main()` function of our program\nand just called `join()` on this thread at the end. This section of the code example is reproduced below.\n\nBecause we are joining this new thread inside the `main()`'s scope, it means that the\nexecution of the `main()` function is temporarily stopped, to wait for the execution of the thread\nto finish. That is, the execution of `main()` stops temporarily at the line where `join()` gets called,\nand it will continue only after the thread has finished its tasks.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn main() !void {\n const thread = try Thread.spawn(.{}, do_some_work, .{});\n thread.join();\n}\n```\n:::\n\n\n\nBecause we have joined this new thread inside the `main()` scope, we have a\nguarantee that this new thread will finish before the end of the execution of `main()`.\nBecause it's guaranteed that `main()` will wait for the thread to finish its tasks.\n\nIn the example above, there are no more expressions after the `join()` call. We just have the end\nof the `main()`'s scope, and, therefore, the execution of our program just ends after the thread finishes its tasks,\nsince there is nothing more to do. But what if we had more stuff to do after the join call?\n\nTo demonstrate this other possibility, consider the next example exposed\nbelow. Here, we create a `print_id()` function, that just receives an id\nas input, and prints it to `stdout`. In this example, we are creating two\nnew threads, one after another. Then, we join the first thread, then,\nwe wait for two whole seconds, then, at last, we join the second thread.\n\nThe idea behind this example is that the last `join()` call is executed\nonly after the first thread finishes its task (i.e., the first `join()` call),\nand the two-second delay. If you compile and run this\nexample, you will notice that most messages are quickly printed to `stdout`,\ni.e., they appear almost instantly on your screen.\nHowever, the last message (\"Joining thread 2\") takes around 2 seconds to appear\non the screen.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_id(id: *const u8) !void {\n try stdout.print(\"Thread ID: {d}\\n\", .{id.*});\n}\n\npub fn main() !void {\n const id1: u8 = 1;\n const id2: u8 = 2;\n const thread1 = try Thread.spawn(.{}, print_id, .{&id1});\n const thread2 = try Thread.spawn(.{}, print_id, .{&id2});\n\n _ = try stdout.write(\"Joining thread 1\\n\");\n thread1.join();\n std.time.sleep(2 * std.time.ns_per_s);\n _ = try stdout.write(\"Joining thread 2\\n\");\n thread2.join();\n}\n```\n:::\n\n\n\n```\nThread ID: Joining thread 1\n1\nThread ID: 2\nJoining thread 2\n```\n\nThis demonstrates that both threads finish their work (i.e., printing the IDs)\nvery fast, before the two seconds of delay end. Because of that, the last `join()` call\nreturns pretty much instantly. Because when this last `join()` call happens, the second\nthread has already finished its task.\n\nNow, if you compile and run this example, you will also notice that, in some cases,\nthe messages intertwine with each other. In other words, you might see\nthe message \"Joining thread 1\" inserted in the middle of the message \"Thread 1\",\nor vice-versa. This happens because:\n\n- the threads are executing basically at the same time as the main process of the program (i.e., the `main()` function).\n- the threads share the same `stdout` from the main process of the program, which means that the messages that the threads produce are sent to exact same place as the messages produced by the main process.\n\nBoth of these points were described previously in @sec-what-thread.\nSo the messages might get intertwined because they are being produced and\nsent to the same `stdout` roughly at the same time.\nAnyway, when you call `join()` over a thread, the current process will wait\nfor the thread to finish before it continues, and, when the thread finishes its\ntask, the resources associated with this thread are automatically freed, and\nthe current process continues with its execution.\n\n\n### Detaching a thread\n\nWhen you detach a thread, the resources associated with this thread are automatically\nreleased back to the system, without the need for another thread to join with this terminated thread.\n\nIn other words, when you call `detach()` on a thread it's like when your children become adults,\ni.e., they become independent from you. A detached thread frees itself, and when this thread finishes its\ntasks, it does not report the results back to you. Thus, you normally mark a thread as *detached*\nwhen you don't need to use the return value of the thread, or when you don't care about\nwhen exactly the thread finishes its job, i.e., the thread solves everything by itself.\n\nTake the code example below. We create a new thread, detach it, and then, we just\nprint a final message before we end our program. We use the same `print_id()`\nfunction that we have used over the previous examples.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_id(id: *const u8) !void {\n try stdout.print(\"Thread ID: {d}\\n\", .{id.*});\n}\n\npub fn main() !void {\n const id1: u8 = 1;\n const thread1 = try Thread.spawn(.{}, print_id, .{&id1});\n thread1.detach();\n _ = try stdout.write(\"Finish main\\n\");\n}\n```\n:::\n\n\n\n```\nFinish main\n```\n\nNow, if you look closely at the output of this code example, you will notice\nthat only the final message in main was printed to the console. The message\nthat was supposed to be printed by `print_id()` did not appear in the console.\nWhy? It's because the main process of our program has finished first,\nbefore the thread was able to say anything.\n\nAnd that is perfectly ok behaviour, because the thread was detached, so it was\nable to free itself, without the need to wait for the main process.\nIf you ask main to sleep (or \"wait\") for some extra nanoseconds, before it ends, you will likely\nsee the message printed by `print_id()`, because you give enough time for the thread to\nfinish before the main process ends.\n\n\n## Thread pools\n\nThread pools is a very popular programming pattern, which is used especially on servers and daemons processes.\nA thread pool is just a set of threads, or a \"pool\" of threads. Many programmers like to use this pattern because it makes\nit easier to manage and use multiple threads in your program, instead of manually creating the threads when you need them.\n\nAlso, using thread pools might increase performance as well in your program,\nespecially if your program is constantly creating threads to perform short-lived tasks.\nIn such instance, a thread pool might cause an increase in performance because you do not have be constantly\ncreating and destroying threads all the time, so you don't face a lot of the overhead involved\nin this constant process of creating and destroying threads.\n\nThe main idea behind a thread pool is to have a set of threads already created and ready to perform\ntasks at all times. You create a set of threads at the moment that your program starts, and keep\nthese threads alive while your program runs. Each of these threads will be either performing a task, or\nwaiting for a task to be assigned.\nEvery time a new task emerges in your program, this task is added to a \"queue of tasks\",\nand the moment that a thread becomes available and ready to perform a new task,\nthis thread takes the next task from the \"queue of tasks\", and it simply performs the task.\n\nThe Zig Standard Library offers a thread pool implementation on the `std.Thread.Pool` struct.\nYou create a new instance of a `Pool` object by providing a `Pool.Options` object\nas input to the `init()` method of this struct. A `Pool.Options` object, is a struct object that contains\nconfigurations for the pool of threads. The most important settings in this struct object are\nthe members `n_jobs` and `allocator`. As the name suggests, the member `allocator` should receive an allocator object,\nwhile the member `n_jobs` specifies the number of threads to be created and maintained in this pool.\n\nConsider the example exposed below, that demonstrates how can we create a new thread pool object.\nHere, we create a `Pool.Options` object that contains\na general purpose allocator object, and also, the `n_jobs` member was set to 4, which\nmeans that the thread pool will create and use 4 threads.\n\nAlso notice that the `pool` object was initially set to `undefined`. This allow us\nto initially declare the thread pool object, but not properly instantiate the\nunderlying memory of the object. You have to initially declare your thread pool object\nby using `undefined` like this, because the `init()` method of `Pool` needs\nto have an initial pointer to properly instantiate the object.\n\nSo, just remember to create your thread pool object by using `undefined`, and then,\nafter that, you call the `init()` method over the object.\nYou should also not forget to call the `deinit()` method over the thread pool\nobject, once you are done with it, to release the resources allocated for the thread pool. Otherwise, you will\nhave a memory leak in your program.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Pool = std.Thread.Pool;\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const opt = Pool.Options{\n .n_jobs = 4,\n .allocator = allocator,\n };\n var pool: Pool = undefined;\n try pool.init(opt);\n defer pool.deinit();\n}\n```\n:::\n\n\n\nNow that we know how to create `Pool` objects, we have\nto understand how to assign tasks to be executed by the threads in this pool object.\nTo assign a task to be performed by a thread, we need to call the `spawn()` method\nfrom the thread pool object.\n\nThis `spawn()` method works identical to the `spawn()` method from the\n`Thread` object. The method has almost the same arguments as the previous one,\nmore precisely, we don't have to provide a `SpawnConfig` object in this case.\nBut instead of creating a new thread, this `spawn()` method from\nthe thread pool object just registers a new task in the internal \"queue of tasks\" to be performed,\nand any available thread in the pool will get this task, and it will simply perform the task.\n\nIn the example below, we are using our previous `print_id()` function once again.\nBut you may notice that the `print_id()` function is a little different this time,\nbecause now we are using `catch` instead of `try` in the `print()` call.\nCurrently, the `Pool` struct only supports functions that don't return errors\nas tasks. Thus, when assigning tasks to threads in a thread pool, it is essential to use functions\nthat don't return errors. That is why we are using `catch` here, so that the\n`print_id()` function don't return an error.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_id(id: *const u8) void {\n _ = stdout.print(\"Thread ID: {d}\\n\", .{id.*})\n catch void;\n}\nconst id1: u8 = 1;\nconst id2: u8 = 2;\ntry pool.spawn(print_id, .{&id1});\ntry pool.spawn(print_id, .{&id2});\n```\n:::\n\n\n\nThis limitation should probably not exist, and, in fact, it's already on the radar of the\nZig team to fix this issue, and it's being tracked in an [open issue](https://github.com/ziglang/zig/issues/18810)[^issue].\nSo, if you do need to provide a function that might return an error as the task\nto be performed by the threads in the thread pool, then, you are either limited to:\n\n- implementing your own thread pool that does not have this limitation.\n- wait for the Zig team to actually fix this issue.\n\n[^issue]: \n\n\n\n\n## Mutexes\n\nMutexes are a classic component of every thread library. In essence, a mutex is a *Mutually Exclusive Flag*, and this flag\nacts like a type of \"lock\", or as a gate keeper to a particular section of your code. Mutexes are related to thread synchronization,\nmore specifically, they prevent you from having some classic race conditions in your program,\nand, therefore, major bugs and undefined behaviour that are usually difficult to track and understand.\n\nThe main idea behind a mutex is to help us to control the execution of a particular section of the code, and to\nprevent two or more threads from executing this particular section of the code at the same time.\nMany programmers like to compare a mutex to a bathroom door (which typically has a lock).\nWhen a thread locks its own mutex object, it's like if the bathroom door was locked.\nTherefore, other people (in this case, other threads) who want to use the same bathroom at the same time\nmust be patient and simply wait for the current occupant (or thread) to unlock the door and get out of the bathroom.\n\nSome other programmers also like to explain mutexes by using the analogy of \"each person will have their turn to speak\".\nThis is the analogy used in the [*Multithreading Code* video from the Computerphile project](https://www.youtube.com/watch?v=7ENFeb-J75k&ab_channel=Computerphile)[^computerphile].\nImagine if you are in a conversation circle. There is a moderator in this circle, which is the person that decides who\nhas the right to speak at that particular moment. The moderator gives a green card (or some sort of an authorization card) to the person that\nis going to speak, and, as a result, everyone else must be silent and hear this person that has the green card.\nWhen the person finishes talking, they give the green card back to the moderator, and the moderator decides\nwho is going to talk next, and delivers the green card to that person. And the cycle goes on like this.\n\n[^computerphile]: \n\n\nA mutex acts like the moderator in this conversation circle. The mutex authorizes one single thread to execute a specific section of the code,\nand it also blocks the other threads from executing this same section of the code. If these other threads want to execute this same\npiece of the code, they are forced to wait for the the authorized thread to finish first.\nWhen the authorized thread finishes executing this code, the mutex authorizes the next thread to execute this code,\nwhile the remaining threads remain blocked. Therefore, a mutex is like a moderator that does a \"each\nthread will have their turn to execute this section of the code\" type of control.\n\n\nMutexes are especially used to prevent data race problems from happening. A data race problem happens when two or more threads\nare trying to read from or write to the same shared object at the same time.\nSo, when you have an object that is shared will all threads, and, you want to avoid two or more threads from\naccessing this same object at the same time, you can use a mutex to lock the part of the code that access this specific object.\nWhen a thread tries to run this code that is locked by a mutex, this thread stops its execution,\nand patiently waits for this section of the codebase to be unlocked to continue.\n\nNotice that mutexes are normally used to lock areas of the codebase that access/modify data that is **shared** with all threads,\ni.e., objects that are either stored in the global data section, or in the heap space of your program.\nSo mutexes are not normally used on areas of the codebase that access/modify objects that are local to the thread.\n\n\n\n### Critical section {#sec-critical-section}\n\nCritical section is a concept commonly associated with mutexes and thread synchronization.\nIn essence, a critical section is the section of the program that a thread access/modify a shared resource\n(i.e., an object, a file descriptor, something that all threads have access to). In other words,\na critical section is the section of the program where race conditions might happen, and, therefore,\nwhere undefined behaviour can be introduced into the program.\n\nWhen we use mutexes in our program, the critical section defines the area of the codebase that we want to lock.\nSo we normally lock the mutex object at the beginning of the critical section,\nand then, we unlock it at the end of the critical section.\nThe two bullet points exposed below comes from the \"Critical Section\" article from GeekFromGeeks,\nand they summarise well the role that a critical section plays in the thread synchronization problem [@geeks_critical_section].\n\n\n1. The critical section must be executed as an atomic operation, which means that once one thread or process has entered the critical section, all other threads or processes must wait until the executing thread or process exits the critical section. The purpose of synchronization mechanisms is to ensure that only one thread or process can execute the critical section at a time.\n1. The concept of a critical section is central to synchronization in computer systems, as it is necessary to ensure that multiple threads or processes can execute concurrently without interfering with each other. Various synchronization mechanisms such as semaphores, mutexes, monitors, and condition variables are used to implement critical sections and ensure that shared resources are accessed in a mutually exclusive manner.\n\n\n### Atomic operations {#sec-atomic-operation}\n\nYou will also see the term \"atomic operation\" a lot when reading about threads, race conditions and mutexes.\nIn summary, an operation is categorized as \"atomic\" when a context switch cannot occur in\nthe middle of the operation. In other words, this operation is always done from beginning to end, without interruptions\nof another process or operation in the middle of its execution phase.\n\nNot many operations today are atomic. But why do atomic operations matter here? It's because data races\n(which is a type of a race condition) cannot happen on operations that are atomic.\nSo if a particular line in your code performs an atomic operation, then this line will never\nsuffer from a data race problem. Therefore, programmers sometimes use an atomic operation\nto protect themselves from data race problems in their code.\n\nWhen you have an operation that is compiled into just one single assembly instruction, this operation might be atomic,\nbecause it's just one assembly instruction. But this is not guaranteed. This is usually true for old CPU architectures\n(such as `x86`). But nowadays, most assembly instructions in modern CPU architectures are broken down into multiple micro-tasks,\nwhich inherently makes the operation non-atomic, even if it consists of a single assembly instruction.\n\nThe Zig Standard Library offers some atomic functionality in the `std.atomic` module.\nIn this module, you will find a public and generic function called `Value()`. With this function we create an \"atomic object\", which is\na value that contains some native atomic operations, most notably, a `load()` and a `fetchAdd()` operation.\nIf you have experience with multithreading in C++, you probably have recognized this pattern. So yes, this generic\n\"atomic object\" in Zig is essentially identical to the template struct `std::atomic` from the C++ Standard Library.\nIt's important to emphasize that only primitive data types (i.e., the types presented in @sec-primitive-data-types)\nare supported by these atomic operations in Zig.\n\n\n\n\n\n### Data races and race conditions\n\nTo understand why mutexes are used, we need to understand better the problem that they seek\nto solve, which can be summarized into data race problems. A data race problem is a type of a race condition,\nwhich happens when one thread is accessing a particular memory location (i.e., a particular shared object) at the same\ntime that another thread is trying to write/save new data into this same memory location (i.e., the same shared object).\n\nWe can simply define a race condition as any type of bug in your program that is based\non a \"who gets there first\" problem. A data race problem is a type of a race condition, because it occurs when two or more parties\nare trying to read and write into the same memory location at the same time, and, therefore, the end result of this operation\ndepends completely on who gets to this memory location first.\nAs a consequence, a program that has a data race problem will likely produce a different result each time that we execute it.\n\nThus, race conditions produce undefined behaviour and unpredictability because the program produces\na different answer each time a different person gets to the target location before the others.\nAnd, we have no easy way to either predict or control who is getting to this target location first.\nIn other words, each time your program runs, you may get a different answer because a different person,\nfunction, or part of the code finishes its tasks before the others.\n\nAs an example, consider the code snippet exposed below. In this example, we create a global counter\nvariable, and we also create an `increment()` function, whose job is to just increment this global counter\nvariable in a for loop.\n\nSince the for loop iterates 1 hundred thousand times, and, we create two separate threads\nin this code example, what number do you expect to see in the final message printed to `stdout`?\nThe answer should be 2 hundred thousand. Right? Well, in theory, this program was supposed\nto print 2 hundred thousand at the end, but in practice, every time that I execute this program\nI get a different answer.\n\nIn the example exposed below, you can see that this time the end\nresult was 117254, instead of the expected 200000. The second time I executed this program,\nI got the number 108592 as the result. So the end result of this program is varying, but it never gets\nto the expected 200000 that we want.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// Global counter variable\nvar counter: usize = 0;\n// Function to increment the counter\nfn increment() void {\n for (0..100000) |_| {\n counter += 1;\n }\n}\n\npub fn main() !void {\n const thr1 = try Thread.spawn(.{}, increment, .{});\n const thr2 = try Thread.spawn(.{}, increment, .{});\n thr1.join();\n thr2.join();\n try stdout.print(\"Couter value: {d}\\n\", .{counter});\n}\n```\n:::\n\n\n\n```\nCouter value: 117254\n```\n\n\nWhy this is happening? The answer is: because this program contains a data race problem.\nThis program would print the correct number 200000 if and only if the first thread finishes\nits tasks before the second thread starts to execute. But that is very unlikely to happen.\nBecause the process of creating the thread is too fast, and therefore, both threads start to execute roughly\nat the same time. If you change this code to add some nanoseconds of sleep between the first and the second calls to `spawn()`,\nyou will increase the chances of the program producing the \"correct result\".\n\nSo the data race problem happens because both threads are reading and writing to the same\nmemory location at roughly the same time. In this example, each thread is essentially performing\nthree basic operations at each iteration of the for loop, which are:\n\n1. reading the current value of `count`.\n1. incrementing this value by 1.\n1. writing the result back into `count`.\n\nIdeally, a thread B should read the value of `count`, only after the other thread A has finished\nwriting the incremented value back into the `count` object. Therefore, in the ideal scenario, which is demonstrated\nin @tbl-data-race-ideal, the threads should work in sync with each other. But the reality is that these\nthreads are out of sync, and because of that, they suffer from a data race problem, which is demonstrated\nin @tbl-data-race-not.\n\nNotice that, in the data race scenario (@tbl-data-race-not), the read performed by a thread B happens\nbefore the write operation of thread A, and that ultimately leads to wrong results at the end of the program.\nBecause when thread B reads the value of the `count` variable, thread A is still processing\nthe initial value from `count`, and has not yet written the new, incremented value back to `count`. As a result,\nthread B ends up reading the same initial (or \"old\") value from `count` instead of\nthe updated, incremented value that thread A would have written.\n\n\n::: {#tbl-data-race-ideal}\n\n| Thread 1 | Thread 2 | Integer value |\n|-------------|-------------|---------------|\n| read value | | 0 |\n| increment | | 1 |\n| write value | | 1 |\n| | read value | 1 |\n| | increment | 2 |\n| | write value | 2 |\n\n: An ideal scenario for two threads incrementing the same integer value\n:::\n\n::: {#tbl-data-race-not}\n\n| Thread 1 | Thread 2 | Integer value |\n|-------------|-------------|---------------|\n| read value | | 0 |\n| | read value | 0 |\n| increment | | 1 |\n| | increment | 1 |\n| write value | | 1 |\n| | write value | 1 |\n\n: A data race scenario when two threads are incrementing the same integer value\n:::\n\n\nIf you think about these diagrams exposed in form of tables, you will notice that they relate back to our discussion of atomic operations\nin @sec-atomic-operation. Remember, atomic operations are operations that the CPU executes\nfrom beginning to end, without interruptions from other threads or processes. So,\nthe scenario exposed in @tbl-data-race-ideal does not suffer from a data race, because\nthe operations performed by thread A are not interrupted in the middle by the operations\nfrom thread B.\n\nIf we also think about the discussion of critical section from @sec-critical-section, we can identify\nthe section that representes the critical section of the program, which is the section that is vulnerable\nto data race conditions. In this example, the critical section of the program is the line where we increment\nthe `counter` variable (`counter += 1`). So, ideally, we want to use a mutex, and lock right before this line, and then\nunlock right after this line.\n\n\n\n\n### Using mutexes in Zig\n\nNow that we know the problem that mutexes seek to solve, we can learn how to use them in Zig.\nMutexes in Zig are available through the `std.Thread.Mutex` struct from the Zig Standard Library.\nIf we take the same code from the previous example, and improve it with mutexes, to solve\nour data race problem, we get the code example below.\n\nNotice that this time, we had to alter the `increment()` function to receive a pointer to\nthe `Mutex` object as input. All that we need to do, to make this program safe against\ndata race problems, is to call the `lock()` method at the beginning of\nthe critical section, and then, call `unlock()` at the end of the critical section.\nNotice that the output of this program is now the correct number of 200000.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Thread = std.Thread;\nconst Mutex = std.Thread.Mutex;\nvar counter: usize = 0;\nfn increment(mutex: *Mutex) void {\n for (0..100000) |_| {\n mutex.lock();\n counter += 1;\n mutex.unlock();\n }\n}\n\npub fn main() !void {\n var mutex: Mutex = .{};\n const thr1 = try Thread.spawn(.{}, increment, .{&mutex});\n const thr2 = try Thread.spawn(.{}, increment, .{&mutex});\n thr1.join();\n thr2.join();\n try stdout.print(\"Couter value: {d}\\n\", .{counter});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nCouter value: 200000\n```\n\n\n:::\n:::\n\n\n\n\n\n\n## Read/Write locks\n\nMutexes are normally used when it's not always safe for two or more threads running the same\npiece of code at the same time. In contrast, read/write locks are normally used in situations\nwhere you have a mixture of scenarios, i.e., there are some pieces of the codebase that are safe\nto run in parallel, and other pieces that are not safe.\n\nFor example, suppose that you have multiple threads that uses the same shared file in the filesystem to store some configurations, or\nstatistics. If two or more threads try to read the data from this same file at the same time, nothing bad happens.\nSo this part of the codebase is perfectly safe to be executed in parallel, with multiple threads reading the same file at the same time.\n\nHowever, if two or more threads try to write data into this same file at the same time, then we cause some race condition\nproblems. So this other part of the codebase is not safe to be executed in parallel.\nMore specifically, a thread might end up writing data in the middle of the data written by the other thread.\nThis process of two or more threads writing to the same location might lead to data corruption.\nThis specific situation is usually called a *torn write*.\n\nThus, what we can extract from this example is that there are certain types of operations that cause\na race condition, but there are also other types of operations that do not cause a race condition problem.\nYou could also say that there are types of operations that are susceptible to race condition problems,\nand there are other types of operations that are not.\n\nA read/write lock is a type of lock that acknowledges the existence of this specific scenario, and you can\nuse this type of lock to control which parts of the codebase are safe to run in parallel and which parts are not.\n\n\n\n### Exclusive lock vs shared lock\n\nTherefore, a read/write lock is a little different from a mutex. Because a mutex is always an *exclusive lock*, meaning that, only\none thread is allowed to execute at all times. With an exclusive lock, the other threads are always \"excluded\",\ni.e., they are always blocked from executing. But in a read/write lock, the other threads might be authorized\nto run at the same time, depending on the type of lock that they acquire.\n\nWe have two types of locks in a read/write lock, which are: an exclusive lock and a shared lock. An exclusive lock works exactly the same\nas a mutex, while a shared lock is a lock that does not block the other threads from running at the same time.\nIn the `pthreads` C library, read/write locks are available through the `pthread_rwlock_t` C struct. With\nthis C struct, you can create:\n\n- a \"write lock\", which corresponds to an exclusive lock.\n- a \"read lock\", which corresponds to a shared lock.\n\nThe terminology might be a little different compared to Zig. But the meaning is still the same.\nTherefore, just remember this relationship, write locks are exclusive locks, while read locks are shared locks.\n\nWhen a thread tries to acquire a read lock (i.e., a shared lock), this thread gets the shared lock\nif and only if another thread does not currently hold a write lock (i.e., an exclusive lock), and also\nif there are no other threads already in the queue,\nwaiting for their turn to acquire a write lock. In other words, the thread in the queue has attempted\nto get a write lock earlier, but this thread was blocked\nbecause there was another thread running that already had a write lock. As a consequence, this thread is in the queue to get a write lock,\nand it's currently waiting for the other thread with a write lock to finish its execution.\n\nWhen a thread tries to acquire a read lock, but it fails in acquiring this read lock, either because there is\na thread with a write lock already running, or because there is a thread in the queue to get a write lock,\nthe execution of this thread is instantly blocked, i.e., paused. This thread will indefinitely attempt to get the\nread lock, and its execution will be unblocked (or unpaused) only after this thread successfully acquires the read lock.\n\nIf you think deeply about this dynamic between read locks versus write locks, you might notice that a read lock is basically a safety mechanism.\nMore specifically, it's a way for us to\nallow a particular thread to run together with the other threads only when it's safe to. In other words, if there is currently\na thread with a write lock running, then it's very likely not safe for the thread that is trying to acquire the read lock to run now.\nAs a consequence, the read lock protects this thread from running into dangerous waters, and patiently waits for the\n\"write lock\" thread to finishes its tasks before it continues.\n\nOn the other hand, if there are only \"read lock\" (i.e., \"shared lock\") threads currently running\n(i.e., not a single \"write lock\" thread currently exists), then it\nis perfectly safe for this thread that is acquiring the read lock to run in parallel with the other\nthreads. As a result, the read lock just\nallows for this thread to run together with the other threads.\n\nThus, by using read locks (shared locks) in conjunction with write locks (exclusive locks), we can control which regions or sections\nof our multithreaded code is safe to have parallelism, and which sections are not safe to have parallelism.\n\n\n\n\n\n### Using read/write locks in Zig\n\nThe Zig Standard Library supports read/write locks through the `std.Thread.RwLock` module.\nIf you want a particular thread to acquire a shared lock (i.e., a read lock), you should\ncall the `lockShared()` method from the `RwLock` object. But, if you want this thread\nto acquire an exclusive lock (i.e., a write lock) instead, then you should call the\n`lock()` method from the `RwLock` object.\n\nAs with mutexes, we also have to unlock the shared or exclusive locks that we acquire through a read/write lock object,\nonce we are at the end of our \"critical section\". If you have acquired an exclusive lock, then, you unlock\nthis exclusive lock by calling the `unlock()` method from the read/write lock object. In contrast,\nif you have acquired a shared lock instead, then, call `unlockShared()` to unlock this shared lock.\n\nAs a simple example, the snippet below creates three separate threads responsible for reading the\ncurrent value in a `counter` object, and it also creates another thread responsible for writing\nnew data into the `counter` object (incrementing it, more specifically).\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar counter: u32 = 0;\nfn reader(lock: *RwLock) !void {\n while (true) {\n lock.lockShared();\n const v: u32 = counter;\n try stdout.print(\"{d}\", .{v});\n lock.unlockShared();\n std.time.sleep(2 * std.time.ns_per_s);\n }\n}\nfn writer(lock: *RwLock) void {\n while (true) {\n lock.lock();\n counter += 1;\n lock.unlock();\n std.time.sleep(2 * std.time.ns_per_s);\n }\n}\n\npub fn main() !void {\n var lock: RwLock = .{};\n const thr1 = try Thread.spawn(.{}, reader, .{&lock});\n const thr2 = try Thread.spawn(.{}, reader, .{&lock});\n const thr3 = try Thread.spawn(.{}, reader, .{&lock});\n const wthread = try Thread.spawn(.{}, writer, .{&lock});\n\n thr1.join();\n thr2.join();\n thr3.join();\n wthread.join();\n}\n```\n:::\n\n\n\n\n## Yielding a thread\n\nThe `Thread` struct supports yielding through the `yield()` method.\nYielding a thread means that the execution of the thread is temporarily stopped,\nand it moves to the end of the priority queue managed by the scheduler of\nyour operating system.\n\nThat is, when you yield a thread, you are essentially saying the following to your OS:\n\"Hey! Could you please stop executing this thread for now, and comeback to continue it later?\".\nYou could also interpret this yield operation as: \"Could you please deprioritize this thread,\nto focus on doing other things instead?\".\nSo this yield operation is also a way for you\nto stop a particular thread, so that you can work and prioritize other threads instead.\n\nIt's important to say that, yielding a thread is a \"not so common\" thread operation these days.\nIn other words, not many programmers use yielding in production, simply because it's hard to use\nthis operation and make it work properly, and also, there\nare better alternatives. Most programmers prefer to use `join()` instead.\nIn fact, most of the time, when you see someone using this \"yield\" operation in some code example,\nthey are usually doing so to help debug race conditions in their applications.\nThat is, this \"yield\" operation is mostly used as a debug tool nowadays.\n\nAnyway, if you want to yield a thread, just call the `yield()` method from it, like this:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nthread.yield();\n```\n:::\n\n\n\n\n\n\n\n\n## Common problems in threads\n\n\n\n### Deadlocks\n\nA deadlock occurs when two or more threads are blocked forever,\nwaiting for each other to release a resource. This usually happens when multiple locks are involved,\nand the order of acquiring them is not well managed.\n\nThe code example below demonstrates a deadlock situation. We have two different threads that execute\ntwo different functions (`work1()` and `work2()`) in this example. And we also have two separate\nmutexes. If you compile and run this code example, you will notice that the program just runs indefinitely,\nwithout ending.\n\nWhen we look into the first thread, which executes the `work1()` function, we can\nnotice that this function acquires the `mut1` lock first. Because this is the first operation\nthat is executed inside this thread, which is the first thread created in the program.\nAfter that, the function sleeps for 1 second, to\nsimulate some type of work, and then, the function tries to acquire the `mut2` lock.\n\nOn the other hand, when we look into the second thread, which executes the `work2()` function,\nwe can see that this function acquires the `mut2` lock first. Because when this thread gets created and it tries\nto acquire this `mut2` lock, the first thread is still sleeping on that \"sleep 1 second\" line.\nAfter acquiring `mut2`, the `work2()` function also sleeps for 1 second, to\nsimulate some type of work, and then the function tries to acquire the `mut1` lock.\n\nThis creates a deadlock situation, because after the \"sleep for 1 second\" line in both threads,\nthread 1 is trying to acquire the `mut2` lock, but this lock is currently being used by thread 2.\nHowever, at this moment, thread 2 is also trying to acquire the `mut1` lock, which is currently\nbeing used by thread 1. Therefore, both threads end up waiting for ever. Waiting for their peer to\nfree the lock that they want to acquire.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar mut1: Mutex = .{}; var mut2: Mutex = .{};\nfn work1() !void {\n mut1.lock();\n std.time.sleep(1 * std.time.ns_per_s);\n mut2.lock();\n _ = try stdout.write(\"Doing some work 1\\n\");\n mut2.unlock(); mut1.unlock();\n}\n\nfn work2() !void {\n mut2.lock();\n std.time.sleep(1 * std.time.ns_per_s);\n mut1.lock();\n _ = try stdout.write(\"Doing some work 1\\n\");\n mut1.unlock(); mut2.unlock();\n}\n\npub fn main() !void {\n const thr1 = try Thread.spawn(.{}, work1, .{});\n const thr2 = try Thread.spawn(.{}, work2, .{});\n thr1.join();\n thr2.join();\n}\n```\n:::\n\n\n\n\n### Not calling `join()` or `detach()` {#sec-not-call-join-detach}\n\nWhen you do not call either `join()` or `detach()` over a thread, then this thread becomes a \"zombie thread\",\nbecause it does not have a clear \"return point\".\nYou could also interpret this as: \"nobody is properly responsible for managing the thread\".\nWhen we don't establish if a thread is either *joinable* or *detached*,\nnobody becomes responsible for dealing with the return value of this thread, and also,\nnobody becomes responsible for clearing (or freeing) the resources associated with this thread.\n\nYou don't want to be in this situation, so remember to always use `join()` or `detach()`\non the threads that you create. When you don't use one of these methods, we lose\ncontrol over the thread, and its resources are never freed\n(i.e., you have leaked resources in the system).\n\n\n### Cancelling or killing a particular thread\n\nWhen we think about the `pthreads` C library, there is a possible way to asynchronously kill or cancel\na thread, which is by sending a `SIGTERM` signal to the thread through the `pthread_kill()` function.\nBut canceling a thread like this is bad. It's dangerously bad. As a consequence, the Zig implementation\nof threads does not have a similar function, or, a similar way to asynchronously cancel or kill\na thread.\n\nTherefore, if you want to cancel a thread in the middle of its execution in Zig,\nthen one good strategy that you can take is to use control flow in conjunction with `join()`.\nMore specifically, you can design your thread around a while loop that is constantly\nchecking if the thread should continue running.\nIf it's time to cancel the thread, we could make the while loop break, and join the thread with the main thread\nby calling `join()`.\n\nThe code example below demonstrates to some extent this strategy.\nHere, we are using control flow to break the while loop, and exit the thread earlier than\nwhat we have initially planned to. This example also demonstrates how can we use\natomic objects in Zig with the `Value()` generic function that we have mentioned in @sec-atomic-operation.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Thread = std.Thread;\nconst stdout = std.io.getStdOut().writer();\nvar running = std.atomic.Value(bool).init(true);\nvar counter: u64 = 0;\nfn do_more_work() void {\n std.time.sleep(2 * std.time.ns_per_s);\n}\nfn work() !void {\n while (running.load(.monotonic)) {\n for (0..10000) |_| { counter += 1; }\n if (counter < 15000) {\n _ = try stdout.write(\n \"Time to cancel the thread.\\n\"\n );\n running.store(false, .monotonic);\n } else {\n _ = try stdout.write(\"Time to do more work.\\n\");\n do_more_work();\n running.store(false, .monotonic);\n }\n }\n}\n\npub fn main() !void {\n const thread = try Thread.spawn(.{}, work, .{});\n thread.join();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nTime to cancel the thread.\n```\n\n\n:::\n:::\n", - "supporting": [ - "14-threads_files" - ], - "filters": [ - "rmarkdown/pagebreak.lua" - ], - "includes": {}, - "engineDependencies": { - "knitr": [ - "{\"type\":\"list\",\"attributes\":{},\"value\":[]}" - ] - }, - "preserve": null, - "postProcess": false - } -} \ No newline at end of file diff --git a/_freeze/Chapters/14-threads/execute-results/html.json b/_freeze/Chapters/14-threads/execute-results/html.json index e68da4ad..6357f7e3 100644 --- a/_freeze/Chapters/14-threads/execute-results/html.json +++ b/_freeze/Chapters/14-threads/execute-results/html.json @@ -2,10 +2,8 @@ "hash": "5330e6bae2255d3ad46893b0641f0683", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Introducing threads and parallelism in Zig {#sec-thread}\n\nThreads are available in Zig through the `Thread` struct from the Zig Standard Library.\nThis struct represents a kernel thread, and it follows a POSIX Thread pattern,\nmeaning that, it works similarly to a thread from the `pthread` C library, which is usually available on any distribution\nof the GNU C Compiler (`gcc`). If you are not familiar with threads, I will give you some theory behind it first, shall we?\n\n\n## What are threads? {#sec-what-thread}\n\nA thread is basically a separate context of execution.\nWe use threads to introduce parallelism into our program,\nwhich in most cases, makes the program run faster, because we have multiple tasks\nbeing performed at the same time, parallel to each other.\n\nPrograms are normally single-threaded by default. Which means that each program\nusually runs on a single thread, or, a single context of execution. When we have only one thread running, we have no\nparallelism. And when we don't have parallelism, the commands are executed sequentially, that is,\nonly one command is executed at a time, one after another. By creating multiple threads inside our program,\nwe start to execute multiple commands at the same time.\n\nPrograms that create multiple threads are very common in the wild. Because many different types\nof applications are well suited for parallelism. Good examples are video and photo-editing applications\n(e.g. Adobe Photoshop or DaVinci Resolve), games (e.g. The Witcher 3), and also web browsers\n(e.g. Google Chrome, Firefox, Microsoft Edge, etc).\nFor example, in web browsers, threads are normally used to implement tabs.\nThe tabs in a web browsers usually run as separate threads in the main process of\nthe web browser. That is, each new tab that you open in your web browser\nusually runs on a separate thread of execution.\n\nBy running each tab in a separate thread, we allow all open tabs in the browser to run at the same time,\nand independently from each other. For example, you might have YouTube or Spotify currently open in\na tab, and you are listening to some podcast in that tab while at the same time\nworking in another tab, writing an essay on Google Docs. Even if you are not looking\ninto the YouTube tab, you can still hear the podcast only because this YouTube tab is running in parallel\nwith the other tab where Google Docs is running.\n\nWithout threads, the other alternative would be to run each tab as a completely separate\nprocess in your computer. But that would be a bad choice because just a few tabs would already consume\ntoo much power and resources from your computer. In other words, it's very expensive to create a completely new process,\ncompared to creating a new thread of execution. Also, the chances of you experiencing lag and overhead\nwhile using the browser would be significant. Threads are faster to create, and they also consume\nmuch, much less resources from the computer, especially because they share some resources\nwith the main process.\n\nTherefore, it's the use of threads in modern web browsers that allow you to hear the podcast\nat the same time while you are writing something on Google Docs.\nWithout threads, a web browser would probably be limited to just one single tab.\n\nThreads are also well-suited for anything that involves serving requests or orders.\nBecause serving a request takes time, and usually involves a lot of \"waiting time\".\nIn other words, we spend a lot of time in idle, waiting for something to complete.\nFor example, consider a restaurant. Serving orders in a restaurant usually involves\nthe following steps:\n\n1. receive order from the client.\n1. pass the order to the kitchen, and wait for the food to be cooked.\n1. start cooking the food in the kitchen.\n1. when the food is fully cooked deliver this food to the client.\n\nIf you think about the bullet points above, you will notice that one big moment of waiting time\nis present in this whole process, which is while the food is being cooked\ninside the kitchen. While the food is being prepped, both the waiter and the client\nthemselves are waiting for the food to be ready and delivered.\n\nIf we write a program to represent this restaurant, more specifically, a single-threaded program, then\nthis program would be very inefficient. Because the program would stay in idle, waiting for a considerable amount\nof time on the \"check if food is ready\" step. Consider the code snippet exposed below that could\npotentially represent such program.\n\nThe problem with this program is the while loop. This program will spend a lot of time\nwaiting on the while loop, doing nothing more than just checking if the food is ready.\nThis is a waste of time. Instead of waiting for something to happen, the waiter\ncould just send the order to the kitchen, and just move on, and continue with receiving\nmore orders from other clients, and sending more orders to the kitchen, instead\nof doing nothing and waiting for the food to be ready.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst order = Order.init(\"Pizza Margherita\", n = 1);\nconst waiter = Waiter.init();\nwaiter.receive_order(order);\nwaiter.ask_kitchen_to_cook();\nvar food_not_ready = true;\nwhile (food_not_ready) {\n food_not_ready = waiter.is_food_ready();\n}\nconst food = waiter.get_food_from_kitchen();\nwaiter.send_food_to_client(food);\n```\n:::\n\n\n\n\nThis is why threads would be a great fit for this program. We could use threads\nto free the waiters from their \"waiting duties\", so they can go on with their\nother tasks, and receive more orders. Take a look at the next example, where I have re-written the above\nprogram into a different program that uses threads to cook and deliver the orders.\n\nYou can see in this program that when a waiter receives a new order\nfrom a client, this waiter executes the `send_order()` function.\nThe only thing that this function does is to create a new thread\nand detaches it. Since creating a thread is a very fast operation,\nthis `send_order()` function returns almost immediately,\nso the waiter spends almost no time worrying about the order, and just\nmove on and tries to get the next order from the clients.\n\nInside the new thread created, the order gets cooked by a chef, and when the\nfood is ready, it's delivered to the client's table.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn cook_and_deliver_order(order: *Order) void {\n const chef = Chef.init();\n const food = chef.cook(order.*);\n chef.deliver_food(food);\n}\nfn send_order(order: Order) void {\n const cook_thread = Thread.spawn(\n .{}, cook_and_deliver_order, .{&order}\n );\n cook_thread.detach();\n}\n\nconst waiter = Waiter.init();\nwhile (true) {\n const order = waiter.get_new_order();\n if (order) {\n send_order(order);\n }\n}\n```\n:::\n\n\n\n\n\n\n## Threads versus processes\n\nWhen we run a program, this program is executed as a *process* in the operating system.\nThis is a one to one relationship, each program or application that you execute\nis a separate process in the operating system. But each program, or each process,\ncan create and contain multiple threads inside of it. Therefore,\nprocesses and threads have a one to many relationship.\n\nThis also means that every thread that we create is always associated with a particular process in our computer.\nIn other words, a thread is always a subset (or a children) of an existing process.\nAll threads share some of the resources associated with the process from which they were created.\nAnd because threads share resources with the process, they are very good for making communication\nbetween tasks easier.\n\nFor example, suppose that you were developing a big and complex application\nthat would be much simpler if you could split it in two, and make these two separate pieces talk\nwith each other. Some programmers opt to effectively write these two pieces of the codebase as two\ncompletely separate programs, and then, they use IPC (*inter-process communication*) to make these\ntwo separate programs/processes talk to each other, and make them work together.\n\nHowever, some programmers find IPC hard to deal with, and, as consequence,\nthey prefer to write one piece of the codebase as the \"main part of the program\",\nor, as the part of the code that runs as the process in the operating system,\nwhile the other piece of the codebase is written as a task to be executed in\na new thread. A process and a thread can easily comunicate with each other\nthrough both control flow, and also, through data, because they share and have\naccess to the same standard file descriptors (`stdout`, `stdin`, `stderr`), and also to the\nsame memory space on the heap and global data section.\n\n\nIn more details, each thread that you create have a separate stack frame reserved just for that thread,\nwhich essentially means that each local object that you create inside this thread, is local to that\nthread, i.e., the other threads cannot see this local object. Unless this object that you have created\nis an object that lives on the heap. In other words, if the memory associated with this object\nis on the heap, then, the other threads can potentially access this object.\n\nTherefore, objects that are stored in the stack are local to the thread where they were created.\nBut objects that are stored on the heap are potentially accessible to other threads. All of this means that,\neach thread has its own separate stack frame, but, at the same time, all threads share\nthe same heap, the same standard file descriptors (which means that they share the same `stdout`, `stdin`, `stderr`),\nand the same global data section in the program.\n\n\n\n## Creating a thread\n\nWe create new threads in Zig by first importing the `Thread` struct into\nour current Zig module and then calling the `spawn()` method of this struct,\nwhich creates (or \"spawns\") a new thread of execution from our current process.\nThis method has three arguments, which are, respectively:\n\n1. a `SpawnConfig` object, which contains configurations for the spawn process.\n1. the name of the function that is going to be executed (or that is going to be \"called\") inside this new thread.\n1. a list of arguments (or inputs) to be passed to the function provided in the second argument.\n\nWith these three arguments, you can control how the thread gets created, and also, specify which\nwork (or \"tasks\") will be performed inside this new thread. A thread is just a separate context of execution,\nand we usually create new threads in our code because we want to perform some work inside this\nnew context of execution. And we specify which exact work, or which exact steps that are going to be\nperformed inside this context by providing the name of a function as the second argument of the `spawn()` method.\n\nThus, when this new thread gets created, this function that you provided as input to the `spawn()`\nmethod gets called, or gets executed inside this new thread. You can control the\narguments, or the inputs that are passed to this function when it gets called by providing\na list of arguments (or a list of inputs) in the third argument of the `spawn()` method.\nThese arguments are passed to the function in the same order that they are\nprovided to `spawn()`.\n\nFurthermore, the `SpawnConfig` is a struct object with only two possible fields, or, two possible members, that you\ncan set to tailor the spawn behaviour. These fields are:\n\n- `stack_size`: you can provide a `usize` value to specify the size (in bytes) of the thread's stack frame. By default, this value is: $16 \\times 1024 \\times 1024$.\n- `allocator`: you can provide an allocator object to be used when allocating memory for the thread.\n\nTo use one of these two fields (or \"configs\"), you just have to create a new object of type `SpawnConfig`,\nand provide this object as input to the `spawn()` method. But, if you are not interested in using\none of these configs, and you are ok with using just the defaults, you can just provide an anonymous\nstruct literal (`.{}`) in place of this `SpawnConfig` argument.\n\nAs our first, and very simple example, consider the code exposed below.\nInside the same program, you can create multiple threads of execution if you want to.\nBut, in this first example, we are creating just a single thread of execution, because\nwe call `spawn()` only once.\n\nAlso, notice in this example that we are executing the function `do_some_work()`\ninside the new thread. Since this function receives no inputs, because it has\nno arguments, we have passed an empty list in this instance, or more precisely,\nan empty, anonymous struct (`.{}`) in the third argument of `spawn()`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Thread = std.Thread;\nfn do_some_work() !void {\n _ = try stdout.write(\"Starting the work.\\n\");\n std.time.sleep(100 * std.time.ns_per_ms);\n _ = try stdout.write(\"Finishing the work.\\n\");\n}\n\npub fn main() !void {\n const thread = try Thread.spawn(.{}, do_some_work, .{});\n thread.join();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nStarting the work.Finishing the work.\n```\n\n\n:::\n:::\n\n\n\n\nNotice the use of `try` when calling the `spawn()` method. This means\nthat this method can return an error in some circumstances. One circumstance\nin particular is when you attempt to create a new thread, when you have already\ncreated too much (i.e., you have exceeded the quota of concurrent threads in your system).\n\nBut, if the new thread is successfully created, the `spawn()` method returns a handler\nobject (which is just an object of type `Thread`) to this new thread. You can use\nthis handler object to effectively control all aspects of the thread.\n\nWhen the thread gets created, the function that you provided as input to `spawn()`\ngets invoked (i.e., gets called) to start the execution on this new thread.\nIn other words, every time you call `spawn()`, not only is a new thread created,\nbut the \"start work button\" of this thread is also automatically pressed.\nSo the work being performed in this thread starts as soon as the thread is created.\nThis is similar to how `pthread_create()` from the `pthreads` library in C works,\nwhich also starts the execution as soon as the thread is created.\n\n\n## Returning from a thread\n\nWe have learned in the previous section that the execution of the thread starts as soon as\nthe thread is created. Now, we will learn how to \"join\" or \"detach\" a thread in Zig.\n\"Join\" and \"detach\" are operations that control how the thread returns to\nthe main thread, or to the main process in our program.\n\nWe perform these operations by using the methods `join()` and `detach()` from the thread handler object.\nEvery thread that you create can be marked as either *joinable* or *detached* [@linux_pthread_create].\nYou can turn a thread into a *detached* thread by calling the `detach()` method\nfrom the thread handler object. But if you call the `join()` method instead, then this thread\nbecomes a *joinable* thread.\n\nA thread cannot be both *joinable* and *detached*. Which in general means\nthat you cannot call both `join()` and `detach()` on the same thread.\nBut a thread must be one of the two, meaning that, you should always call\neither `join()` or `detach()` over a thread. If you don't call\none of these two methods over your thread, you introduce undefined behaviour into your program,\nwhich is described in @sec-not-call-join-detach.\n\nNow, let's describe what each of these two methods do to your thread.\n\n\n### Joining a thread\n\nWhen you join a thread, you are essentially saying: \"Hey! Could you please wait for the thread to finish,\nbefore you continue with your execution?\". For example, if we come back to our first and simplest example\nof a thread in Zig, we created a single thread inside the `main()` function of our program\nand just called `join()` on this thread at the end. This section of the code example is reproduced below.\n\nBecause we are joining this new thread inside the `main()`'s scope, it means that the\nexecution of the `main()` function is temporarily stopped, to wait for the execution of the thread\nto finish. That is, the execution of `main()` stops temporarily at the line where `join()` gets called,\nand it will continue only after the thread has finished its tasks.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn main() !void {\n const thread = try Thread.spawn(.{}, do_some_work, .{});\n thread.join();\n}\n```\n:::\n\n\n\n\nBecause we have joined this new thread inside the `main()` scope, we have a\nguarantee that this new thread will finish before the end of the execution of `main()`.\nBecause it's guaranteed that `main()` will wait for the thread to finish its tasks.\n\nIn the example above, there are no more expressions after the `join()` call. We just have the end\nof the `main()`'s scope, and, therefore, the execution of our program just ends after the thread finishes its tasks,\nsince there is nothing more to do. But what if we had more stuff to do after the join call?\n\nTo demonstrate this other possibility, consider the next example exposed\nbelow. Here, we create a `print_id()` function, that just receives an id\nas input, and prints it to `stdout`. In this example, we are creating two\nnew threads, one after another. Then, we join the first thread, then,\nwe wait for two whole seconds, then, at last, we join the second thread.\n\nThe idea behind this example is that the last `join()` call is executed\nonly after the first thread finishes its task (i.e., the first `join()` call),\nand the two-second delay. If you compile and run this\nexample, you will notice that most messages are quickly printed to `stdout`,\ni.e., they appear almost instantly on your screen.\nHowever, the last message (\"Joining thread 2\") takes around 2 seconds to appear\non the screen.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_id(id: *const u8) !void {\n try stdout.print(\"Thread ID: {d}\\n\", .{id.*});\n}\n\npub fn main() !void {\n const id1: u8 = 1;\n const id2: u8 = 2;\n const thread1 = try Thread.spawn(.{}, print_id, .{&id1});\n const thread2 = try Thread.spawn(.{}, print_id, .{&id2});\n\n _ = try stdout.write(\"Joining thread 1\\n\");\n thread1.join();\n std.time.sleep(2 * std.time.ns_per_s);\n _ = try stdout.write(\"Joining thread 2\\n\");\n thread2.join();\n}\n```\n:::\n\n\n\n\n```\nThread ID: Joining thread 1\n1\nThread ID: 2\nJoining thread 2\n```\n\nThis demonstrates that both threads finish their work (i.e., printing the IDs)\nvery fast, before the two seconds of delay end. Because of that, the last `join()` call\nreturns pretty much instantly. Because when this last `join()` call happens, the second\nthread has already finished its task.\n\nNow, if you compile and run this example, you will also notice that, in some cases,\nthe messages intertwine with each other. In other words, you might see\nthe message \"Joining thread 1\" inserted in the middle of the message \"Thread 1\",\nor vice-versa. This happens because:\n\n- the threads are executing basically at the same time as the main process of the program (i.e., the `main()` function).\n- the threads share the same `stdout` from the main process of the program, which means that the messages that the threads produce are sent to exact same place as the messages produced by the main process.\n\nBoth of these points were described previously in @sec-what-thread.\nSo the messages might get intertwined because they are being produced and\nsent to the same `stdout` roughly at the same time.\nAnyway, when you call `join()` over a thread, the current process will wait\nfor the thread to finish before it continues, and, when the thread finishes its\ntask, the resources associated with this thread are automatically freed, and\nthe current process continues with its execution.\n\n\n### Detaching a thread\n\nWhen you detach a thread, the resources associated with this thread are automatically\nreleased back to the system, without the need for another thread to join with this terminated thread.\n\nIn other words, when you call `detach()` on a thread it's like when your children become adults,\ni.e., they become independent from you. A detached thread frees itself, and when this thread finishes its\ntasks, it does not report the results back to you. Thus, you normally mark a thread as *detached*\nwhen you don't need to use the return value of the thread, or when you don't care about\nwhen exactly the thread finishes its job, i.e., the thread solves everything by itself.\n\nTake the code example below. We create a new thread, detach it, and then, we just\nprint a final message before we end our program. We use the same `print_id()`\nfunction that we have used over the previous examples.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_id(id: *const u8) !void {\n try stdout.print(\"Thread ID: {d}\\n\", .{id.*});\n}\n\npub fn main() !void {\n const id1: u8 = 1;\n const thread1 = try Thread.spawn(.{}, print_id, .{&id1});\n thread1.detach();\n _ = try stdout.write(\"Finish main\\n\");\n}\n```\n:::\n\n\n\n\n```\nFinish main\n```\n\nNow, if you look closely at the output of this code example, you will notice\nthat only the final message in main was printed to the console. The message\nthat was supposed to be printed by `print_id()` did not appear in the console.\nWhy? It's because the main process of our program has finished first,\nbefore the thread was able to say anything.\n\nAnd that is perfectly ok behaviour, because the thread was detached, so it was\nable to free itself, without the need to wait for the main process.\nIf you ask main to sleep (or \"wait\") for some extra nanoseconds, before it ends, you will likely\nsee the message printed by `print_id()`, because you give enough time for the thread to\nfinish before the main process ends.\n\n\n## Thread pools\n\nThread pools is a very popular programming pattern, which is used especially on servers and daemons processes.\nA thread pool is just a set of threads, or a \"pool\" of threads. Many programmers like to use this pattern because it makes\nit easier to manage and use multiple threads in your program, instead of manually creating the threads when you need them.\n\nAlso, using thread pools might increase performance as well in your program,\nespecially if your program is constantly creating threads to perform short-lived tasks.\nIn such instance, a thread pool might cause an increase in performance because you do not have be constantly\ncreating and destroying threads all the time, so you don't face a lot of the overhead involved\nin this constant process of creating and destroying threads.\n\nThe main idea behind a thread pool is to have a set of threads already created and ready to perform\ntasks at all times. You create a set of threads at the moment that your program starts, and keep\nthese threads alive while your program runs. Each of these threads will be either performing a task, or\nwaiting for a task to be assigned.\nEvery time a new task emerges in your program, this task is added to a \"queue of tasks\",\nand the moment that a thread becomes available and ready to perform a new task,\nthis thread takes the next task from the \"queue of tasks\", and it simply performs the task.\n\nThe Zig Standard Library offers a thread pool implementation on the `std.Thread.Pool` struct.\nYou create a new instance of a `Pool` object by providing a `Pool.Options` object\nas input to the `init()` method of this struct. A `Pool.Options` object, is a struct object that contains\nconfigurations for the pool of threads. The most important settings in this struct object are\nthe members `n_jobs` and `allocator`. As the name suggests, the member `allocator` should receive an allocator object,\nwhile the member `n_jobs` specifies the number of threads to be created and maintained in this pool.\n\nConsider the example exposed below, that demonstrates how can we create a new thread pool object.\nHere, we create a `Pool.Options` object that contains\na general purpose allocator object, and also, the `n_jobs` member was set to 4, which\nmeans that the thread pool will create and use 4 threads.\n\nAlso notice that the `pool` object was initially set to `undefined`. This allow us\nto initially declare the thread pool object, but not properly instantiate the\nunderlying memory of the object. You have to initially declare your thread pool object\nby using `undefined` like this, because the `init()` method of `Pool` needs\nto have an initial pointer to properly instantiate the object.\n\nSo, just remember to create your thread pool object by using `undefined`, and then,\nafter that, you call the `init()` method over the object.\nYou should also not forget to call the `deinit()` method over the thread pool\nobject, once you are done with it, to release the resources allocated for the thread pool. Otherwise, you will\nhave a memory leak in your program.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Pool = std.Thread.Pool;\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const opt = Pool.Options{\n .n_jobs = 4,\n .allocator = allocator,\n };\n var pool: Pool = undefined;\n try pool.init(opt);\n defer pool.deinit();\n}\n```\n:::\n\n\n\n\nNow that we know how to create `Pool` objects, we have\nto understand how to assign tasks to be executed by the threads in this pool object.\nTo assign a task to be performed by a thread, we need to call the `spawn()` method\nfrom the thread pool object.\n\nThis `spawn()` method works identical to the `spawn()` method from the\n`Thread` object. The method has almost the same arguments as the previous one,\nmore precisely, we don't have to provide a `SpawnConfig` object in this case.\nBut instead of creating a new thread, this `spawn()` method from\nthe thread pool object just registers a new task in the internal \"queue of tasks\" to be performed,\nand any available thread in the pool will get this task, and it will simply perform the task.\n\nIn the example below, we are using our previous `print_id()` function once again.\nBut you may notice that the `print_id()` function is a little different this time,\nbecause now we are using `catch` instead of `try` in the `print()` call.\nCurrently, the `Pool` struct only supports functions that don't return errors\nas tasks. Thus, when assigning tasks to threads in a thread pool, it is essential to use functions\nthat don't return errors. That is why we are using `catch` here, so that the\n`print_id()` function don't return an error.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_id(id: *const u8) void {\n _ = stdout.print(\"Thread ID: {d}\\n\", .{id.*})\n catch void;\n}\nconst id1: u8 = 1;\nconst id2: u8 = 2;\ntry pool.spawn(print_id, .{&id1});\ntry pool.spawn(print_id, .{&id2});\n```\n:::\n\n\n\n\nThis limitation should probably not exist, and, in fact, it's already on the radar of the\nZig team to fix this issue, and it's being tracked in an [open issue](https://github.com/ziglang/zig/issues/18810)[^issue].\nSo, if you do need to provide a function that might return an error as the task\nto be performed by the threads in the thread pool, then, you are either limited to:\n\n- implementing your own thread pool that does not have this limitation.\n- wait for the Zig team to actually fix this issue.\n\n[^issue]: \n\n\n\n\n## Mutexes\n\nMutexes are a classic component of every thread library. In essence, a mutex is a *Mutually Exclusive Flag*, and this flag\nacts like a type of \"lock\", or as a gate keeper to a particular section of your code. Mutexes are related to thread synchronization,\nmore specifically, they prevent you from having some classic race conditions in your program,\nand, therefore, major bugs and undefined behaviour that are usually difficult to track and understand.\n\nThe main idea behind a mutex is to help us to control the execution of a particular section of the code, and to\nprevent two or more threads from executing this particular section of the code at the same time.\nMany programmers like to compare a mutex to a bathroom door (which typically has a lock).\nWhen a thread locks its own mutex object, it's like if the bathroom door was locked.\nTherefore, other people (in this case, other threads) who want to use the same bathroom at the same time\nmust be patient and simply wait for the current occupant (or thread) to unlock the door and get out of the bathroom.\n\nSome other programmers also like to explain mutexes by using the analogy of \"each person will have their turn to speak\".\nThis is the analogy used in the [*Multithreading Code* video from the Computerphile project](https://www.youtube.com/watch?v=7ENFeb-J75k&ab_channel=Computerphile)[^computerphile].\nImagine if you are in a conversation circle. There is a moderator in this circle, which is the person that decides who\nhas the right to speak at that particular moment. The moderator gives a green card (or some sort of an authorization card) to the person that\nis going to speak, and, as a result, everyone else must be silent and hear this person that has the green card.\nWhen the person finishes talking, they give the green card back to the moderator, and the moderator decides\nwho is going to talk next, and delivers the green card to that person. And the cycle goes on like this.\n\n[^computerphile]: \n\n\nA mutex acts like the moderator in this conversation circle. The mutex authorizes one single thread to execute a specific section of the code,\nand it also blocks the other threads from executing this same section of the code. If these other threads want to execute this same\npiece of the code, they are forced to wait for the the authorized thread to finish first.\nWhen the authorized thread finishes executing this code, the mutex authorizes the next thread to execute this code,\nwhile the remaining threads remain blocked. Therefore, a mutex is like a moderator that does a \"each\nthread will have their turn to execute this section of the code\" type of control.\n\n\nMutexes are especially used to prevent data race problems from happening. A data race problem happens when two or more threads\nare trying to read from or write to the same shared object at the same time.\nSo, when you have an object that is shared will all threads, and, you want to avoid two or more threads from\naccessing this same object at the same time, you can use a mutex to lock the part of the code that access this specific object.\nWhen a thread tries to run this code that is locked by a mutex, this thread stops its execution,\nand patiently waits for this section of the codebase to be unlocked to continue.\n\nNotice that mutexes are normally used to lock areas of the codebase that access/modify data that is **shared** with all threads,\ni.e., objects that are either stored in the global data section, or in the heap space of your program.\nSo mutexes are not normally used on areas of the codebase that access/modify objects that are local to the thread.\n\n\n\n### Critical section {#sec-critical-section}\n\nCritical section is a concept commonly associated with mutexes and thread synchronization.\nIn essence, a critical section is the section of the program that a thread access/modify a shared resource\n(i.e., an object, a file descriptor, something that all threads have access to). In other words,\na critical section is the section of the program where race conditions might happen, and, therefore,\nwhere undefined behaviour can be introduced into the program.\n\nWhen we use mutexes in our program, the critical section defines the area of the codebase that we want to lock.\nSo we normally lock the mutex object at the beginning of the critical section,\nand then, we unlock it at the end of the critical section.\nThe two bullet points exposed below comes from the \"Critical Section\" article from GeekFromGeeks,\nand they summarise well the role that a critical section plays in the thread synchronization problem [@geeks_critical_section].\n\n\n1. The critical section must be executed as an atomic operation, which means that once one thread or process has entered the critical section, all other threads or processes must wait until the executing thread or process exits the critical section. The purpose of synchronization mechanisms is to ensure that only one thread or process can execute the critical section at a time.\n1. The concept of a critical section is central to synchronization in computer systems, as it is necessary to ensure that multiple threads or processes can execute concurrently without interfering with each other. Various synchronization mechanisms such as semaphores, mutexes, monitors, and condition variables are used to implement critical sections and ensure that shared resources are accessed in a mutually exclusive manner.\n\n\n### Atomic operations {#sec-atomic-operation}\n\nYou will also see the term \"atomic operation\" a lot when reading about threads, race conditions and mutexes.\nIn summary, an operation is categorized as \"atomic\" when a context switch cannot occur in\nthe middle of the operation. In other words, this operation is always done from beginning to end, without interruptions\nof another process or operation in the middle of its execution phase.\n\nNot many operations today are atomic. But why do atomic operations matter here? It's because data races\n(which is a type of a race condition) cannot happen on operations that are atomic.\nSo if a particular line in your code performs an atomic operation, then this line will never\nsuffer from a data race problem. Therefore, programmers sometimes use an atomic operation\nto protect themselves from data race problems in their code.\n\nWhen you have an operation that is compiled into just one single assembly instruction, this operation might be atomic,\nbecause it's just one assembly instruction. But this is not guaranteed. This is usually true for old CPU architectures\n(such as `x86`). But nowadays, most assembly instructions in modern CPU architectures are broken down into multiple micro-tasks,\nwhich inherently makes the operation non-atomic, even if it consists of a single assembly instruction.\n\nThe Zig Standard Library offers some atomic functionality in the `std.atomic` module.\nIn this module, you will find a public and generic function called `Value()`. With this function we create an \"atomic object\", which is\na value that contains some native atomic operations, most notably, a `load()` and a `fetchAdd()` operation.\nIf you have experience with multithreading in C++, you probably have recognized this pattern. So yes, this generic\n\"atomic object\" in Zig is essentially identical to the template struct `std::atomic` from the C++ Standard Library.\nIt's important to emphasize that only primitive data types (i.e., the types presented in @sec-primitive-data-types)\nare supported by these atomic operations in Zig.\n\n\n\n\n\n### Data races and race conditions\n\nTo understand why mutexes are used, we need to understand better the problem that they seek\nto solve, which can be summarized into data race problems. A data race problem is a type of a race condition,\nwhich happens when one thread is accessing a particular memory location (i.e., a particular shared object) at the same\ntime that another thread is trying to write/save new data into this same memory location (i.e., the same shared object).\n\nWe can simply define a race condition as any type of bug in your program that is based\non a \"who gets there first\" problem. A data race problem is a type of a race condition, because it occurs when two or more parties\nare trying to read and write into the same memory location at the same time, and, therefore, the end result of this operation\ndepends completely on who gets to this memory location first.\nAs a consequence, a program that has a data race problem will likely produce a different result each time that we execute it.\n\nThus, race conditions produce undefined behaviour and unpredictability because the program produces\na different answer each time a different person gets to the target location before the others.\nAnd, we have no easy way to either predict or control who is getting to this target location first.\nIn other words, each time your program runs, you may get a different answer because a different person,\nfunction, or part of the code finishes its tasks before the others.\n\nAs an example, consider the code snippet exposed below. In this example, we create a global counter\nvariable, and we also create an `increment()` function, whose job is to just increment this global counter\nvariable in a for loop.\n\nSince the for loop iterates 1 hundred thousand times, and, we create two separate threads\nin this code example, what number do you expect to see in the final message printed to `stdout`?\nThe answer should be 2 hundred thousand. Right? Well, in theory, this program was supposed\nto print 2 hundred thousand at the end, but in practice, every time that I execute this program\nI get a different answer.\n\nIn the example exposed below, you can see that this time the end\nresult was 117254, instead of the expected 200000. The second time I executed this program,\nI got the number 108592 as the result. So the end result of this program is varying, but it never gets\nto the expected 200000 that we want.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// Global counter variable\nvar counter: usize = 0;\n// Function to increment the counter\nfn increment() void {\n for (0..100000) |_| {\n counter += 1;\n }\n}\n\npub fn main() !void {\n const thr1 = try Thread.spawn(.{}, increment, .{});\n const thr2 = try Thread.spawn(.{}, increment, .{});\n thr1.join();\n thr2.join();\n try stdout.print(\"Couter value: {d}\\n\", .{counter});\n}\n```\n:::\n\n\n\n\n```\nCouter value: 117254\n```\n\n\nWhy this is happening? The answer is: because this program contains a data race problem.\nThis program would print the correct number 200000 if and only if the first thread finishes\nits tasks before the second thread starts to execute. But that is very unlikely to happen.\nBecause the process of creating the thread is too fast, and therefore, both threads start to execute roughly\nat the same time. If you change this code to add some nanoseconds of sleep between the first and the second calls to `spawn()`,\nyou will increase the chances of the program producing the \"correct result\".\n\nSo the data race problem happens because both threads are reading and writing to the same\nmemory location at roughly the same time. In this example, each thread is essentially performing\nthree basic operations at each iteration of the for loop, which are:\n\n1. reading the current value of `count`.\n1. incrementing this value by 1.\n1. writing the result back into `count`.\n\nIdeally, a thread B should read the value of `count`, only after the other thread A has finished\nwriting the incremented value back into the `count` object. Therefore, in the ideal scenario, which is demonstrated\nin @tbl-data-race-ideal, the threads should work in sync with each other. But the reality is that these\nthreads are out of sync, and because of that, they suffer from a data race problem, which is demonstrated\nin @tbl-data-race-not.\n\nNotice that, in the data race scenario (@tbl-data-race-not), the read performed by a thread B happens\nbefore the write operation of thread A, and that ultimately leads to wrong results at the end of the program.\nBecause when thread B reads the value of the `count` variable, thread A is still processing\nthe initial value from `count`, and has not yet written the new, incremented value back to `count`. As a result,\nthread B ends up reading the same initial (or \"old\") value from `count` instead of\nthe updated, incremented value that thread A would have written.\n\n\n::: {#tbl-data-race-ideal}\n\n| Thread 1 | Thread 2 | Integer value |\n|-------------|-------------|---------------|\n| read value | | 0 |\n| increment | | 1 |\n| write value | | 1 |\n| | read value | 1 |\n| | increment | 2 |\n| | write value | 2 |\n\n: An ideal scenario for two threads incrementing the same integer value\n:::\n\n::: {#tbl-data-race-not}\n\n| Thread 1 | Thread 2 | Integer value |\n|-------------|-------------|---------------|\n| read value | | 0 |\n| | read value | 0 |\n| increment | | 1 |\n| | increment | 1 |\n| write value | | 1 |\n| | write value | 1 |\n\n: A data race scenario when two threads are incrementing the same integer value\n:::\n\n\nIf you think about these diagrams exposed in form of tables, you will notice that they relate back to our discussion of atomic operations\nin @sec-atomic-operation. Remember, atomic operations are operations that the CPU executes\nfrom beginning to end, without interruptions from other threads or processes. So,\nthe scenario exposed in @tbl-data-race-ideal does not suffer from a data race, because\nthe operations performed by thread A are not interrupted in the middle by the operations\nfrom thread B.\n\nIf we also think about the discussion of critical section from @sec-critical-section, we can identify\nthe section that representes the critical section of the program, which is the section that is vulnerable\nto data race conditions. In this example, the critical section of the program is the line where we increment\nthe `counter` variable (`counter += 1`). So, ideally, we want to use a mutex, and lock right before this line, and then\nunlock right after this line.\n\n\n\n\n### Using mutexes in Zig\n\nNow that we know the problem that mutexes seek to solve, we can learn how to use them in Zig.\nMutexes in Zig are available through the `std.Thread.Mutex` struct from the Zig Standard Library.\nIf we take the same code from the previous example, and improve it with mutexes, to solve\nour data race problem, we get the code example below.\n\nNotice that this time, we had to alter the `increment()` function to receive a pointer to\nthe `Mutex` object as input. All that we need to do, to make this program safe against\ndata race problems, is to call the `lock()` method at the beginning of\nthe critical section, and then, call `unlock()` at the end of the critical section.\nNotice that the output of this program is now the correct number of 200000.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Thread = std.Thread;\nconst Mutex = std.Thread.Mutex;\nvar counter: usize = 0;\nfn increment(mutex: *Mutex) void {\n for (0..100000) |_| {\n mutex.lock();\n counter += 1;\n mutex.unlock();\n }\n}\n\npub fn main() !void {\n var mutex: Mutex = .{};\n const thr1 = try Thread.spawn(.{}, increment, .{&mutex});\n const thr2 = try Thread.spawn(.{}, increment, .{&mutex});\n thr1.join();\n thr2.join();\n try stdout.print(\"Couter value: {d}\\n\", .{counter});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nCouter value: 200000\n```\n\n\n:::\n:::\n\n\n\n\n\n\n\n## Read/Write locks\n\nMutexes are normally used when it's not always safe for two or more threads running the same\npiece of code at the same time. In contrast, read/write locks are normally used in situations\nwhere you have a mixture of scenarios, i.e., there are some pieces of the codebase that are safe\nto run in parallel, and other pieces that are not safe.\n\nFor example, suppose that you have multiple threads that uses the same shared file in the filesystem to store some configurations, or\nstatistics. If two or more threads try to read the data from this same file at the same time, nothing bad happens.\nSo this part of the codebase is perfectly safe to be executed in parallel, with multiple threads reading the same file at the same time.\n\nHowever, if two or more threads try to write data into this same file at the same time, then we cause some race condition\nproblems. So this other part of the codebase is not safe to be executed in parallel.\nMore specifically, a thread might end up writing data in the middle of the data written by the other thread.\nThis process of two or more threads writing to the same location might lead to data corruption.\nThis specific situation is usually called a *torn write*.\n\nThus, what we can extract from this example is that there are certain types of operations that cause\na race condition, but there are also other types of operations that do not cause a race condition problem.\nYou could also say that there are types of operations that are susceptible to race condition problems,\nand there are other types of operations that are not.\n\nA read/write lock is a type of lock that acknowledges the existence of this specific scenario, and you can\nuse this type of lock to control which parts of the codebase are safe to run in parallel and which parts are not.\n\n\n\n### Exclusive lock vs shared lock\n\nTherefore, a read/write lock is a little different from a mutex. Because a mutex is always an *exclusive lock*, meaning that, only\none thread is allowed to execute at all times. With an exclusive lock, the other threads are always \"excluded\",\ni.e., they are always blocked from executing. But in a read/write lock, the other threads might be authorized\nto run at the same time, depending on the type of lock that they acquire.\n\nWe have two types of locks in a read/write lock, which are: an exclusive lock and a shared lock. An exclusive lock works exactly the same\nas a mutex, while a shared lock is a lock that does not block the other threads from running at the same time.\nIn the `pthreads` C library, read/write locks are available through the `pthread_rwlock_t` C struct. With\nthis C struct, you can create:\n\n- a \"write lock\", which corresponds to an exclusive lock.\n- a \"read lock\", which corresponds to a shared lock.\n\nThe terminology might be a little different compared to Zig. But the meaning is still the same.\nTherefore, just remember this relationship, write locks are exclusive locks, while read locks are shared locks.\n\nWhen a thread tries to acquire a read lock (i.e., a shared lock), this thread gets the shared lock\nif and only if another thread does not currently hold a write lock (i.e., an exclusive lock), and also\nif there are no other threads already in the queue,\nwaiting for their turn to acquire a write lock. In other words, the thread in the queue has attempted\nto get a write lock earlier, but this thread was blocked\nbecause there was another thread running that already had a write lock. As a consequence, this thread is in the queue to get a write lock,\nand it's currently waiting for the other thread with a write lock to finish its execution.\n\nWhen a thread tries to acquire a read lock, but it fails in acquiring this read lock, either because there is\na thread with a write lock already running, or because there is a thread in the queue to get a write lock,\nthe execution of this thread is instantly blocked, i.e., paused. This thread will indefinitely attempt to get the\nread lock, and its execution will be unblocked (or unpaused) only after this thread successfully acquires the read lock.\n\nIf you think deeply about this dynamic between read locks versus write locks, you might notice that a read lock is basically a safety mechanism.\nMore specifically, it's a way for us to\nallow a particular thread to run together with the other threads only when it's safe to. In other words, if there is currently\na thread with a write lock running, then it's very likely not safe for the thread that is trying to acquire the read lock to run now.\nAs a consequence, the read lock protects this thread from running into dangerous waters, and patiently waits for the\n\"write lock\" thread to finishes its tasks before it continues.\n\nOn the other hand, if there are only \"read lock\" (i.e., \"shared lock\") threads currently running\n(i.e., not a single \"write lock\" thread currently exists), then it\nis perfectly safe for this thread that is acquiring the read lock to run in parallel with the other\nthreads. As a result, the read lock just\nallows for this thread to run together with the other threads.\n\nThus, by using read locks (shared locks) in conjunction with write locks (exclusive locks), we can control which regions or sections\nof our multithreaded code is safe to have parallelism, and which sections are not safe to have parallelism.\n\n\n\n\n\n### Using read/write locks in Zig\n\nThe Zig Standard Library supports read/write locks through the `std.Thread.RwLock` module.\nIf you want a particular thread to acquire a shared lock (i.e., a read lock), you should\ncall the `lockShared()` method from the `RwLock` object. But, if you want this thread\nto acquire an exclusive lock (i.e., a write lock) instead, then you should call the\n`lock()` method from the `RwLock` object.\n\nAs with mutexes, we also have to unlock the shared or exclusive locks that we acquire through a read/write lock object,\nonce we are at the end of our \"critical section\". If you have acquired an exclusive lock, then, you unlock\nthis exclusive lock by calling the `unlock()` method from the read/write lock object. In contrast,\nif you have acquired a shared lock instead, then, call `unlockShared()` to unlock this shared lock.\n\nAs a simple example, the snippet below creates three separate threads responsible for reading the\ncurrent value in a `counter` object, and it also creates another thread responsible for writing\nnew data into the `counter` object (incrementing it, more specifically).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar counter: u32 = 0;\nfn reader(lock: *RwLock) !void {\n while (true) {\n lock.lockShared();\n const v: u32 = counter;\n try stdout.print(\"{d}\", .{v});\n lock.unlockShared();\n std.time.sleep(2 * std.time.ns_per_s);\n }\n}\nfn writer(lock: *RwLock) void {\n while (true) {\n lock.lock();\n counter += 1;\n lock.unlock();\n std.time.sleep(2 * std.time.ns_per_s);\n }\n}\n\npub fn main() !void {\n var lock: RwLock = .{};\n const thr1 = try Thread.spawn(.{}, reader, .{&lock});\n const thr2 = try Thread.spawn(.{}, reader, .{&lock});\n const thr3 = try Thread.spawn(.{}, reader, .{&lock});\n const wthread = try Thread.spawn(.{}, writer, .{&lock});\n\n thr1.join();\n thr2.join();\n thr3.join();\n wthread.join();\n}\n```\n:::\n\n\n\n\n\n## Yielding a thread\n\nThe `Thread` struct supports yielding through the `yield()` method.\nYielding a thread means that the execution of the thread is temporarily stopped,\nand it moves to the end of the priority queue managed by the scheduler of\nyour operating system.\n\nThat is, when you yield a thread, you are essentially saying the following to your OS:\n\"Hey! Could you please stop executing this thread for now, and comeback to continue it later?\".\nYou could also interpret this yield operation as: \"Could you please deprioritize this thread,\nto focus on doing other things instead?\".\nSo this yield operation is also a way for you\nto stop a particular thread, so that you can work and prioritize other threads instead.\n\nIt's important to say that, yielding a thread is a \"not so common\" thread operation these days.\nIn other words, not many programmers use yielding in production, simply because it's hard to use\nthis operation and make it work properly, and also, there\nare better alternatives. Most programmers prefer to use `join()` instead.\nIn fact, most of the time, when you see someone using this \"yield\" operation in some code example,\nthey are usually doing so to help debug race conditions in their applications.\nThat is, this \"yield\" operation is mostly used as a debug tool nowadays.\n\nAnyway, if you want to yield a thread, just call the `yield()` method from it, like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nthread.yield();\n```\n:::\n\n\n\n\n\n\n\n\n\n## Common problems in threads\n\n\n\n### Deadlocks\n\nA deadlock occurs when two or more threads are blocked forever,\nwaiting for each other to release a resource. This usually happens when multiple locks are involved,\nand the order of acquiring them is not well managed.\n\nThe code example below demonstrates a deadlock situation. We have two different threads that execute\ntwo different functions (`work1()` and `work2()`) in this example. And we also have two separate\nmutexes. If you compile and run this code example, you will notice that the program just runs indefinitely,\nwithout ending.\n\nWhen we look into the first thread, which executes the `work1()` function, we can\nnotice that this function acquires the `mut1` lock first. Because this is the first operation\nthat is executed inside this thread, which is the first thread created in the program.\nAfter that, the function sleeps for 1 second, to\nsimulate some type of work, and then, the function tries to acquire the `mut2` lock.\n\nOn the other hand, when we look into the second thread, which executes the `work2()` function,\nwe can see that this function acquires the `mut2` lock first. Because when this thread gets created and it tries\nto acquire this `mut2` lock, the first thread is still sleeping on that \"sleep 1 second\" line.\nAfter acquiring `mut2`, the `work2()` function also sleeps for 1 second, to\nsimulate some type of work, and then the function tries to acquire the `mut1` lock.\n\nThis creates a deadlock situation, because after the \"sleep for 1 second\" line in both threads,\nthread 1 is trying to acquire the `mut2` lock, but this lock is currently being used by thread 2.\nHowever, at this moment, thread 2 is also trying to acquire the `mut1` lock, which is currently\nbeing used by thread 1. Therefore, both threads end up waiting for ever. Waiting for their peer to\nfree the lock that they want to acquire.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar mut1: Mutex = .{}; var mut2: Mutex = .{};\nfn work1() !void {\n mut1.lock();\n std.time.sleep(1 * std.time.ns_per_s);\n mut2.lock();\n _ = try stdout.write(\"Doing some work 1\\n\");\n mut2.unlock(); mut1.unlock();\n}\n\nfn work2() !void {\n mut2.lock();\n std.time.sleep(1 * std.time.ns_per_s);\n mut1.lock();\n _ = try stdout.write(\"Doing some work 1\\n\");\n mut1.unlock(); mut2.unlock();\n}\n\npub fn main() !void {\n const thr1 = try Thread.spawn(.{}, work1, .{});\n const thr2 = try Thread.spawn(.{}, work2, .{});\n thr1.join();\n thr2.join();\n}\n```\n:::\n\n\n\n\n\n### Not calling `join()` or `detach()` {#sec-not-call-join-detach}\n\nWhen you do not call either `join()` or `detach()` over a thread, then this thread becomes a \"zombie thread\",\nbecause it does not have a clear \"return point\".\nYou could also interpret this as: \"nobody is properly responsible for managing the thread\".\nWhen we don't establish if a thread is either *joinable* or *detached*,\nnobody becomes responsible for dealing with the return value of this thread, and also,\nnobody becomes responsible for clearing (or freeing) the resources associated with this thread.\n\nYou don't want to be in this situation, so remember to always use `join()` or `detach()`\non the threads that you create. When you don't use one of these methods, we lose\ncontrol over the thread, and its resources are never freed\n(i.e., you have leaked resources in the system).\n\n\n### Cancelling or killing a particular thread\n\nWhen we think about the `pthreads` C library, there is a possible way to asynchronously kill or cancel\na thread, which is by sending a `SIGTERM` signal to the thread through the `pthread_kill()` function.\nBut canceling a thread like this is bad. It's dangerously bad. As a consequence, the Zig implementation\nof threads does not have a similar function, or, a similar way to asynchronously cancel or kill\na thread.\n\nTherefore, if you want to cancel a thread in the middle of its execution in Zig,\nthen one good strategy that you can take is to use control flow in conjunction with `join()`.\nMore specifically, you can design your thread around a while loop that is constantly\nchecking if the thread should continue running.\nIf it's time to cancel the thread, we could make the while loop break, and join the thread with the main thread\nby calling `join()`.\n\nThe code example below demonstrates to some extent this strategy.\nHere, we are using control flow to break the while loop, and exit the thread earlier than\nwhat we have initially planned to. This example also demonstrates how can we use\natomic objects in Zig with the `Value()` generic function that we have mentioned in @sec-atomic-operation.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Thread = std.Thread;\nconst stdout = std.io.getStdOut().writer();\nvar running = std.atomic.Value(bool).init(true);\nvar counter: u64 = 0;\nfn do_more_work() void {\n std.time.sleep(2 * std.time.ns_per_s);\n}\nfn work() !void {\n while (running.load(.monotonic)) {\n for (0..10000) |_| { counter += 1; }\n if (counter < 15000) {\n _ = try stdout.write(\n \"Time to cancel the thread.\\n\"\n );\n running.store(false, .monotonic);\n } else {\n _ = try stdout.write(\"Time to do more work.\\n\");\n do_more_work();\n running.store(false, .monotonic);\n }\n }\n}\n\npub fn main() !void {\n const thread = try Thread.spawn(.{}, work, .{});\n thread.join();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nTime to cancel the thread.\n```\n\n\n:::\n:::\n", - "supporting": [ - "14-threads_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n# Introducing threads and parallelism in Zig {#sec-thread}\n\nThreads are available in Zig through the `Thread` struct from the Zig Standard Library.\nThis struct represents a kernel thread, and it follows a POSIX Thread pattern,\nmeaning that, it works similarly to a thread from the `pthread` C library, which is usually available on any distribution\nof the GNU C Compiler (`gcc`). If you are not familiar with threads, I will give you some theory behind it first, shall we?\n\n\n## What are threads? {#sec-what-thread}\n\nA thread is basically a separate context of execution.\nWe use threads to introduce parallelism into our program,\nwhich in most cases, makes the program run faster, because we have multiple tasks\nbeing performed at the same time, parallel to each other.\n\nPrograms are normally single-threaded by default. Which means that each program\nusually runs on a single thread, or, a single context of execution. When we have only one thread running, we have no\nparallelism. And when we don't have parallelism, the commands are executed sequentially, that is,\nonly one command is executed at a time, one after another. By creating multiple threads inside our program,\nwe start to execute multiple commands at the same time.\n\nPrograms that create multiple threads are very common in the wild. Because many different types\nof applications are well suited for parallelism. Good examples are video and photo-editing applications\n(e.g. Adobe Photoshop or DaVinci Resolve), games (e.g. The Witcher 3), and also web browsers\n(e.g. Google Chrome, Firefox, Microsoft Edge, etc).\nFor example, in web browsers, threads are normally used to implement tabs.\nThe tabs in a web browsers usually run as separate threads in the main process of\nthe web browser. That is, each new tab that you open in your web browser\nusually runs on a separate thread of execution.\n\nBy running each tab in a separate thread, we allow all open tabs in the browser to run at the same time,\nand independently from each other. For example, you might have YouTube or Spotify currently open in\na tab, and you are listening to some podcast in that tab while at the same time\nworking in another tab, writing an essay on Google Docs. Even if you are not looking\ninto the YouTube tab, you can still hear the podcast only because this YouTube tab is running in parallel\nwith the other tab where Google Docs is running.\n\nWithout threads, the other alternative would be to run each tab as a completely separate\nprocess in your computer. But that would be a bad choice because just a few tabs would already consume\ntoo much power and resources from your computer. In other words, it's very expensive to create a completely new process,\ncompared to creating a new thread of execution. Also, the chances of you experiencing lag and overhead\nwhile using the browser would be significant. Threads are faster to create, and they also consume\nmuch, much less resources from the computer, especially because they share some resources\nwith the main process.\n\nTherefore, it's the use of threads in modern web browsers that allow you to hear the podcast\nat the same time while you are writing something on Google Docs.\nWithout threads, a web browser would probably be limited to just one single tab.\n\nThreads are also well-suited for anything that involves serving requests or orders.\nBecause serving a request takes time, and usually involves a lot of \"waiting time\".\nIn other words, we spend a lot of time in idle, waiting for something to complete.\nFor example, consider a restaurant. Serving orders in a restaurant usually involves\nthe following steps:\n\n1. receive order from the client.\n1. pass the order to the kitchen, and wait for the food to be cooked.\n1. start cooking the food in the kitchen.\n1. when the food is fully cooked deliver this food to the client.\n\nIf you think about the bullet points above, you will notice that one big moment of waiting time\nis present in this whole process, which is while the food is being cooked\ninside the kitchen. While the food is being prepped, both the waiter and the client\nthemselves are waiting for the food to be ready and delivered.\n\nIf we write a program to represent this restaurant, more specifically, a single-threaded program, then\nthis program would be very inefficient. Because the program would stay in idle, waiting for a considerable amount\nof time on the \"check if food is ready\" step. Consider the code snippet exposed below that could\npotentially represent such program.\n\nThe problem with this program is the while loop. This program will spend a lot of time\nwaiting on the while loop, doing nothing more than just checking if the food is ready.\nThis is a waste of time. Instead of waiting for something to happen, the waiter\ncould just send the order to the kitchen, and just move on, and continue with receiving\nmore orders from other clients, and sending more orders to the kitchen, instead\nof doing nothing and waiting for the food to be ready.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst order = Order.init(\"Pizza Margherita\", n = 1);\nconst waiter = Waiter.init();\nwaiter.receive_order(order);\nwaiter.ask_kitchen_to_cook();\nvar food_not_ready = true;\nwhile (food_not_ready) {\n food_not_ready = waiter.is_food_ready();\n}\nconst food = waiter.get_food_from_kitchen();\nwaiter.send_food_to_client(food);\n```\n:::\n\n\nThis is why threads would be a great fit for this program. We could use threads\nto free the waiters from their \"waiting duties\", so they can go on with their\nother tasks, and receive more orders. Take a look at the next example, where I have re-written the above\nprogram into a different program that uses threads to cook and deliver the orders.\n\nYou can see in this program that when a waiter receives a new order\nfrom a client, this waiter executes the `send_order()` function.\nThe only thing that this function does is to create a new thread\nand detaches it. Since creating a thread is a very fast operation,\nthis `send_order()` function returns almost immediately,\nso the waiter spends almost no time worrying about the order, and just\nmove on and tries to get the next order from the clients.\n\nInside the new thread created, the order gets cooked by a chef, and when the\nfood is ready, it's delivered to the client's table.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn cook_and_deliver_order(order: *Order) void {\n const chef = Chef.init();\n const food = chef.cook(order.*);\n chef.deliver_food(food);\n}\nfn send_order(order: Order) void {\n const cook_thread = Thread.spawn(\n .{}, cook_and_deliver_order, .{&order}\n );\n cook_thread.detach();\n}\n\nconst waiter = Waiter.init();\nwhile (true) {\n const order = waiter.get_new_order();\n if (order) {\n send_order(order);\n }\n}\n```\n:::\n\n\n\n\n## Threads versus processes\n\nWhen we run a program, this program is executed as a *process* in the operating system.\nThis is a one to one relationship, each program or application that you execute\nis a separate process in the operating system. But each program, or each process,\ncan create and contain multiple threads inside of it. Therefore,\nprocesses and threads have a one to many relationship.\n\nThis also means that every thread that we create is always associated with a particular process in our computer.\nIn other words, a thread is always a subset (or a children) of an existing process.\nAll threads share some of the resources associated with the process from which they were created.\nAnd because threads share resources with the process, they are very good for making communication\nbetween tasks easier.\n\nFor example, suppose that you were developing a big and complex application\nthat would be much simpler if you could split it in two, and make these two separate pieces talk\nwith each other. Some programmers opt to effectively write these two pieces of the codebase as two\ncompletely separate programs, and then, they use IPC (*inter-process communication*) to make these\ntwo separate programs/processes talk to each other, and make them work together.\n\nHowever, some programmers find IPC hard to deal with, and, as consequence,\nthey prefer to write one piece of the codebase as the \"main part of the program\",\nor, as the part of the code that runs as the process in the operating system,\nwhile the other piece of the codebase is written as a task to be executed in\na new thread. A process and a thread can easily comunicate with each other\nthrough both control flow, and also, through data, because they share and have\naccess to the same standard file descriptors (`stdout`, `stdin`, `stderr`), and also to the\nsame memory space on the heap and global data section.\n\n\nIn more details, each thread that you create have a separate stack frame reserved just for that thread,\nwhich essentially means that each local object that you create inside this thread, is local to that\nthread, i.e., the other threads cannot see this local object. Unless this object that you have created\nis an object that lives on the heap. In other words, if the memory associated with this object\nis on the heap, then, the other threads can potentially access this object.\n\nTherefore, objects that are stored in the stack are local to the thread where they were created.\nBut objects that are stored on the heap are potentially accessible to other threads. All of this means that,\neach thread has its own separate stack frame, but, at the same time, all threads share\nthe same heap, the same standard file descriptors (which means that they share the same `stdout`, `stdin`, `stderr`),\nand the same global data section in the program.\n\n\n\n## Creating a thread\n\nWe create new threads in Zig by first importing the `Thread` struct into\nour current Zig module and then calling the `spawn()` method of this struct,\nwhich creates (or \"spawns\") a new thread of execution from our current process.\nThis method has three arguments, which are, respectively:\n\n1. a `SpawnConfig` object, which contains configurations for the spawn process.\n1. the name of the function that is going to be executed (or that is going to be \"called\") inside this new thread.\n1. a list of arguments (or inputs) to be passed to the function provided in the second argument.\n\nWith these three arguments, you can control how the thread gets created, and also, specify which\nwork (or \"tasks\") will be performed inside this new thread. A thread is just a separate context of execution,\nand we usually create new threads in our code because we want to perform some work inside this\nnew context of execution. And we specify which exact work, or which exact steps that are going to be\nperformed inside this context by providing the name of a function as the second argument of the `spawn()` method.\n\nThus, when this new thread gets created, this function that you provided as input to the `spawn()`\nmethod gets called, or gets executed inside this new thread. You can control the\narguments, or the inputs that are passed to this function when it gets called by providing\na list of arguments (or a list of inputs) in the third argument of the `spawn()` method.\nThese arguments are passed to the function in the same order that they are\nprovided to `spawn()`.\n\nFurthermore, the `SpawnConfig` is a struct object with only two possible fields, or, two possible members, that you\ncan set to tailor the spawn behaviour. These fields are:\n\n- `stack_size`: you can provide a `usize` value to specify the size (in bytes) of the thread's stack frame. By default, this value is: $16 \\times 1024 \\times 1024$.\n- `allocator`: you can provide an allocator object to be used when allocating memory for the thread.\n\nTo use one of these two fields (or \"configs\"), you just have to create a new object of type `SpawnConfig`,\nand provide this object as input to the `spawn()` method. But, if you are not interested in using\none of these configs, and you are ok with using just the defaults, you can just provide an anonymous\nstruct literal (`.{}`) in place of this `SpawnConfig` argument.\n\nAs our first, and very simple example, consider the code exposed below.\nInside the same program, you can create multiple threads of execution if you want to.\nBut, in this first example, we are creating just a single thread of execution, because\nwe call `spawn()` only once.\n\nAlso, notice in this example that we are executing the function `do_some_work()`\ninside the new thread. Since this function receives no inputs, because it has\nno arguments, we have passed an empty list in this instance, or more precisely,\nan empty, anonymous struct (`.{}`) in the third argument of `spawn()`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Thread = std.Thread;\nfn do_some_work() !void {\n _ = try stdout.write(\"Starting the work.\\n\");\n std.time.sleep(100 * std.time.ns_per_ms);\n _ = try stdout.write(\"Finishing the work.\\n\");\n}\n\npub fn main() !void {\n const thread = try Thread.spawn(.{}, do_some_work, .{});\n thread.join();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nStarting the work.Finishing the work.\n```\n\n\n:::\n:::\n\n\nNotice the use of `try` when calling the `spawn()` method. This means\nthat this method can return an error in some circumstances. One circumstance\nin particular is when you attempt to create a new thread, when you have already\ncreated too much (i.e., you have exceeded the quota of concurrent threads in your system).\n\nBut, if the new thread is successfully created, the `spawn()` method returns a handler\nobject (which is just an object of type `Thread`) to this new thread. You can use\nthis handler object to effectively control all aspects of the thread.\n\nWhen the thread gets created, the function that you provided as input to `spawn()`\ngets invoked (i.e., gets called) to start the execution on this new thread.\nIn other words, every time you call `spawn()`, not only is a new thread created,\nbut the \"start work button\" of this thread is also automatically pressed.\nSo the work being performed in this thread starts as soon as the thread is created.\nThis is similar to how `pthread_create()` from the `pthreads` library in C works,\nwhich also starts the execution as soon as the thread is created.\n\n\n## Returning from a thread\n\nWe have learned in the previous section that the execution of the thread starts as soon as\nthe thread is created. Now, we will learn how to \"join\" or \"detach\" a thread in Zig.\n\"Join\" and \"detach\" are operations that control how the thread returns to\nthe main thread, or to the main process in our program.\n\nWe perform these operations by using the methods `join()` and `detach()` from the thread handler object.\nEvery thread that you create can be marked as either *joinable* or *detached* [@linux_pthread_create].\nYou can turn a thread into a *detached* thread by calling the `detach()` method\nfrom the thread handler object. But if you call the `join()` method instead, then this thread\nbecomes a *joinable* thread.\n\nA thread cannot be both *joinable* and *detached*. Which in general means\nthat you cannot call both `join()` and `detach()` on the same thread.\nBut a thread must be one of the two, meaning that, you should always call\neither `join()` or `detach()` over a thread. If you don't call\none of these two methods over your thread, you introduce undefined behaviour into your program,\nwhich is described in @sec-not-call-join-detach.\n\nNow, let's describe what each of these two methods do to your thread.\n\n\n### Joining a thread\n\nWhen you join a thread, you are essentially saying: \"Hey! Could you please wait for the thread to finish,\nbefore you continue with your execution?\". For example, if we come back to our first and simplest example\nof a thread in Zig, we created a single thread inside the `main()` function of our program\nand just called `join()` on this thread at the end. This section of the code example is reproduced below.\n\nBecause we are joining this new thread inside the `main()`'s scope, it means that the\nexecution of the `main()` function is temporarily stopped, to wait for the execution of the thread\nto finish. That is, the execution of `main()` stops temporarily at the line where `join()` gets called,\nand it will continue only after the thread has finished its tasks.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\npub fn main() !void {\n const thread = try Thread.spawn(.{}, do_some_work, .{});\n thread.join();\n}\n```\n:::\n\n\nBecause we have joined this new thread inside the `main()` scope, we have a\nguarantee that this new thread will finish before the end of the execution of `main()`.\nBecause it's guaranteed that `main()` will wait for the thread to finish its tasks.\n\nIn the example above, there are no more expressions after the `join()` call. We just have the end\nof the `main()`'s scope, and, therefore, the execution of our program just ends after the thread finishes its tasks,\nsince there is nothing more to do. But what if we had more stuff to do after the join call?\n\nTo demonstrate this other possibility, consider the next example exposed\nbelow. Here, we create a `print_id()` function, that just receives an id\nas input, and prints it to `stdout`. In this example, we are creating two\nnew threads, one after another. Then, we join the first thread, then,\nwe wait for two whole seconds, then, at last, we join the second thread.\n\nThe idea behind this example is that the last `join()` call is executed\nonly after the first thread finishes its task (i.e., the first `join()` call),\nand the two-second delay. If you compile and run this\nexample, you will notice that most messages are quickly printed to `stdout`,\ni.e., they appear almost instantly on your screen.\nHowever, the last message (\"Joining thread 2\") takes around 2 seconds to appear\non the screen.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_id(id: *const u8) !void {\n try stdout.print(\"Thread ID: {d}\\n\", .{id.*});\n}\n\npub fn main() !void {\n const id1: u8 = 1;\n const id2: u8 = 2;\n const thread1 = try Thread.spawn(.{}, print_id, .{&id1});\n const thread2 = try Thread.spawn(.{}, print_id, .{&id2});\n\n _ = try stdout.write(\"Joining thread 1\\n\");\n thread1.join();\n std.time.sleep(2 * std.time.ns_per_s);\n _ = try stdout.write(\"Joining thread 2\\n\");\n thread2.join();\n}\n```\n:::\n\n\n```\nThread ID: Joining thread 1\n1\nThread ID: 2\nJoining thread 2\n```\n\nThis demonstrates that both threads finish their work (i.e., printing the IDs)\nvery fast, before the two seconds of delay end. Because of that, the last `join()` call\nreturns pretty much instantly. Because when this last `join()` call happens, the second\nthread has already finished its task.\n\nNow, if you compile and run this example, you will also notice that, in some cases,\nthe messages intertwine with each other. In other words, you might see\nthe message \"Joining thread 1\" inserted in the middle of the message \"Thread 1\",\nor vice-versa. This happens because:\n\n- the threads are executing basically at the same time as the main process of the program (i.e., the `main()` function).\n- the threads share the same `stdout` from the main process of the program, which means that the messages that the threads produce are sent to exact same place as the messages produced by the main process.\n\nBoth of these points were described previously in @sec-what-thread.\nSo the messages might get intertwined because they are being produced and\nsent to the same `stdout` roughly at the same time.\nAnyway, when you call `join()` over a thread, the current process will wait\nfor the thread to finish before it continues, and, when the thread finishes its\ntask, the resources associated with this thread are automatically freed, and\nthe current process continues with its execution.\n\n\n### Detaching a thread\n\nWhen you detach a thread, the resources associated with this thread are automatically\nreleased back to the system, without the need for another thread to join with this terminated thread.\n\nIn other words, when you call `detach()` on a thread it's like when your children become adults,\ni.e., they become independent from you. A detached thread frees itself, and when this thread finishes its\ntasks, it does not report the results back to you. Thus, you normally mark a thread as *detached*\nwhen you don't need to use the return value of the thread, or when you don't care about\nwhen exactly the thread finishes its job, i.e., the thread solves everything by itself.\n\nTake the code example below. We create a new thread, detach it, and then, we just\nprint a final message before we end our program. We use the same `print_id()`\nfunction that we have used over the previous examples.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_id(id: *const u8) !void {\n try stdout.print(\"Thread ID: {d}\\n\", .{id.*});\n}\n\npub fn main() !void {\n const id1: u8 = 1;\n const thread1 = try Thread.spawn(.{}, print_id, .{&id1});\n thread1.detach();\n _ = try stdout.write(\"Finish main\\n\");\n}\n```\n:::\n\n\n```\nFinish main\n```\n\nNow, if you look closely at the output of this code example, you will notice\nthat only the final message in main was printed to the console. The message\nthat was supposed to be printed by `print_id()` did not appear in the console.\nWhy? It's because the main process of our program has finished first,\nbefore the thread was able to say anything.\n\nAnd that is perfectly ok behaviour, because the thread was detached, so it was\nable to free itself, without the need to wait for the main process.\nIf you ask main to sleep (or \"wait\") for some extra nanoseconds, before it ends, you will likely\nsee the message printed by `print_id()`, because you give enough time for the thread to\nfinish before the main process ends.\n\n\n## Thread pools\n\nThread pools is a very popular programming pattern, which is used especially on servers and daemons processes.\nA thread pool is just a set of threads, or a \"pool\" of threads. Many programmers like to use this pattern because it makes\nit easier to manage and use multiple threads in your program, instead of manually creating the threads when you need them.\n\nAlso, using thread pools might increase performance as well in your program,\nespecially if your program is constantly creating threads to perform short-lived tasks.\nIn such instance, a thread pool might cause an increase in performance because you do not have be constantly\ncreating and destroying threads all the time, so you don't face a lot of the overhead involved\nin this constant process of creating and destroying threads.\n\nThe main idea behind a thread pool is to have a set of threads already created and ready to perform\ntasks at all times. You create a set of threads at the moment that your program starts, and keep\nthese threads alive while your program runs. Each of these threads will be either performing a task, or\nwaiting for a task to be assigned.\nEvery time a new task emerges in your program, this task is added to a \"queue of tasks\",\nand the moment that a thread becomes available and ready to perform a new task,\nthis thread takes the next task from the \"queue of tasks\", and it simply performs the task.\n\nThe Zig Standard Library offers a thread pool implementation on the `std.Thread.Pool` struct.\nYou create a new instance of a `Pool` object by providing a `Pool.Options` object\nas input to the `init()` method of this struct. A `Pool.Options` object, is a struct object that contains\nconfigurations for the pool of threads. The most important settings in this struct object are\nthe members `n_jobs` and `allocator`. As the name suggests, the member `allocator` should receive an allocator object,\nwhile the member `n_jobs` specifies the number of threads to be created and maintained in this pool.\n\nConsider the example exposed below, that demonstrates how can we create a new thread pool object.\nHere, we create a `Pool.Options` object that contains\na general purpose allocator object, and also, the `n_jobs` member was set to 4, which\nmeans that the thread pool will create and use 4 threads.\n\nAlso notice that the `pool` object was initially set to `undefined`. This allow us\nto initially declare the thread pool object, but not properly instantiate the\nunderlying memory of the object. You have to initially declare your thread pool object\nby using `undefined` like this, because the `init()` method of `Pool` needs\nto have an initial pointer to properly instantiate the object.\n\nSo, just remember to create your thread pool object by using `undefined`, and then,\nafter that, you call the `init()` method over the object.\nYou should also not forget to call the `deinit()` method over the thread pool\nobject, once you are done with it, to release the resources allocated for the thread pool. Otherwise, you will\nhave a memory leak in your program.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Pool = std.Thread.Pool;\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n const opt = Pool.Options{\n .n_jobs = 4,\n .allocator = allocator,\n };\n var pool: Pool = undefined;\n try pool.init(opt);\n defer pool.deinit();\n}\n```\n:::\n\n\nNow that we know how to create `Pool` objects, we have\nto understand how to assign tasks to be executed by the threads in this pool object.\nTo assign a task to be performed by a thread, we need to call the `spawn()` method\nfrom the thread pool object.\n\nThis `spawn()` method works identical to the `spawn()` method from the\n`Thread` object. The method has almost the same arguments as the previous one,\nmore precisely, we don't have to provide a `SpawnConfig` object in this case.\nBut instead of creating a new thread, this `spawn()` method from\nthe thread pool object just registers a new task in the internal \"queue of tasks\" to be performed,\nand any available thread in the pool will get this task, and it will simply perform the task.\n\nIn the example below, we are using our previous `print_id()` function once again.\nBut you may notice that the `print_id()` function is a little different this time,\nbecause now we are using `catch` instead of `try` in the `print()` call.\nCurrently, the `Pool` struct only supports functions that don't return errors\nas tasks. Thus, when assigning tasks to threads in a thread pool, it is essential to use functions\nthat don't return errors. That is why we are using `catch` here, so that the\n`print_id()` function don't return an error.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nfn print_id(id: *const u8) void {\n _ = stdout.print(\"Thread ID: {d}\\n\", .{id.*})\n catch void;\n}\nconst id1: u8 = 1;\nconst id2: u8 = 2;\ntry pool.spawn(print_id, .{&id1});\ntry pool.spawn(print_id, .{&id2});\n```\n:::\n\n\nThis limitation should probably not exist, and, in fact, it's already on the radar of the\nZig team to fix this issue, and it's being tracked in an [open issue](https://github.com/ziglang/zig/issues/18810)[^issue].\nSo, if you do need to provide a function that might return an error as the task\nto be performed by the threads in the thread pool, then, you are either limited to:\n\n- implementing your own thread pool that does not have this limitation.\n- wait for the Zig team to actually fix this issue.\n\n[^issue]: \n\n\n\n\n## Mutexes\n\nMutexes are a classic component of every thread library. In essence, a mutex is a *Mutually Exclusive Flag*, and this flag\nacts like a type of \"lock\", or as a gate keeper to a particular section of your code. Mutexes are related to thread synchronization,\nmore specifically, they prevent you from having some classic race conditions in your program,\nand, therefore, major bugs and undefined behaviour that are usually difficult to track and understand.\n\nThe main idea behind a mutex is to help us to control the execution of a particular section of the code, and to\nprevent two or more threads from executing this particular section of the code at the same time.\nMany programmers like to compare a mutex to a bathroom door (which typically has a lock).\nWhen a thread locks its own mutex object, it's like if the bathroom door was locked.\nTherefore, other people (in this case, other threads) who want to use the same bathroom at the same time\nmust be patient and simply wait for the current occupant (or thread) to unlock the door and get out of the bathroom.\n\nSome other programmers also like to explain mutexes by using the analogy of \"each person will have their turn to speak\".\nThis is the analogy used in the [*Multithreading Code* video from the Computerphile project](https://www.youtube.com/watch?v=7ENFeb-J75k&ab_channel=Computerphile)[^computerphile].\nImagine if you are in a conversation circle. There is a moderator in this circle, which is the person that decides who\nhas the right to speak at that particular moment. The moderator gives a green card (or some sort of an authorization card) to the person that\nis going to speak, and, as a result, everyone else must be silent and hear this person that has the green card.\nWhen the person finishes talking, they give the green card back to the moderator, and the moderator decides\nwho is going to talk next, and delivers the green card to that person. And the cycle goes on like this.\n\n[^computerphile]: \n\n\nA mutex acts like the moderator in this conversation circle. The mutex authorizes one single thread to execute a specific section of the code,\nand it also blocks the other threads from executing this same section of the code. If these other threads want to execute this same\npiece of the code, they are forced to wait for the the authorized thread to finish first.\nWhen the authorized thread finishes executing this code, the mutex authorizes the next thread to execute this code,\nwhile the remaining threads remain blocked. Therefore, a mutex is like a moderator that does a \"each\nthread will have their turn to execute this section of the code\" type of control.\n\n\nMutexes are especially used to prevent data race problems from happening. A data race problem happens when two or more threads\nare trying to read from or write to the same shared object at the same time.\nSo, when you have an object that is shared will all threads, and, you want to avoid two or more threads from\naccessing this same object at the same time, you can use a mutex to lock the part of the code that access this specific object.\nWhen a thread tries to run this code that is locked by a mutex, this thread stops its execution,\nand patiently waits for this section of the codebase to be unlocked to continue.\n\nNotice that mutexes are normally used to lock areas of the codebase that access/modify data that is **shared** with all threads,\ni.e., objects that are either stored in the global data section, or in the heap space of your program.\nSo mutexes are not normally used on areas of the codebase that access/modify objects that are local to the thread.\n\n\n\n### Critical section {#sec-critical-section}\n\nCritical section is a concept commonly associated with mutexes and thread synchronization.\nIn essence, a critical section is the section of the program that a thread access/modify a shared resource\n(i.e., an object, a file descriptor, something that all threads have access to). In other words,\na critical section is the section of the program where race conditions might happen, and, therefore,\nwhere undefined behaviour can be introduced into the program.\n\nWhen we use mutexes in our program, the critical section defines the area of the codebase that we want to lock.\nSo we normally lock the mutex object at the beginning of the critical section,\nand then, we unlock it at the end of the critical section.\nThe two bullet points exposed below comes from the \"Critical Section\" article from GeekFromGeeks,\nand they summarise well the role that a critical section plays in the thread synchronization problem [@geeks_critical_section].\n\n\n1. The critical section must be executed as an atomic operation, which means that once one thread or process has entered the critical section, all other threads or processes must wait until the executing thread or process exits the critical section. The purpose of synchronization mechanisms is to ensure that only one thread or process can execute the critical section at a time.\n1. The concept of a critical section is central to synchronization in computer systems, as it is necessary to ensure that multiple threads or processes can execute concurrently without interfering with each other. Various synchronization mechanisms such as semaphores, mutexes, monitors, and condition variables are used to implement critical sections and ensure that shared resources are accessed in a mutually exclusive manner.\n\n\n### Atomic operations {#sec-atomic-operation}\n\nYou will also see the term \"atomic operation\" a lot when reading about threads, race conditions and mutexes.\nIn summary, an operation is categorized as \"atomic\" when a context switch cannot occur in\nthe middle of the operation. In other words, this operation is always done from beginning to end, without interruptions\nof another process or operation in the middle of its execution phase.\n\nNot many operations today are atomic. But why do atomic operations matter here? It's because data races\n(which is a type of a race condition) cannot happen on operations that are atomic.\nSo if a particular line in your code performs an atomic operation, then this line will never\nsuffer from a data race problem. Therefore, programmers sometimes use an atomic operation\nto protect themselves from data race problems in their code.\n\nWhen you have an operation that is compiled into just one single assembly instruction, this operation might be atomic,\nbecause it's just one assembly instruction. But this is not guaranteed. This is usually true for old CPU architectures\n(such as `x86`). But nowadays, most assembly instructions in modern CPU architectures are broken down into multiple micro-tasks,\nwhich inherently makes the operation non-atomic, even if it consists of a single assembly instruction.\n\nThe Zig Standard Library offers some atomic functionality in the `std.atomic` module.\nIn this module, you will find a public and generic function called `Value()`. With this function we create an \"atomic object\", which is\na value that contains some native atomic operations, most notably, a `load()` and a `fetchAdd()` operation.\nIf you have experience with multithreading in C++, you probably have recognized this pattern. So yes, this generic\n\"atomic object\" in Zig is essentially identical to the template struct `std::atomic` from the C++ Standard Library.\nIt's important to emphasize that only primitive data types (i.e., the types presented in @sec-primitive-data-types)\nare supported by these atomic operations in Zig.\n\n\n\n\n\n### Data races and race conditions\n\nTo understand why mutexes are used, we need to understand better the problem that they seek\nto solve, which can be summarized into data race problems. A data race problem is a type of a race condition,\nwhich happens when one thread is accessing a particular memory location (i.e., a particular shared object) at the same\ntime that another thread is trying to write/save new data into this same memory location (i.e., the same shared object).\n\nWe can simply define a race condition as any type of bug in your program that is based\non a \"who gets there first\" problem. A data race problem is a type of a race condition, because it occurs when two or more parties\nare trying to read and write into the same memory location at the same time, and, therefore, the end result of this operation\ndepends completely on who gets to this memory location first.\nAs a consequence, a program that has a data race problem will likely produce a different result each time that we execute it.\n\nThus, race conditions produce undefined behaviour and unpredictability because the program produces\na different answer each time a different person gets to the target location before the others.\nAnd, we have no easy way to either predict or control who is getting to this target location first.\nIn other words, each time your program runs, you may get a different answer because a different person,\nfunction, or part of the code finishes its tasks before the others.\n\nAs an example, consider the code snippet exposed below. In this example, we create a global counter\nvariable, and we also create an `increment()` function, whose job is to just increment this global counter\nvariable in a for loop.\n\nSince the for loop iterates 1 hundred thousand times, and, we create two separate threads\nin this code example, what number do you expect to see in the final message printed to `stdout`?\nThe answer should be 2 hundred thousand. Right? Well, in theory, this program was supposed\nto print 2 hundred thousand at the end, but in practice, every time that I execute this program\nI get a different answer.\n\nIn the example exposed below, you can see that this time the end\nresult was 117254, instead of the expected 200000. The second time I executed this program,\nI got the number 108592 as the result. So the end result of this program is varying, but it never gets\nto the expected 200000 that we want.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n// Global counter variable\nvar counter: usize = 0;\n// Function to increment the counter\nfn increment() void {\n for (0..100000) |_| {\n counter += 1;\n }\n}\n\npub fn main() !void {\n const thr1 = try Thread.spawn(.{}, increment, .{});\n const thr2 = try Thread.spawn(.{}, increment, .{});\n thr1.join();\n thr2.join();\n try stdout.print(\"Couter value: {d}\\n\", .{counter});\n}\n```\n:::\n\n\n```\nCouter value: 117254\n```\n\n\nWhy this is happening? The answer is: because this program contains a data race problem.\nThis program would print the correct number 200000 if and only if the first thread finishes\nits tasks before the second thread starts to execute. But that is very unlikely to happen.\nBecause the process of creating the thread is too fast, and therefore, both threads start to execute roughly\nat the same time. If you change this code to add some nanoseconds of sleep between the first and the second calls to `spawn()`,\nyou will increase the chances of the program producing the \"correct result\".\n\nSo the data race problem happens because both threads are reading and writing to the same\nmemory location at roughly the same time. In this example, each thread is essentially performing\nthree basic operations at each iteration of the for loop, which are:\n\n1. reading the current value of `count`.\n1. incrementing this value by 1.\n1. writing the result back into `count`.\n\nIdeally, a thread B should read the value of `count`, only after the other thread A has finished\nwriting the incremented value back into the `count` object. Therefore, in the ideal scenario, which is demonstrated\nin @tbl-data-race-ideal, the threads should work in sync with each other. But the reality is that these\nthreads are out of sync, and because of that, they suffer from a data race problem, which is demonstrated\nin @tbl-data-race-not.\n\nNotice that, in the data race scenario (@tbl-data-race-not), the read performed by a thread B happens\nbefore the write operation of thread A, and that ultimately leads to wrong results at the end of the program.\nBecause when thread B reads the value of the `count` variable, thread A is still processing\nthe initial value from `count`, and has not yet written the new, incremented value back to `count`. As a result,\nthread B ends up reading the same initial (or \"old\") value from `count` instead of\nthe updated, incremented value that thread A would have written.\n\n\n::: {#tbl-data-race-ideal}\n\n| Thread 1 | Thread 2 | Integer value |\n|-------------|-------------|---------------|\n| read value | | 0 |\n| increment | | 1 |\n| write value | | 1 |\n| | read value | 1 |\n| | increment | 2 |\n| | write value | 2 |\n\n: An ideal scenario for two threads incrementing the same integer value\n:::\n\n::: {#tbl-data-race-not}\n\n| Thread 1 | Thread 2 | Integer value |\n|-------------|-------------|---------------|\n| read value | | 0 |\n| | read value | 0 |\n| increment | | 1 |\n| | increment | 1 |\n| write value | | 1 |\n| | write value | 1 |\n\n: A data race scenario when two threads are incrementing the same integer value\n:::\n\n\nIf you think about these diagrams exposed in form of tables, you will notice that they relate back to our discussion of atomic operations\nin @sec-atomic-operation. Remember, atomic operations are operations that the CPU executes\nfrom beginning to end, without interruptions from other threads or processes. So,\nthe scenario exposed in @tbl-data-race-ideal does not suffer from a data race, because\nthe operations performed by thread A are not interrupted in the middle by the operations\nfrom thread B.\n\nIf we also think about the discussion of critical section from @sec-critical-section, we can identify\nthe section that representes the critical section of the program, which is the section that is vulnerable\nto data race conditions. In this example, the critical section of the program is the line where we increment\nthe `counter` variable (`counter += 1`). So, ideally, we want to use a mutex, and lock right before this line, and then\nunlock right after this line.\n\n\n\n\n### Using mutexes in Zig\n\nNow that we know the problem that mutexes seek to solve, we can learn how to use them in Zig.\nMutexes in Zig are available through the `std.Thread.Mutex` struct from the Zig Standard Library.\nIf we take the same code from the previous example, and improve it with mutexes, to solve\nour data race problem, we get the code example below.\n\nNotice that this time, we had to alter the `increment()` function to receive a pointer to\nthe `Mutex` object as input. All that we need to do, to make this program safe against\ndata race problems, is to call the `lock()` method at the beginning of\nthe critical section, and then, call `unlock()` at the end of the critical section.\nNotice that the output of this program is now the correct number of 200000.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst Thread = std.Thread;\nconst Mutex = std.Thread.Mutex;\nvar counter: usize = 0;\nfn increment(mutex: *Mutex) void {\n for (0..100000) |_| {\n mutex.lock();\n counter += 1;\n mutex.unlock();\n }\n}\n\npub fn main() !void {\n var mutex: Mutex = .{};\n const thr1 = try Thread.spawn(.{}, increment, .{&mutex});\n const thr2 = try Thread.spawn(.{}, increment, .{&mutex});\n thr1.join();\n thr2.join();\n try stdout.print(\"Couter value: {d}\\n\", .{counter});\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nCouter value: 200000\n```\n\n\n:::\n:::\n\n\n\n\n\n## Read/Write locks\n\nMutexes are normally used when it's not always safe for two or more threads running the same\npiece of code at the same time. In contrast, read/write locks are normally used in situations\nwhere you have a mixture of scenarios, i.e., there are some pieces of the codebase that are safe\nto run in parallel, and other pieces that are not safe.\n\nFor example, suppose that you have multiple threads that uses the same shared file in the filesystem to store some configurations, or\nstatistics. If two or more threads try to read the data from this same file at the same time, nothing bad happens.\nSo this part of the codebase is perfectly safe to be executed in parallel, with multiple threads reading the same file at the same time.\n\nHowever, if two or more threads try to write data into this same file at the same time, then we cause some race condition\nproblems. So this other part of the codebase is not safe to be executed in parallel.\nMore specifically, a thread might end up writing data in the middle of the data written by the other thread.\nThis process of two or more threads writing to the same location might lead to data corruption.\nThis specific situation is usually called a *torn write*.\n\nThus, what we can extract from this example is that there are certain types of operations that cause\na race condition, but there are also other types of operations that do not cause a race condition problem.\nYou could also say that there are types of operations that are susceptible to race condition problems,\nand there are other types of operations that are not.\n\nA read/write lock is a type of lock that acknowledges the existence of this specific scenario, and you can\nuse this type of lock to control which parts of the codebase are safe to run in parallel and which parts are not.\n\n\n\n### Exclusive lock vs shared lock\n\nTherefore, a read/write lock is a little different from a mutex. Because a mutex is always an *exclusive lock*, meaning that, only\none thread is allowed to execute at all times. With an exclusive lock, the other threads are always \"excluded\",\ni.e., they are always blocked from executing. But in a read/write lock, the other threads might be authorized\nto run at the same time, depending on the type of lock that they acquire.\n\nWe have two types of locks in a read/write lock, which are: an exclusive lock and a shared lock. An exclusive lock works exactly the same\nas a mutex, while a shared lock is a lock that does not block the other threads from running at the same time.\nIn the `pthreads` C library, read/write locks are available through the `pthread_rwlock_t` C struct. With\nthis C struct, you can create:\n\n- a \"write lock\", which corresponds to an exclusive lock.\n- a \"read lock\", which corresponds to a shared lock.\n\nThe terminology might be a little different compared to Zig. But the meaning is still the same.\nTherefore, just remember this relationship, write locks are exclusive locks, while read locks are shared locks.\n\nWhen a thread tries to acquire a read lock (i.e., a shared lock), this thread gets the shared lock\nif and only if another thread does not currently hold a write lock (i.e., an exclusive lock), and also\nif there are no other threads already in the queue,\nwaiting for their turn to acquire a write lock. In other words, the thread in the queue has attempted\nto get a write lock earlier, but this thread was blocked\nbecause there was another thread running that already had a write lock. As a consequence, this thread is in the queue to get a write lock,\nand it's currently waiting for the other thread with a write lock to finish its execution.\n\nWhen a thread tries to acquire a read lock, but it fails in acquiring this read lock, either because there is\na thread with a write lock already running, or because there is a thread in the queue to get a write lock,\nthe execution of this thread is instantly blocked, i.e., paused. This thread will indefinitely attempt to get the\nread lock, and its execution will be unblocked (or unpaused) only after this thread successfully acquires the read lock.\n\nIf you think deeply about this dynamic between read locks versus write locks, you might notice that a read lock is basically a safety mechanism.\nMore specifically, it's a way for us to\nallow a particular thread to run together with the other threads only when it's safe to. In other words, if there is currently\na thread with a write lock running, then it's very likely not safe for the thread that is trying to acquire the read lock to run now.\nAs a consequence, the read lock protects this thread from running into dangerous waters, and patiently waits for the\n\"write lock\" thread to finishes its tasks before it continues.\n\nOn the other hand, if there are only \"read lock\" (i.e., \"shared lock\") threads currently running\n(i.e., not a single \"write lock\" thread currently exists), then it\nis perfectly safe for this thread that is acquiring the read lock to run in parallel with the other\nthreads. As a result, the read lock just\nallows for this thread to run together with the other threads.\n\nThus, by using read locks (shared locks) in conjunction with write locks (exclusive locks), we can control which regions or sections\nof our multithreaded code is safe to have parallelism, and which sections are not safe to have parallelism.\n\n\n\n\n\n### Using read/write locks in Zig\n\nThe Zig Standard Library supports read/write locks through the `std.Thread.RwLock` module.\nIf you want a particular thread to acquire a shared lock (i.e., a read lock), you should\ncall the `lockShared()` method from the `RwLock` object. But, if you want this thread\nto acquire an exclusive lock (i.e., a write lock) instead, then you should call the\n`lock()` method from the `RwLock` object.\n\nAs with mutexes, we also have to unlock the shared or exclusive locks that we acquire through a read/write lock object,\nonce we are at the end of our \"critical section\". If you have acquired an exclusive lock, then, you unlock\nthis exclusive lock by calling the `unlock()` method from the read/write lock object. In contrast,\nif you have acquired a shared lock instead, then, call `unlockShared()` to unlock this shared lock.\n\nAs a simple example, the snippet below creates three separate threads responsible for reading the\ncurrent value in a `counter` object, and it also creates another thread responsible for writing\nnew data into the `counter` object (incrementing it, more specifically).\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar counter: u32 = 0;\nfn reader(lock: *RwLock) !void {\n while (true) {\n lock.lockShared();\n const v: u32 = counter;\n try stdout.print(\"{d}\", .{v});\n lock.unlockShared();\n std.time.sleep(2 * std.time.ns_per_s);\n }\n}\nfn writer(lock: *RwLock) void {\n while (true) {\n lock.lock();\n counter += 1;\n lock.unlock();\n std.time.sleep(2 * std.time.ns_per_s);\n }\n}\n\npub fn main() !void {\n var lock: RwLock = .{};\n const thr1 = try Thread.spawn(.{}, reader, .{&lock});\n const thr2 = try Thread.spawn(.{}, reader, .{&lock});\n const thr3 = try Thread.spawn(.{}, reader, .{&lock});\n const wthread = try Thread.spawn(.{}, writer, .{&lock});\n\n thr1.join();\n thr2.join();\n thr3.join();\n wthread.join();\n}\n```\n:::\n\n\n\n## Yielding a thread\n\nThe `Thread` struct supports yielding through the `yield()` method.\nYielding a thread means that the execution of the thread is temporarily stopped,\nand it moves to the end of the priority queue managed by the scheduler of\nyour operating system.\n\nThat is, when you yield a thread, you are essentially saying the following to your OS:\n\"Hey! Could you please stop executing this thread for now, and comeback to continue it later?\".\nYou could also interpret this yield operation as: \"Could you please deprioritize this thread,\nto focus on doing other things instead?\".\nSo this yield operation is also a way for you\nto stop a particular thread, so that you can work and prioritize other threads instead.\n\nIt's important to say that, yielding a thread is a \"not so common\" thread operation these days.\nIn other words, not many programmers use yielding in production, simply because it's hard to use\nthis operation and make it work properly, and also, there\nare better alternatives. Most programmers prefer to use `join()` instead.\nIn fact, most of the time, when you see someone using this \"yield\" operation in some code example,\nthey are usually doing so to help debug race conditions in their applications.\nThat is, this \"yield\" operation is mostly used as a debug tool nowadays.\n\nAnyway, if you want to yield a thread, just call the `yield()` method from it, like this:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nthread.yield();\n```\n:::\n\n\n\n\n\n\n\n## Common problems in threads\n\n\n\n### Deadlocks\n\nA deadlock occurs when two or more threads are blocked forever,\nwaiting for each other to release a resource. This usually happens when multiple locks are involved,\nand the order of acquiring them is not well managed.\n\nThe code example below demonstrates a deadlock situation. We have two different threads that execute\ntwo different functions (`work1()` and `work2()`) in this example. And we also have two separate\nmutexes. If you compile and run this code example, you will notice that the program just runs indefinitely,\nwithout ending.\n\nWhen we look into the first thread, which executes the `work1()` function, we can\nnotice that this function acquires the `mut1` lock first. Because this is the first operation\nthat is executed inside this thread, which is the first thread created in the program.\nAfter that, the function sleeps for 1 second, to\nsimulate some type of work, and then, the function tries to acquire the `mut2` lock.\n\nOn the other hand, when we look into the second thread, which executes the `work2()` function,\nwe can see that this function acquires the `mut2` lock first. Because when this thread gets created and it tries\nto acquire this `mut2` lock, the first thread is still sleeping on that \"sleep 1 second\" line.\nAfter acquiring `mut2`, the `work2()` function also sleeps for 1 second, to\nsimulate some type of work, and then the function tries to acquire the `mut1` lock.\n\nThis creates a deadlock situation, because after the \"sleep for 1 second\" line in both threads,\nthread 1 is trying to acquire the `mut2` lock, but this lock is currently being used by thread 2.\nHowever, at this moment, thread 2 is also trying to acquire the `mut1` lock, which is currently\nbeing used by thread 1. Therefore, both threads end up waiting for ever. Waiting for their peer to\nfree the lock that they want to acquire.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nvar mut1: Mutex = .{}; var mut2: Mutex = .{};\nfn work1() !void {\n mut1.lock();\n std.time.sleep(1 * std.time.ns_per_s);\n mut2.lock();\n _ = try stdout.write(\"Doing some work 1\\n\");\n mut2.unlock(); mut1.unlock();\n}\n\nfn work2() !void {\n mut2.lock();\n std.time.sleep(1 * std.time.ns_per_s);\n mut1.lock();\n _ = try stdout.write(\"Doing some work 1\\n\");\n mut1.unlock(); mut2.unlock();\n}\n\npub fn main() !void {\n const thr1 = try Thread.spawn(.{}, work1, .{});\n const thr2 = try Thread.spawn(.{}, work2, .{});\n thr1.join();\n thr2.join();\n}\n```\n:::\n\n\n\n### Not calling `join()` or `detach()` {#sec-not-call-join-detach}\n\nWhen you do not call either `join()` or `detach()` over a thread, then this thread becomes a \"zombie thread\",\nbecause it does not have a clear \"return point\".\nYou could also interpret this as: \"nobody is properly responsible for managing the thread\".\nWhen we don't establish if a thread is either *joinable* or *detached*,\nnobody becomes responsible for dealing with the return value of this thread, and also,\nnobody becomes responsible for clearing (or freeing) the resources associated with this thread.\n\nYou don't want to be in this situation, so remember to always use `join()` or `detach()`\non the threads that you create. When you don't use one of these methods, we lose\ncontrol over the thread, and its resources are never freed\n(i.e., you have leaked resources in the system).\n\n\n### Cancelling or killing a particular thread\n\nWhen we think about the `pthreads` C library, there is a possible way to asynchronously kill or cancel\na thread, which is by sending a `SIGTERM` signal to the thread through the `pthread_kill()` function.\nBut canceling a thread like this is bad. It's dangerously bad. As a consequence, the Zig implementation\nof threads does not have a similar function, or, a similar way to asynchronously cancel or kill\na thread.\n\nTherefore, if you want to cancel a thread in the middle of its execution in Zig,\nthen one good strategy that you can take is to use control flow in conjunction with `join()`.\nMore specifically, you can design your thread around a while loop that is constantly\nchecking if the thread should continue running.\nIf it's time to cancel the thread, we could make the while loop break, and join the thread with the main thread\nby calling `join()`.\n\nThe code example below demonstrates to some extent this strategy.\nHere, we are using control flow to break the while loop, and exit the thread earlier than\nwhat we have initially planned to. This example also demonstrates how can we use\natomic objects in Zig with the `Value()` generic function that we have mentioned in @sec-atomic-operation.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst Thread = std.Thread;\nconst stdout = std.io.getStdOut().writer();\nvar running = std.atomic.Value(bool).init(true);\nvar counter: u64 = 0;\nfn do_more_work() void {\n std.time.sleep(2 * std.time.ns_per_s);\n}\nfn work() !void {\n while (running.load(.monotonic)) {\n for (0..10000) |_| { counter += 1; }\n if (counter < 15000) {\n _ = try stdout.write(\n \"Time to cancel the thread.\\n\"\n );\n running.store(false, .monotonic);\n } else {\n _ = try stdout.write(\"Time to do more work.\\n\");\n do_more_work();\n running.store(false, .monotonic);\n }\n }\n}\n\npub fn main() !void {\n const thread = try Thread.spawn(.{}, work, .{});\n thread.join();\n}\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\nTime to cancel the thread.\n```\n\n\n:::\n:::\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/14-zig-c-interop/execute-results/epub.json b/_freeze/Chapters/14-zig-c-interop/execute-results/epub.json deleted file mode 100644 index d2ed7502..00000000 --- a/_freeze/Chapters/14-zig-c-interop/execute-results/epub.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "hash": "7f0fb45d8337d93333a20759133b82dc", - "result": { - "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Zig interoperability with C\n\nIn this chapter, we are going to discuss the interoperability of Zig with C.\nWe have discussed in @sec-building-c-code how you can use the `zig` compiler to build C code.\nBut we haven't discussed yet how to actually use C code in Zig. In other words,\nwe haven't discussed yet how to call and use C code from Zig.\n\nThis is the main subject of this chapter.\nAlso, in our next small project in this book, we are going to use a C library in it.\nAs consequence, we will put in practice a lot of the knowledge discussed here on\nthis next project.\n\n\n## How to call C code from Zig\n\nInteroperability with C is not something new. Most high-level programming languages have FFI (foreign function interfaces),\nwhich can be used to call C code. For example, Python have Cython, R have `.Call()`, Javascript have `ccall()`, etc.\nBut Zig integrates with C in a deeper level, which affects not only the way that C code gets called, but also,\nhow this C code is compiled and incorporated into your Zig project.\n\nIn summary, Zig have great interoperability with C. If you want to call any C code from Zig,\nyou have to perform the following steps:\n\n- import a C header file into your Zig code.\n- link your Zig code with the C library.\n\n\n### Strategies to import C header files {#sec-strategy-c}\n\nUsing C code in Zig always involves performing the two steps cited above. However, when\nwe talk specifically about the first step listed above, there are currently two\ndifferent ways to perform this first step, which are:\n\n- translating the C header file into Zig code, through the `zig translate-c` command, and then, import and use the translated Zig code.\n- importing the C header file directly into your Zig module through the `@cImport()` built-in function.\n\nIf you are not familiar with `translate-c`, this is a subcommand inside the `zig` compiler that takes C files\nas input, and outputs the Zig representation of the C code present in these C files.\nIn other words, this subcommand works like a transpiler. It takes C code, and translates it into\nthe equivalent Zig code.\n\nI think it would be ok to interpret `translate-c` as a tool to generate Zig bindings\nto C code, similarly to the `rust-bindgen`[^bindgen] tool, which generates Rust FFI bindings to C code.\nBut that would not be a precise interpretation of `translate-c`. The idea behind this tool is\nto really translate the C code into Zig code.\n\n[^bindgen]: \n\nNow, on a surface level, `@cImport()` versus `translate-c` might seem like\ntwo completely different strategies. But in fact, they are effectively the exact same strategy.\nBecause, under the hood, the `@cImport()` built-in function is just a shortcut to `translate-c`.\nBoth tools use the same \"C to Zig\" translation functionality. So when you use `@cImport()`,\nyou are essentially asking the `zig` compiler to translate the C header file into Zig code, then,\nto import this Zig code into your current Zig module.\n\nAt the present moment, there is an accepted proposal at the Zig project, to move `@cImport()`\nto the Zig build system[^cimport-issue]. If this proposal is completed, then, the \"use `@cImport()`\"\nstrategy would be transformed into \"call a translate C function in your Zig build script\".\nSo, the step of translating the C code into Zig code would be moved to\nthe build script of your Zig project, and you would only need to import the translated Zig code into\nyour Zig module to start calling C code from Zig.\n\n[^cimport-issue]: \n\nIf you think about this proposal for a minute, you will understand that this is actually\na small change. I mean, the logic is the same, and the steps are still essentially the same.\nThe only difference is that one of the steps will be moved to the build script of your Zig project.\n\n\n\n### Linking Zig code with a C library {#sec-linking-c}\n\nRegardless of which of the two strategies from the previous section you choose,\nif you want to call C code from Zig, you must link your Zig code\nwith the C library that contains the C code that you want to call.\n\nIn other words, everytime you use some C code in your Zig code, **you introduce a dependency in your build process**.\nThis should come as no surprise to anyone that have any experience with C and C++.\nBecause this is no different in C. Everytime you use a C library in your C code, you also\nhave to build and link your C code with this C library that you are using.\n\nWhen we use a C library in our Zig code, the `zig` compiler needs to access the definition of the C functions that\nare being called in your Zig code. The C header file of this library provides the\ndeclarations of these C functions, but not their definitions. So, in order to access these definitions,\nthe `zig` compiler needs to build your Zig code and link it with the C library during the build process.\n\nAs we discussed across the @sec-build-system, there are different strategies to link something with a library.\nThis might involve building the C library first, and then, linking it with the Zig code. Or,\nit could also involve just the linking step, if this C library is already built and\ninstalled in your system. Anyway, if you have doubts about this, comeback to @sec-build-system.\n\n\n\n## Importing C header files {#sec-import-c-header}\n\nIn @sec-strategy-c, we have described that, currently, there are two different paths that\nyou can take to import a C header file into your Zig modules, `translate-c` or `@cImport()`.\nThis section describes each strategy separately in more details.\n\n### Strategy 1: using `translate-c`\n\nWhen we choose this strategy, we first need to use the `translate-c` tool to translate\nthe C header files that we want to use into Zig code. For example, suppose we wanted to\nuse the `fopen()` C function from the `stdio.h` C header file. We can translate the\n`stdio.h` C header file through the bash command below:\n\n```bash\nzig translate-c /usr/include/stdio.h \\\n -lc -I/usr/include \\\n -D_NO_CRT_STDIO_INLINE=1 > c.zig \\\n```\n\nNotice that, in this bash command, we are passing the necessary compiler flags (`-D` to define macros,\n`-l` to link libraries, `-I` to add an \"include path\") to compile and use the `stdio.h` header file.\nAlso notice that we are saving the results of the translation process inside a Zig module called `c.zig`.\n\nTherefore, after running this command, all we have to do is to import this `c.zig` module, and start\ncalling the C functions that you want to call from it. The example below demonstrates that.\nIt's important to remember what we've discussed in @sec-linking-c. In order to compile this\nexample you have to link this code with `libc`, by passing the flag `-lc` to the `zig` compiler.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @import(\"c.zig\");\npub fn main() !void {\n const x: f32 = 1772.94122;\n _ = c.printf(\"%.3f\\n\", x);\n}\n```\n:::\n\n\n\n```\n1772.941\n```\n\n\n### Strategy 2: using `@cImport()`\n\nTo import a C header file into our Zig code, we can use the built-in functions `@cInclude()` and `@cImport()`.\nInside the `@cImport()` function, we open a block (with a pair of curly braces). Inside this block\nwe can (if we need to) include multiple `@cDefine()` calls to define C macros when including this specific C header file.\nBut for the most part, you will probably need to use just a single call inside this block,\nwhich is a call to `@cInclude()`.\n\nThis `@cInclude()` function is equivalent to the `#include` statement in C.\nYou provide the name of the C header that you want to include as input to this `@cInclude()` function,\nthen, in conjunction with `@cImport()`, it will perform the necessary steps\nto include this C header file into your Zig code.\n\nYou should bind the result of `@cImport()` to a constant object, pretty much like you would do with\n`@import()`. You just assign the result to a constant object in your\nZig code, and, as consequence, all C functions, C structs, C macros, etc. that are defined inside the\nC header files will be available through this constant object.\n\nLook at the code example below, where we are importing the Standard I/O C Library (`stdio.h`),\nand calling the `printf()`[^printf] C function. Notice that we have also used in this example the C function `powf()`[^powf],\nwhich comes from the C Math Library (`math.h`).\nIn order to compile this example, you have to link this Zig code with both\nthe C Standard Library and the C Math Library, by passing the flags `-lc` and `-lm`\nto the `zig` compiler.\n\n[^printf]: \n[^powf]: \n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cDefine(\"_NO_CRT_STDIO_INLINE\", \"1\");\n @cInclude(\"stdio.h\");\n @cInclude(\"math.h\");\n});\n\npub fn main() !void {\n const x: f32 = 15.2;\n const y = c.powf(x, @as(f32, 2.6));\n _ = c.printf(\"%.3f\\n\", y);\n}\n```\n:::\n\n\n\n```\n1182.478\n```\n\n\n## About passing Zig values to C functions {#sec-zig-obj-to-c}\n\nZig objects have some intrinsic differences between their C equivalents.\nProbably the most noticeable one is the difference between C strings and Zig strings,\nwhich I described in @sec-zig-strings.\nZig strings are objects that contains both an array of arbitrary bytes and a length value.\nOn the other hand, a C string is usually just a pointer to a null-terminated array of arbitrary bytes.\n\nBecause of these intrinsic differences, in some specific cases, you cannot pass Zig objects directly\nas inputs to C functions before you convert them into C compatible values. However, in some other cases,\nyou are allowed to pass Zig objects and Zig literal values directly as inputs to C functions,\nand everything will work just fine, because the `zig` compiler will handle everything for you.\n\nSo we have two different scenarios being described here. Let's call them \"auto-conversion\" and \"need-conversion\".\nThe \"auto-conversion\" scenario is when the `zig` compiler handles everything for you, and automatically convert your\nZig objects/values into C compatible values. In contrast,\nthe \"need-conversion\" scenario is when you, the programmer, have the responsibility of converting\nthat Zig object into a C compatible value, before passing it to C code.\n\nThere is also a third scenario that is not being described here, which is when you create a C object, or, a C struct, or\na C compatible value in your Zig code, and you pass this C object/value as input to a C function in your Zig code.\nThis scenario will be described later in @sec-c-inputs. In this section, we are focused on the scenarios where\nwe are passing Zig objects/values to C code, instead of C objects/values being passed to C code.\n\n\n### The \"auto-conversion\" scenario\n\nAn \"auto-conversion\" scenario is when the `zig` compiler automatically converts our Zig objects into\nC compatible values for us. This specific scenario happens mostly in two instances:\n\n- with string literal values;\n- with any of the primitive data types that were introduced in @sec-primitive-data-types.\n\nWhen we think about the second instance described above, the `zig` compiler does automatically\nconvert any of the primitive data types into their C equivalents, because the compiler knows how\nto properly convert a `i16` into a `signed short`, or, a `u8` into a `unsigned char`, etc.\nNow, when we think about string literal values, they can be automatically\nconverted into C strings as well, especially because the `zig` compiler does not forces\na specific Zig data type into a string literal at first glance, unless you store this\nstring literal into a Zig object, and explicitly annotate the data type of this object.\n\nThus, with string literal values, the `zig` compiler has more freedom to infer which is the appropriate data type\nto be used in each situation. You could say that the string literal value \"inherits its data type\" depending on the context that\nit's used in. Most of the times, this data type is going to be the type that we commonly associate with Zig strings (`[]const u8`).\nBut it might be a different type depending on the situation. When the `zig` compiler detects that you are providing\na string literal value as input to some C function, the compiler automatically interprets this string\nliteral as a C string value.\n\nAs an example, look at the code exposed below. Here we are using\nthe `fopen()` C function to simply open and close a file. If you do not know how this `fopen()`\nfunction works in C, it takes two C strings as input. But in this code example below, we are passing some\nstring literals written in our Zig code directly as inputs to this `fopen()` C function.\n\nIn other words, we are not doing any conversion from a Zig string to a C string.\nWe are just passing the Zig string literals directly as inputs to the C function. And it works just fine!\nBecause the compiler interprets the string `\"foo.txt\"` as a C string given the current context.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cDefine(\"_NO_CRT_STDIO_INLINE\", \"1\");\n @cInclude(\"stdio.h\");\n});\n\npub fn main() !void {\n const file = c.fopen(\"foo.txt\", \"rb\");\n if (file == null) {\n @panic(\"Could not open file!\");\n }\n if (c.fclose(file) != 0) {\n return error.CouldNotCloseFileDescriptor;\n }\n}\n```\n:::\n\n\n\nLet's make some experiments, by writing the same code in different manners, and we\nsee how this affects the program. As a starting point, let's store the `\"foo.txt\"` string inside\na Zig object, like the `path` object below, and then, we pass this Zig object as input to the `fopen()` C function.\n\nIf we do this, the program still compiles and runs successfully. Notice that I have omitted most of the code in this example below.\nThis is just for brevity reasons, because the remainder of the program is still the same.\nThe only difference between this example and the previous one is just these two lines exposed below.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path = \"foo.txt\";\n const file = c.fopen(path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\nNow, what happens if you give an explicit data type to the `path` object? Well, if I force\nthe `zig` compiler to interpret this `path` object as a Zig string object,\nby annotating the `path` object with the data type `[]const u8`, then, I actually get a compile error\nas demonstrated below. We get this compile error because now I'm forcing the `zig` compiler\nto interpret `path` as a Zig string object.\n\nAccording to the error message, the `fopen()` C function was expecting to receive an\ninput value of type `[*c]const u8` (C string) instead of a value of type `[]const u8` (Zig string).\nIn more details, the type `[*c]const u8` is actually the Zig type representation of a C string.\nThe `[*c]` portion of this type identifies a C pointer. So, this Zig type essentially means: a C pointer to an array (`[*c]`) of\nconstant bytes (`const u8`).\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const file = c.fopen(path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n```\nt.zig:2:7 error: expected type '[*c]const u8', found '[]const u8':\n const file = c.fopen(path, \"rb\");\n ^~~~\n```\n\nTherefore, when we talk exclusively about string literal values, as long as you don't give an\nexplicit data type to these string literal values, the `zig` compiler should be capable of automatically\nconverting them into C strings as needed.\n\nBut what about using one of the primitive data types that were introduced in @sec-primitive-data-types?\nLet's take code exposed below as an example of that. Here, we are giving some float literal values as input\nto the C function `powf()`. Notice that this code example compiles and runs successfully.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst cmath = @cImport({\n @cInclude(\"math.h\");\n});\n\npub fn main() !void {\n const y = cmath.powf(15.68, 2.32);\n try stdout.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n```\n593.2023\n```\n\nOnce again, because the `zig` compiler does not associate a specific data type with the literal values\n`15.68` and `2.32` at first glance, the compiler can automatically convert these values\ninto their C `float` (or `double`) equivalents, before it passes to the `powf()` C function.\nNow, even if I give an explicit Zig data type to these literal values, by storing them into a Zig object,\nand explicit annotating the type of these objects, the code still compiles and runs successfully.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const x: f32 = 15.68;\n const y = cmath.powf(x, 2.32);\n // The remainder of the program\n```\n:::\n\n\n\n```\n593.2023\n```\n\n\n\n### The \"need-conversion\" scenario\n\nA \"need-conversion\" scenario is when we need to manually convert our Zig objects into C compatible values\nbefore passing them as input to C functions. You will fall in this scenario, when passing Zig string objects\nto C functions.\n\nWe have already seen this specific circumstance in the last `fopen()` example,\nwhich is reproduced below. You can see in this example, that we have given an explicit Zig data type\n(`[]const u8`) to our `path` object, and, as a consequence of that, we have forced the `zig` compiler\nto see this `path` object, as a Zig string object. Therefore, we need now to manually convert\nthis `path` object into a C string before we pass it to `fopen()`.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const file = c.fopen(path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n```\nt.zig:10:26: error: expected type '[*c]const u8', found '[]const u8'\n const file = c.fopen(path, \"rb\");\n ^~~~\n```\n\n\nThere are different ways to convert a Zig string object into a C string.\nOne way to solve this problem is to provide the pointer to the underlying array\nof bytes, instead of providing the Zig object directly as input.\nYou can access this pointer by using the `ptr` property of the Zig string object.\n\nThe code example below demonstrates this strategy. Notice that, by giving the\npointer to the underlying array in `path` through the `ptr` property, we get no compile errors as result\nwhile using the `fopen()` C function.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const file = c.fopen(path.ptr, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\nThis strategy works because this pointer to the underlying array found in the `ptr` property,\nis semantically identical to a C pointer to an array of bytes, i.e., a C object of type `*unsigned char`.\nThis is why this option also solves the problem of converting the Zig string into a C string.\n\nAnother option is to explicitly convert the Zig string object into a C pointer by using the\nbuilt-in function `@ptrCast()`. With this function we can convert\nan object of type `[]const u8` into an object of type `[*c]const u8`.\nAs I described at the previous section, the `[*c]` portion of the type\nmeans that it's a C pointer. This strategy is not-recommended. But it's\nuseful to demonstrate the use of `@ptrCast()`.\n\nYou may recall of `@as()` and `@ptrCast()` from @sec-type-cast. Just as a recap,\nthe `@as()` built-in function is used to explicitly convert (or cast) a Zig value\nfrom a type \"x\" into a value of type \"y\". But in our case here, we are converting\na pointer object. Everytime a pointer is involved in some \"type casting operation\" in Zig,\nthe `@ptrCast()` function is involved.\n\nIn the example below, we are using this function to cast our `path` object\ninto a C pointer to an array of bytes. Then, we pass this C pointer as input\nto the `fopen()` function. Notice that this code example compiles successfully\nwith no errors.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const c_path: [*c]const u8 = @ptrCast(path);\n const file = c.fopen(c_path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\n\n## Creating C objects in Zig {#sec-c-inputs}\n\nCreating C objects, or, in other words, creating instances of C structs in your Zig code\nis actually something quite easy to do. You first need to import the C header file (like I described in @sec-import-c-header) that defines\nthe C struct that you are trying to instantiate in your Zig code. After that, you can just\ncreate a new object in your Zig code, and annotate it with the data type of the C struct.\n\nFor example, suppose we have a C header file called `user.h`, and that this header file is declaring a new struct named `User`.\nThis C header file is exposed below:\n\n```c\n#include \n\ntypedef struct {\n uint64_t id;\n char* name;\n} User;\n```\n\nThis `User` C struct have two distinct fields, or two struct members, named `id` and `name`.\nThe field `id` is an unsigned 64-bit integer value, while the field `name` is just a standard C string.\nNow, suppose that I want to create an instance of this `User` struct in my Zig code.\nI can do that by importing this `user.h` header file into my Zig code, and creating\na new object with type `User`. These steps are reproduced in the code example below.\n\nNotice that I have used the keyword `undefined` in this example. This allows me to\ncreate the `new_user` object without the need to provide an initial value to the object.\nAs consequence, the underlying memory associated with this `new_user` object is uninitialized,\ni.e., the memory is currently populated with \"garbage\" values.\nThus, this expression have the exact same effect of the expression `User new_user;` in C,\nwhich means \"declare a new object named `new_user` of type `User`\".\n\nIt's our responsibility to properly initialize this memory associated with this `new_user` object,\nby assigning valid values to the members (or the fields) of the C struct. In the example below,\nI'm assigning the integer 1 to the member `id`. I am also saving the string `\"pedropark99\"` into the member `name`.\nNotice in this example that I manually add the null character (zero byte) to the end of the allocated array\nfor this string. This null character marks the end of the array in C.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst c = @cImport({\n @cInclude(\"user.h\");\n});\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n\n var new_user: c.User = undefined;\n new_user.id = 1;\n var user_name = try allocator.alloc(u8, 12);\n defer allocator.free(user_name);\n @memcpy(user_name[0..(user_name.len - 1)], \"pedropark99\");\n user_name[user_name.len - 1] = 0;\n new_user.name = user_name.ptr;\n}\n```\n:::\n\n\n\nSo, in this example above, we are manually initializing each field of the C struct.\nWe could say that, in this instance, we are \"manually instantiating\nthe C struct object\". However, when we use C libraries in our Zig code, we rarely need\nto manually instantiate the C structs like that. Only because C libraries\nusually provide a \"constructor function\" in their public APIs. As consequence, we normally rely on\nthese constructor functions to properly initialize the C structs, and\nthe struct fields for us.\n\nFor example, consider the Harfbuzz C library. This a text shaping C library,\nand it works around a \"buffer object\", or, more specifically, an instance of\nthe C struct `hb_buffer_t`. Therefore, we need to create an instance of\nthis C struct if we want to use this C library. Luckily, this library offers\nthe function `hb_buffer_create()`, which we can use to create such object.\nSo the Zig code necessary to create such object would probably look something like this:\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cInclude(\"hb.h\");\n});\nvar buf: c.hb_buffer_t = c.hb_buffer_create();\n// Do stuff with the \"buffer object\"\n```\n:::\n\n\n\nTherefore, we do not need to manually create an instance of the C struct\n`hb_buffer_t` here, and manually assign valid values to each field in this C struct.\nBecause the constructor function `hb_buffer_create()` is doing this heavy job for us.\n\nSince this `buf` object, and also, the `new_user` object from previous examples, are instances of C structs, these\nobjects are by themselves C compatible values. They are C objects defined in our Zig code. As consequence,\nyou can freely pass these objects as input to any C function that expects to receive this type\nof C struct as input. You do not need to use any special syntax, or, to convert them in\nany special manner to use them in C code. This is how we create and use C objects in our Zig code.\n\n\n\n## Passing C structs across Zig functions {#sec-pass-c-structs}\n\nNow that we have learned how to create/declare C objects in our Zig code, we\nneed to learn how to pass these C objects as inputs to Zig functions.\nAs I described in @sec-c-inputs, we can freely pass these C objects as inputs to C code\nthat we call from our Zig code. But what about passing these C objects to Zig functions?\n\nIn essence, this specific case requires one small adjustment in the Zig function declaration.\nAll you need to do, is to make sure that you pass your C object *by reference* to the function,\ninstead of passing it *by value*. To do that, you have to annotate the data type of the function argument\nthat is receiving this C object as \"a pointer to the C struct\", instead of annotating it as \"an instance of the C struct\".\n\nLet's consider the C struct `User` from the `user.h` C header file that we have used in @sec-c-inputs.\nNow, consider that we want to create a Zig function that sets the value of the `id` field\nin this C struct, like the `set_user_id()` function declared below.\nNotice that the `user` argument in this function is annotated as a pointer (`*`) to a `c.User` object.\n\nTherefore, all you have to do when passing C objects to Zig functions, is to add `*` to the\ndata type of the function argument that is receiving the C object. This will make sure that\nthe C object is passed *by reference* to the function.\n\nBecause we have transformed the function argument into a pointer,\neverytime that you have to access the value pointed by this input pointer inside the function body, for whatever reason (e.g. you want\nto read, update, or delete this value), you have to dereference the pointer with the `.*` syntax that we\nlearned from @sec-pointer. Notice that the `set_user_id()` function is using this syntax to alter\nthe value in the `id` field of the `User` struct pointed by the input pointer.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst c = @cImport({\n @cInclude(\"user.h\");\n});\nfn set_user_id(id: u64, user: *c.User) void {\n user.*.id = id;\n}\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n\n var new_user: c.User = undefined;\n new_user.id = 1;\n var user_name = try allocator.alloc(u8, 12);\n defer allocator.free(user_name);\n @memcpy(user_name[0..(user_name.len - 1)], \"pedropark99\");\n user_name[user_name.len - 1] = 0;\n new_user.name = user_name.ptr;\n\n set_user_id(25, &new_user);\n try stdout.print(\"New ID: {any}\\n\", .{new_user.id});\n}\n```\n:::\n\n\n\n```\nNew ID: 25\n```\n", - "supporting": [ - "14-zig-c-interop_files" - ], - "filters": [ - "rmarkdown/pagebreak.lua" - ], - "includes": {}, - "engineDependencies": { - "knitr": [ - "{\"type\":\"list\",\"attributes\":{},\"value\":[]}" - ] - }, - "preserve": null, - "postProcess": false - } -} \ No newline at end of file diff --git a/_freeze/Chapters/14-zig-c-interop/execute-results/html.json b/_freeze/Chapters/14-zig-c-interop/execute-results/html.json index fe46362b..23876574 100644 --- a/_freeze/Chapters/14-zig-c-interop/execute-results/html.json +++ b/_freeze/Chapters/14-zig-c-interop/execute-results/html.json @@ -2,10 +2,8 @@ "hash": "7f0fb45d8337d93333a20759133b82dc", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Zig interoperability with C\n\nIn this chapter, we are going to discuss the interoperability of Zig with C.\nWe have discussed in @sec-building-c-code how you can use the `zig` compiler to build C code.\nBut we haven't discussed yet how to actually use C code in Zig. In other words,\nwe haven't discussed yet how to call and use C code from Zig.\n\nThis is the main subject of this chapter.\nAlso, in our next small project in this book, we are going to use a C library in it.\nAs consequence, we will put in practice a lot of the knowledge discussed here on\nthis next project.\n\n\n## How to call C code from Zig\n\nInteroperability with C is not something new. Most high-level programming languages have FFI (foreign function interfaces),\nwhich can be used to call C code. For example, Python have Cython, R have `.Call()`, Javascript have `ccall()`, etc.\nBut Zig integrates with C in a deeper level, which affects not only the way that C code gets called, but also,\nhow this C code is compiled and incorporated into your Zig project.\n\nIn summary, Zig have great interoperability with C. If you want to call any C code from Zig,\nyou have to perform the following steps:\n\n- import a C header file into your Zig code.\n- link your Zig code with the C library.\n\n\n### Strategies to import C header files {#sec-strategy-c}\n\nUsing C code in Zig always involves performing the two steps cited above. However, when\nwe talk specifically about the first step listed above, there are currently two\ndifferent ways to perform this first step, which are:\n\n- translating the C header file into Zig code, through the `zig translate-c` command, and then, import and use the translated Zig code.\n- importing the C header file directly into your Zig module through the `@cImport()` built-in function.\n\nIf you are not familiar with `translate-c`, this is a subcommand inside the `zig` compiler that takes C files\nas input, and outputs the Zig representation of the C code present in these C files.\nIn other words, this subcommand works like a transpiler. It takes C code, and translates it into\nthe equivalent Zig code.\n\nI think it would be ok to interpret `translate-c` as a tool to generate Zig bindings\nto C code, similarly to the `rust-bindgen`[^bindgen] tool, which generates Rust FFI bindings to C code.\nBut that would not be a precise interpretation of `translate-c`. The idea behind this tool is\nto really translate the C code into Zig code.\n\n[^bindgen]: \n\nNow, on a surface level, `@cImport()` versus `translate-c` might seem like\ntwo completely different strategies. But in fact, they are effectively the exact same strategy.\nBecause, under the hood, the `@cImport()` built-in function is just a shortcut to `translate-c`.\nBoth tools use the same \"C to Zig\" translation functionality. So when you use `@cImport()`,\nyou are essentially asking the `zig` compiler to translate the C header file into Zig code, then,\nto import this Zig code into your current Zig module.\n\nAt the present moment, there is an accepted proposal at the Zig project, to move `@cImport()`\nto the Zig build system[^cimport-issue]. If this proposal is completed, then, the \"use `@cImport()`\"\nstrategy would be transformed into \"call a translate C function in your Zig build script\".\nSo, the step of translating the C code into Zig code would be moved to\nthe build script of your Zig project, and you would only need to import the translated Zig code into\nyour Zig module to start calling C code from Zig.\n\n[^cimport-issue]: \n\nIf you think about this proposal for a minute, you will understand that this is actually\na small change. I mean, the logic is the same, and the steps are still essentially the same.\nThe only difference is that one of the steps will be moved to the build script of your Zig project.\n\n\n\n### Linking Zig code with a C library {#sec-linking-c}\n\nRegardless of which of the two strategies from the previous section you choose,\nif you want to call C code from Zig, you must link your Zig code\nwith the C library that contains the C code that you want to call.\n\nIn other words, everytime you use some C code in your Zig code, **you introduce a dependency in your build process**.\nThis should come as no surprise to anyone that have any experience with C and C++.\nBecause this is no different in C. Everytime you use a C library in your C code, you also\nhave to build and link your C code with this C library that you are using.\n\nWhen we use a C library in our Zig code, the `zig` compiler needs to access the definition of the C functions that\nare being called in your Zig code. The C header file of this library provides the\ndeclarations of these C functions, but not their definitions. So, in order to access these definitions,\nthe `zig` compiler needs to build your Zig code and link it with the C library during the build process.\n\nAs we discussed across the @sec-build-system, there are different strategies to link something with a library.\nThis might involve building the C library first, and then, linking it with the Zig code. Or,\nit could also involve just the linking step, if this C library is already built and\ninstalled in your system. Anyway, if you have doubts about this, comeback to @sec-build-system.\n\n\n\n## Importing C header files {#sec-import-c-header}\n\nIn @sec-strategy-c, we have described that, currently, there are two different paths that\nyou can take to import a C header file into your Zig modules, `translate-c` or `@cImport()`.\nThis section describes each strategy separately in more details.\n\n### Strategy 1: using `translate-c`\n\nWhen we choose this strategy, we first need to use the `translate-c` tool to translate\nthe C header files that we want to use into Zig code. For example, suppose we wanted to\nuse the `fopen()` C function from the `stdio.h` C header file. We can translate the\n`stdio.h` C header file through the bash command below:\n\n```bash\nzig translate-c /usr/include/stdio.h \\\n -lc -I/usr/include \\\n -D_NO_CRT_STDIO_INLINE=1 > c.zig \\\n```\n\nNotice that, in this bash command, we are passing the necessary compiler flags (`-D` to define macros,\n`-l` to link libraries, `-I` to add an \"include path\") to compile and use the `stdio.h` header file.\nAlso notice that we are saving the results of the translation process inside a Zig module called `c.zig`.\n\nTherefore, after running this command, all we have to do is to import this `c.zig` module, and start\ncalling the C functions that you want to call from it. The example below demonstrates that.\nIt's important to remember what we've discussed in @sec-linking-c. In order to compile this\nexample you have to link this code with `libc`, by passing the flag `-lc` to the `zig` compiler.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @import(\"c.zig\");\npub fn main() !void {\n const x: f32 = 1772.94122;\n _ = c.printf(\"%.3f\\n\", x);\n}\n```\n:::\n\n\n\n\n```\n1772.941\n```\n\n\n### Strategy 2: using `@cImport()`\n\nTo import a C header file into our Zig code, we can use the built-in functions `@cInclude()` and `@cImport()`.\nInside the `@cImport()` function, we open a block (with a pair of curly braces). Inside this block\nwe can (if we need to) include multiple `@cDefine()` calls to define C macros when including this specific C header file.\nBut for the most part, you will probably need to use just a single call inside this block,\nwhich is a call to `@cInclude()`.\n\nThis `@cInclude()` function is equivalent to the `#include` statement in C.\nYou provide the name of the C header that you want to include as input to this `@cInclude()` function,\nthen, in conjunction with `@cImport()`, it will perform the necessary steps\nto include this C header file into your Zig code.\n\nYou should bind the result of `@cImport()` to a constant object, pretty much like you would do with\n`@import()`. You just assign the result to a constant object in your\nZig code, and, as consequence, all C functions, C structs, C macros, etc. that are defined inside the\nC header files will be available through this constant object.\n\nLook at the code example below, where we are importing the Standard I/O C Library (`stdio.h`),\nand calling the `printf()`[^printf] C function. Notice that we have also used in this example the C function `powf()`[^powf],\nwhich comes from the C Math Library (`math.h`).\nIn order to compile this example, you have to link this Zig code with both\nthe C Standard Library and the C Math Library, by passing the flags `-lc` and `-lm`\nto the `zig` compiler.\n\n[^printf]: \n[^powf]: \n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cDefine(\"_NO_CRT_STDIO_INLINE\", \"1\");\n @cInclude(\"stdio.h\");\n @cInclude(\"math.h\");\n});\n\npub fn main() !void {\n const x: f32 = 15.2;\n const y = c.powf(x, @as(f32, 2.6));\n _ = c.printf(\"%.3f\\n\", y);\n}\n```\n:::\n\n\n\n\n```\n1182.478\n```\n\n\n## About passing Zig values to C functions {#sec-zig-obj-to-c}\n\nZig objects have some intrinsic differences between their C equivalents.\nProbably the most noticeable one is the difference between C strings and Zig strings,\nwhich I described in @sec-zig-strings.\nZig strings are objects that contains both an array of arbitrary bytes and a length value.\nOn the other hand, a C string is usually just a pointer to a null-terminated array of arbitrary bytes.\n\nBecause of these intrinsic differences, in some specific cases, you cannot pass Zig objects directly\nas inputs to C functions before you convert them into C compatible values. However, in some other cases,\nyou are allowed to pass Zig objects and Zig literal values directly as inputs to C functions,\nand everything will work just fine, because the `zig` compiler will handle everything for you.\n\nSo we have two different scenarios being described here. Let's call them \"auto-conversion\" and \"need-conversion\".\nThe \"auto-conversion\" scenario is when the `zig` compiler handles everything for you, and automatically convert your\nZig objects/values into C compatible values. In contrast,\nthe \"need-conversion\" scenario is when you, the programmer, have the responsibility of converting\nthat Zig object into a C compatible value, before passing it to C code.\n\nThere is also a third scenario that is not being described here, which is when you create a C object, or, a C struct, or\na C compatible value in your Zig code, and you pass this C object/value as input to a C function in your Zig code.\nThis scenario will be described later in @sec-c-inputs. In this section, we are focused on the scenarios where\nwe are passing Zig objects/values to C code, instead of C objects/values being passed to C code.\n\n\n### The \"auto-conversion\" scenario\n\nAn \"auto-conversion\" scenario is when the `zig` compiler automatically converts our Zig objects into\nC compatible values for us. This specific scenario happens mostly in two instances:\n\n- with string literal values;\n- with any of the primitive data types that were introduced in @sec-primitive-data-types.\n\nWhen we think about the second instance described above, the `zig` compiler does automatically\nconvert any of the primitive data types into their C equivalents, because the compiler knows how\nto properly convert a `i16` into a `signed short`, or, a `u8` into a `unsigned char`, etc.\nNow, when we think about string literal values, they can be automatically\nconverted into C strings as well, especially because the `zig` compiler does not forces\na specific Zig data type into a string literal at first glance, unless you store this\nstring literal into a Zig object, and explicitly annotate the data type of this object.\n\nThus, with string literal values, the `zig` compiler has more freedom to infer which is the appropriate data type\nto be used in each situation. You could say that the string literal value \"inherits its data type\" depending on the context that\nit's used in. Most of the times, this data type is going to be the type that we commonly associate with Zig strings (`[]const u8`).\nBut it might be a different type depending on the situation. When the `zig` compiler detects that you are providing\na string literal value as input to some C function, the compiler automatically interprets this string\nliteral as a C string value.\n\nAs an example, look at the code exposed below. Here we are using\nthe `fopen()` C function to simply open and close a file. If you do not know how this `fopen()`\nfunction works in C, it takes two C strings as input. But in this code example below, we are passing some\nstring literals written in our Zig code directly as inputs to this `fopen()` C function.\n\nIn other words, we are not doing any conversion from a Zig string to a C string.\nWe are just passing the Zig string literals directly as inputs to the C function. And it works just fine!\nBecause the compiler interprets the string `\"foo.txt\"` as a C string given the current context.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cDefine(\"_NO_CRT_STDIO_INLINE\", \"1\");\n @cInclude(\"stdio.h\");\n});\n\npub fn main() !void {\n const file = c.fopen(\"foo.txt\", \"rb\");\n if (file == null) {\n @panic(\"Could not open file!\");\n }\n if (c.fclose(file) != 0) {\n return error.CouldNotCloseFileDescriptor;\n }\n}\n```\n:::\n\n\n\n\nLet's make some experiments, by writing the same code in different manners, and we\nsee how this affects the program. As a starting point, let's store the `\"foo.txt\"` string inside\na Zig object, like the `path` object below, and then, we pass this Zig object as input to the `fopen()` C function.\n\nIf we do this, the program still compiles and runs successfully. Notice that I have omitted most of the code in this example below.\nThis is just for brevity reasons, because the remainder of the program is still the same.\nThe only difference between this example and the previous one is just these two lines exposed below.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path = \"foo.txt\";\n const file = c.fopen(path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\nNow, what happens if you give an explicit data type to the `path` object? Well, if I force\nthe `zig` compiler to interpret this `path` object as a Zig string object,\nby annotating the `path` object with the data type `[]const u8`, then, I actually get a compile error\nas demonstrated below. We get this compile error because now I'm forcing the `zig` compiler\nto interpret `path` as a Zig string object.\n\nAccording to the error message, the `fopen()` C function was expecting to receive an\ninput value of type `[*c]const u8` (C string) instead of a value of type `[]const u8` (Zig string).\nIn more details, the type `[*c]const u8` is actually the Zig type representation of a C string.\nThe `[*c]` portion of this type identifies a C pointer. So, this Zig type essentially means: a C pointer to an array (`[*c]`) of\nconstant bytes (`const u8`).\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const file = c.fopen(path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\n```\nt.zig:2:7 error: expected type '[*c]const u8', found '[]const u8':\n const file = c.fopen(path, \"rb\");\n ^~~~\n```\n\nTherefore, when we talk exclusively about string literal values, as long as you don't give an\nexplicit data type to these string literal values, the `zig` compiler should be capable of automatically\nconverting them into C strings as needed.\n\nBut what about using one of the primitive data types that were introduced in @sec-primitive-data-types?\nLet's take code exposed below as an example of that. Here, we are giving some float literal values as input\nto the C function `powf()`. Notice that this code example compiles and runs successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst cmath = @cImport({\n @cInclude(\"math.h\");\n});\n\npub fn main() !void {\n const y = cmath.powf(15.68, 2.32);\n try stdout.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n\n\n```\n593.2023\n```\n\nOnce again, because the `zig` compiler does not associate a specific data type with the literal values\n`15.68` and `2.32` at first glance, the compiler can automatically convert these values\ninto their C `float` (or `double`) equivalents, before it passes to the `powf()` C function.\nNow, even if I give an explicit Zig data type to these literal values, by storing them into a Zig object,\nand explicit annotating the type of these objects, the code still compiles and runs successfully.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const x: f32 = 15.68;\n const y = cmath.powf(x, 2.32);\n // The remainder of the program\n```\n:::\n\n\n\n\n```\n593.2023\n```\n\n\n\n### The \"need-conversion\" scenario\n\nA \"need-conversion\" scenario is when we need to manually convert our Zig objects into C compatible values\nbefore passing them as input to C functions. You will fall in this scenario, when passing Zig string objects\nto C functions.\n\nWe have already seen this specific circumstance in the last `fopen()` example,\nwhich is reproduced below. You can see in this example, that we have given an explicit Zig data type\n(`[]const u8`) to our `path` object, and, as a consequence of that, we have forced the `zig` compiler\nto see this `path` object, as a Zig string object. Therefore, we need now to manually convert\nthis `path` object into a C string before we pass it to `fopen()`.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const file = c.fopen(path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\n```\nt.zig:10:26: error: expected type '[*c]const u8', found '[]const u8'\n const file = c.fopen(path, \"rb\");\n ^~~~\n```\n\n\nThere are different ways to convert a Zig string object into a C string.\nOne way to solve this problem is to provide the pointer to the underlying array\nof bytes, instead of providing the Zig object directly as input.\nYou can access this pointer by using the `ptr` property of the Zig string object.\n\nThe code example below demonstrates this strategy. Notice that, by giving the\npointer to the underlying array in `path` through the `ptr` property, we get no compile errors as result\nwhile using the `fopen()` C function.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const file = c.fopen(path.ptr, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\nThis strategy works because this pointer to the underlying array found in the `ptr` property,\nis semantically identical to a C pointer to an array of bytes, i.e., a C object of type `*unsigned char`.\nThis is why this option also solves the problem of converting the Zig string into a C string.\n\nAnother option is to explicitly convert the Zig string object into a C pointer by using the\nbuilt-in function `@ptrCast()`. With this function we can convert\nan object of type `[]const u8` into an object of type `[*c]const u8`.\nAs I described at the previous section, the `[*c]` portion of the type\nmeans that it's a C pointer. This strategy is not-recommended. But it's\nuseful to demonstrate the use of `@ptrCast()`.\n\nYou may recall of `@as()` and `@ptrCast()` from @sec-type-cast. Just as a recap,\nthe `@as()` built-in function is used to explicitly convert (or cast) a Zig value\nfrom a type \"x\" into a value of type \"y\". But in our case here, we are converting\na pointer object. Everytime a pointer is involved in some \"type casting operation\" in Zig,\nthe `@ptrCast()` function is involved.\n\nIn the example below, we are using this function to cast our `path` object\ninto a C pointer to an array of bytes. Then, we pass this C pointer as input\nto the `fopen()` function. Notice that this code example compiles successfully\nwith no errors.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const c_path: [*c]const u8 = @ptrCast(path);\n const file = c.fopen(c_path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\n\n\n## Creating C objects in Zig {#sec-c-inputs}\n\nCreating C objects, or, in other words, creating instances of C structs in your Zig code\nis actually something quite easy to do. You first need to import the C header file (like I described in @sec-import-c-header) that defines\nthe C struct that you are trying to instantiate in your Zig code. After that, you can just\ncreate a new object in your Zig code, and annotate it with the data type of the C struct.\n\nFor example, suppose we have a C header file called `user.h`, and that this header file is declaring a new struct named `User`.\nThis C header file is exposed below:\n\n```c\n#include \n\ntypedef struct {\n uint64_t id;\n char* name;\n} User;\n```\n\nThis `User` C struct have two distinct fields, or two struct members, named `id` and `name`.\nThe field `id` is an unsigned 64-bit integer value, while the field `name` is just a standard C string.\nNow, suppose that I want to create an instance of this `User` struct in my Zig code.\nI can do that by importing this `user.h` header file into my Zig code, and creating\na new object with type `User`. These steps are reproduced in the code example below.\n\nNotice that I have used the keyword `undefined` in this example. This allows me to\ncreate the `new_user` object without the need to provide an initial value to the object.\nAs consequence, the underlying memory associated with this `new_user` object is uninitialized,\ni.e., the memory is currently populated with \"garbage\" values.\nThus, this expression have the exact same effect of the expression `User new_user;` in C,\nwhich means \"declare a new object named `new_user` of type `User`\".\n\nIt's our responsibility to properly initialize this memory associated with this `new_user` object,\nby assigning valid values to the members (or the fields) of the C struct. In the example below,\nI'm assigning the integer 1 to the member `id`. I am also saving the string `\"pedropark99\"` into the member `name`.\nNotice in this example that I manually add the null character (zero byte) to the end of the allocated array\nfor this string. This null character marks the end of the array in C.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst c = @cImport({\n @cInclude(\"user.h\");\n});\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n\n var new_user: c.User = undefined;\n new_user.id = 1;\n var user_name = try allocator.alloc(u8, 12);\n defer allocator.free(user_name);\n @memcpy(user_name[0..(user_name.len - 1)], \"pedropark99\");\n user_name[user_name.len - 1] = 0;\n new_user.name = user_name.ptr;\n}\n```\n:::\n\n\n\n\nSo, in this example above, we are manually initializing each field of the C struct.\nWe could say that, in this instance, we are \"manually instantiating\nthe C struct object\". However, when we use C libraries in our Zig code, we rarely need\nto manually instantiate the C structs like that. Only because C libraries\nusually provide a \"constructor function\" in their public APIs. As consequence, we normally rely on\nthese constructor functions to properly initialize the C structs, and\nthe struct fields for us.\n\nFor example, consider the Harfbuzz C library. This a text shaping C library,\nand it works around a \"buffer object\", or, more specifically, an instance of\nthe C struct `hb_buffer_t`. Therefore, we need to create an instance of\nthis C struct if we want to use this C library. Luckily, this library offers\nthe function `hb_buffer_create()`, which we can use to create such object.\nSo the Zig code necessary to create such object would probably look something like this:\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cInclude(\"hb.h\");\n});\nvar buf: c.hb_buffer_t = c.hb_buffer_create();\n// Do stuff with the \"buffer object\"\n```\n:::\n\n\n\n\nTherefore, we do not need to manually create an instance of the C struct\n`hb_buffer_t` here, and manually assign valid values to each field in this C struct.\nBecause the constructor function `hb_buffer_create()` is doing this heavy job for us.\n\nSince this `buf` object, and also, the `new_user` object from previous examples, are instances of C structs, these\nobjects are by themselves C compatible values. They are C objects defined in our Zig code. As consequence,\nyou can freely pass these objects as input to any C function that expects to receive this type\nof C struct as input. You do not need to use any special syntax, or, to convert them in\nany special manner to use them in C code. This is how we create and use C objects in our Zig code.\n\n\n\n## Passing C structs across Zig functions {#sec-pass-c-structs}\n\nNow that we have learned how to create/declare C objects in our Zig code, we\nneed to learn how to pass these C objects as inputs to Zig functions.\nAs I described in @sec-c-inputs, we can freely pass these C objects as inputs to C code\nthat we call from our Zig code. But what about passing these C objects to Zig functions?\n\nIn essence, this specific case requires one small adjustment in the Zig function declaration.\nAll you need to do, is to make sure that you pass your C object *by reference* to the function,\ninstead of passing it *by value*. To do that, you have to annotate the data type of the function argument\nthat is receiving this C object as \"a pointer to the C struct\", instead of annotating it as \"an instance of the C struct\".\n\nLet's consider the C struct `User` from the `user.h` C header file that we have used in @sec-c-inputs.\nNow, consider that we want to create a Zig function that sets the value of the `id` field\nin this C struct, like the `set_user_id()` function declared below.\nNotice that the `user` argument in this function is annotated as a pointer (`*`) to a `c.User` object.\n\nTherefore, all you have to do when passing C objects to Zig functions, is to add `*` to the\ndata type of the function argument that is receiving the C object. This will make sure that\nthe C object is passed *by reference* to the function.\n\nBecause we have transformed the function argument into a pointer,\neverytime that you have to access the value pointed by this input pointer inside the function body, for whatever reason (e.g. you want\nto read, update, or delete this value), you have to dereference the pointer with the `.*` syntax that we\nlearned from @sec-pointer. Notice that the `set_user_id()` function is using this syntax to alter\nthe value in the `id` field of the `User` struct pointed by the input pointer.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst c = @cImport({\n @cInclude(\"user.h\");\n});\nfn set_user_id(id: u64, user: *c.User) void {\n user.*.id = id;\n}\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n\n var new_user: c.User = undefined;\n new_user.id = 1;\n var user_name = try allocator.alloc(u8, 12);\n defer allocator.free(user_name);\n @memcpy(user_name[0..(user_name.len - 1)], \"pedropark99\");\n user_name[user_name.len - 1] = 0;\n new_user.name = user_name.ptr;\n\n set_user_id(25, &new_user);\n try stdout.print(\"New ID: {any}\\n\", .{new_user.id});\n}\n```\n:::\n\n\n\n\n```\nNew ID: 25\n```\n", - "supporting": [ - "14-zig-c-interop_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n# Zig interoperability with C\n\nIn this chapter, we are going to discuss the interoperability of Zig with C.\nWe have discussed in @sec-building-c-code how you can use the `zig` compiler to build C code.\nBut we haven't discussed yet how to actually use C code in Zig. In other words,\nwe haven't discussed yet how to call and use C code from Zig.\n\nThis is the main subject of this chapter.\nAlso, in our next small project in this book, we are going to use a C library in it.\nAs consequence, we will put in practice a lot of the knowledge discussed here on\nthis next project.\n\n\n## How to call C code from Zig\n\nInteroperability with C is not something new. Most high-level programming languages have FFI (foreign function interfaces),\nwhich can be used to call C code. For example, Python have Cython, R have `.Call()`, Javascript have `ccall()`, etc.\nBut Zig integrates with C in a deeper level, which affects not only the way that C code gets called, but also,\nhow this C code is compiled and incorporated into your Zig project.\n\nIn summary, Zig have great interoperability with C. If you want to call any C code from Zig,\nyou have to perform the following steps:\n\n- import a C header file into your Zig code.\n- link your Zig code with the C library.\n\n\n### Strategies to import C header files {#sec-strategy-c}\n\nUsing C code in Zig always involves performing the two steps cited above. However, when\nwe talk specifically about the first step listed above, there are currently two\ndifferent ways to perform this first step, which are:\n\n- translating the C header file into Zig code, through the `zig translate-c` command, and then, import and use the translated Zig code.\n- importing the C header file directly into your Zig module through the `@cImport()` built-in function.\n\nIf you are not familiar with `translate-c`, this is a subcommand inside the `zig` compiler that takes C files\nas input, and outputs the Zig representation of the C code present in these C files.\nIn other words, this subcommand works like a transpiler. It takes C code, and translates it into\nthe equivalent Zig code.\n\nI think it would be ok to interpret `translate-c` as a tool to generate Zig bindings\nto C code, similarly to the `rust-bindgen`[^bindgen] tool, which generates Rust FFI bindings to C code.\nBut that would not be a precise interpretation of `translate-c`. The idea behind this tool is\nto really translate the C code into Zig code.\n\n[^bindgen]: \n\nNow, on a surface level, `@cImport()` versus `translate-c` might seem like\ntwo completely different strategies. But in fact, they are effectively the exact same strategy.\nBecause, under the hood, the `@cImport()` built-in function is just a shortcut to `translate-c`.\nBoth tools use the same \"C to Zig\" translation functionality. So when you use `@cImport()`,\nyou are essentially asking the `zig` compiler to translate the C header file into Zig code, then,\nto import this Zig code into your current Zig module.\n\nAt the present moment, there is an accepted proposal at the Zig project, to move `@cImport()`\nto the Zig build system[^cimport-issue]. If this proposal is completed, then, the \"use `@cImport()`\"\nstrategy would be transformed into \"call a translate C function in your Zig build script\".\nSo, the step of translating the C code into Zig code would be moved to\nthe build script of your Zig project, and you would only need to import the translated Zig code into\nyour Zig module to start calling C code from Zig.\n\n[^cimport-issue]: \n\nIf you think about this proposal for a minute, you will understand that this is actually\na small change. I mean, the logic is the same, and the steps are still essentially the same.\nThe only difference is that one of the steps will be moved to the build script of your Zig project.\n\n\n\n### Linking Zig code with a C library {#sec-linking-c}\n\nRegardless of which of the two strategies from the previous section you choose,\nif you want to call C code from Zig, you must link your Zig code\nwith the C library that contains the C code that you want to call.\n\nIn other words, everytime you use some C code in your Zig code, **you introduce a dependency in your build process**.\nThis should come as no surprise to anyone that have any experience with C and C++.\nBecause this is no different in C. Everytime you use a C library in your C code, you also\nhave to build and link your C code with this C library that you are using.\n\nWhen we use a C library in our Zig code, the `zig` compiler needs to access the definition of the C functions that\nare being called in your Zig code. The C header file of this library provides the\ndeclarations of these C functions, but not their definitions. So, in order to access these definitions,\nthe `zig` compiler needs to build your Zig code and link it with the C library during the build process.\n\nAs we discussed across the @sec-build-system, there are different strategies to link something with a library.\nThis might involve building the C library first, and then, linking it with the Zig code. Or,\nit could also involve just the linking step, if this C library is already built and\ninstalled in your system. Anyway, if you have doubts about this, comeback to @sec-build-system.\n\n\n\n## Importing C header files {#sec-import-c-header}\n\nIn @sec-strategy-c, we have described that, currently, there are two different paths that\nyou can take to import a C header file into your Zig modules, `translate-c` or `@cImport()`.\nThis section describes each strategy separately in more details.\n\n### Strategy 1: using `translate-c`\n\nWhen we choose this strategy, we first need to use the `translate-c` tool to translate\nthe C header files that we want to use into Zig code. For example, suppose we wanted to\nuse the `fopen()` C function from the `stdio.h` C header file. We can translate the\n`stdio.h` C header file through the bash command below:\n\n```bash\nzig translate-c /usr/include/stdio.h \\\n -lc -I/usr/include \\\n -D_NO_CRT_STDIO_INLINE=1 > c.zig \\\n```\n\nNotice that, in this bash command, we are passing the necessary compiler flags (`-D` to define macros,\n`-l` to link libraries, `-I` to add an \"include path\") to compile and use the `stdio.h` header file.\nAlso notice that we are saving the results of the translation process inside a Zig module called `c.zig`.\n\nTherefore, after running this command, all we have to do is to import this `c.zig` module, and start\ncalling the C functions that you want to call from it. The example below demonstrates that.\nIt's important to remember what we've discussed in @sec-linking-c. In order to compile this\nexample you have to link this code with `libc`, by passing the flag `-lc` to the `zig` compiler.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @import(\"c.zig\");\npub fn main() !void {\n const x: f32 = 1772.94122;\n _ = c.printf(\"%.3f\\n\", x);\n}\n```\n:::\n\n\n```\n1772.941\n```\n\n\n### Strategy 2: using `@cImport()`\n\nTo import a C header file into our Zig code, we can use the built-in functions `@cInclude()` and `@cImport()`.\nInside the `@cImport()` function, we open a block (with a pair of curly braces). Inside this block\nwe can (if we need to) include multiple `@cDefine()` calls to define C macros when including this specific C header file.\nBut for the most part, you will probably need to use just a single call inside this block,\nwhich is a call to `@cInclude()`.\n\nThis `@cInclude()` function is equivalent to the `#include` statement in C.\nYou provide the name of the C header that you want to include as input to this `@cInclude()` function,\nthen, in conjunction with `@cImport()`, it will perform the necessary steps\nto include this C header file into your Zig code.\n\nYou should bind the result of `@cImport()` to a constant object, pretty much like you would do with\n`@import()`. You just assign the result to a constant object in your\nZig code, and, as consequence, all C functions, C structs, C macros, etc. that are defined inside the\nC header files will be available through this constant object.\n\nLook at the code example below, where we are importing the Standard I/O C Library (`stdio.h`),\nand calling the `printf()`[^printf] C function. Notice that we have also used in this example the C function `powf()`[^powf],\nwhich comes from the C Math Library (`math.h`).\nIn order to compile this example, you have to link this Zig code with both\nthe C Standard Library and the C Math Library, by passing the flags `-lc` and `-lm`\nto the `zig` compiler.\n\n[^printf]: \n[^powf]: \n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cDefine(\"_NO_CRT_STDIO_INLINE\", \"1\");\n @cInclude(\"stdio.h\");\n @cInclude(\"math.h\");\n});\n\npub fn main() !void {\n const x: f32 = 15.2;\n const y = c.powf(x, @as(f32, 2.6));\n _ = c.printf(\"%.3f\\n\", y);\n}\n```\n:::\n\n\n```\n1182.478\n```\n\n\n## About passing Zig values to C functions {#sec-zig-obj-to-c}\n\nZig objects have some intrinsic differences between their C equivalents.\nProbably the most noticeable one is the difference between C strings and Zig strings,\nwhich I described in @sec-zig-strings.\nZig strings are objects that contains both an array of arbitrary bytes and a length value.\nOn the other hand, a C string is usually just a pointer to a null-terminated array of arbitrary bytes.\n\nBecause of these intrinsic differences, in some specific cases, you cannot pass Zig objects directly\nas inputs to C functions before you convert them into C compatible values. However, in some other cases,\nyou are allowed to pass Zig objects and Zig literal values directly as inputs to C functions,\nand everything will work just fine, because the `zig` compiler will handle everything for you.\n\nSo we have two different scenarios being described here. Let's call them \"auto-conversion\" and \"need-conversion\".\nThe \"auto-conversion\" scenario is when the `zig` compiler handles everything for you, and automatically convert your\nZig objects/values into C compatible values. In contrast,\nthe \"need-conversion\" scenario is when you, the programmer, have the responsibility of converting\nthat Zig object into a C compatible value, before passing it to C code.\n\nThere is also a third scenario that is not being described here, which is when you create a C object, or, a C struct, or\na C compatible value in your Zig code, and you pass this C object/value as input to a C function in your Zig code.\nThis scenario will be described later in @sec-c-inputs. In this section, we are focused on the scenarios where\nwe are passing Zig objects/values to C code, instead of C objects/values being passed to C code.\n\n\n### The \"auto-conversion\" scenario\n\nAn \"auto-conversion\" scenario is when the `zig` compiler automatically converts our Zig objects into\nC compatible values for us. This specific scenario happens mostly in two instances:\n\n- with string literal values;\n- with any of the primitive data types that were introduced in @sec-primitive-data-types.\n\nWhen we think about the second instance described above, the `zig` compiler does automatically\nconvert any of the primitive data types into their C equivalents, because the compiler knows how\nto properly convert a `i16` into a `signed short`, or, a `u8` into a `unsigned char`, etc.\nNow, when we think about string literal values, they can be automatically\nconverted into C strings as well, especially because the `zig` compiler does not forces\na specific Zig data type into a string literal at first glance, unless you store this\nstring literal into a Zig object, and explicitly annotate the data type of this object.\n\nThus, with string literal values, the `zig` compiler has more freedom to infer which is the appropriate data type\nto be used in each situation. You could say that the string literal value \"inherits its data type\" depending on the context that\nit's used in. Most of the times, this data type is going to be the type that we commonly associate with Zig strings (`[]const u8`).\nBut it might be a different type depending on the situation. When the `zig` compiler detects that you are providing\na string literal value as input to some C function, the compiler automatically interprets this string\nliteral as a C string value.\n\nAs an example, look at the code exposed below. Here we are using\nthe `fopen()` C function to simply open and close a file. If you do not know how this `fopen()`\nfunction works in C, it takes two C strings as input. But in this code example below, we are passing some\nstring literals written in our Zig code directly as inputs to this `fopen()` C function.\n\nIn other words, we are not doing any conversion from a Zig string to a C string.\nWe are just passing the Zig string literals directly as inputs to the C function. And it works just fine!\nBecause the compiler interprets the string `\"foo.txt\"` as a C string given the current context.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cDefine(\"_NO_CRT_STDIO_INLINE\", \"1\");\n @cInclude(\"stdio.h\");\n});\n\npub fn main() !void {\n const file = c.fopen(\"foo.txt\", \"rb\");\n if (file == null) {\n @panic(\"Could not open file!\");\n }\n if (c.fclose(file) != 0) {\n return error.CouldNotCloseFileDescriptor;\n }\n}\n```\n:::\n\n\nLet's make some experiments, by writing the same code in different manners, and we\nsee how this affects the program. As a starting point, let's store the `\"foo.txt\"` string inside\na Zig object, like the `path` object below, and then, we pass this Zig object as input to the `fopen()` C function.\n\nIf we do this, the program still compiles and runs successfully. Notice that I have omitted most of the code in this example below.\nThis is just for brevity reasons, because the remainder of the program is still the same.\nThe only difference between this example and the previous one is just these two lines exposed below.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path = \"foo.txt\";\n const file = c.fopen(path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\nNow, what happens if you give an explicit data type to the `path` object? Well, if I force\nthe `zig` compiler to interpret this `path` object as a Zig string object,\nby annotating the `path` object with the data type `[]const u8`, then, I actually get a compile error\nas demonstrated below. We get this compile error because now I'm forcing the `zig` compiler\nto interpret `path` as a Zig string object.\n\nAccording to the error message, the `fopen()` C function was expecting to receive an\ninput value of type `[*c]const u8` (C string) instead of a value of type `[]const u8` (Zig string).\nIn more details, the type `[*c]const u8` is actually the Zig type representation of a C string.\nThe `[*c]` portion of this type identifies a C pointer. So, this Zig type essentially means: a C pointer to an array (`[*c]`) of\nconstant bytes (`const u8`).\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const file = c.fopen(path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n```\nt.zig:2:7 error: expected type '[*c]const u8', found '[]const u8':\n const file = c.fopen(path, \"rb\");\n ^~~~\n```\n\nTherefore, when we talk exclusively about string literal values, as long as you don't give an\nexplicit data type to these string literal values, the `zig` compiler should be capable of automatically\nconverting them into C strings as needed.\n\nBut what about using one of the primitive data types that were introduced in @sec-primitive-data-types?\nLet's take code exposed below as an example of that. Here, we are giving some float literal values as input\nto the C function `powf()`. Notice that this code example compiles and runs successfully.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst cmath = @cImport({\n @cInclude(\"math.h\");\n});\n\npub fn main() !void {\n const y = cmath.powf(15.68, 2.32);\n try stdout.print(\"{d}\\n\", .{y});\n}\n```\n:::\n\n\n```\n593.2023\n```\n\nOnce again, because the `zig` compiler does not associate a specific data type with the literal values\n`15.68` and `2.32` at first glance, the compiler can automatically convert these values\ninto their C `float` (or `double`) equivalents, before it passes to the `powf()` C function.\nNow, even if I give an explicit Zig data type to these literal values, by storing them into a Zig object,\nand explicit annotating the type of these objects, the code still compiles and runs successfully.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const x: f32 = 15.68;\n const y = cmath.powf(x, 2.32);\n // The remainder of the program\n```\n:::\n\n\n```\n593.2023\n```\n\n\n\n### The \"need-conversion\" scenario\n\nA \"need-conversion\" scenario is when we need to manually convert our Zig objects into C compatible values\nbefore passing them as input to C functions. You will fall in this scenario, when passing Zig string objects\nto C functions.\n\nWe have already seen this specific circumstance in the last `fopen()` example,\nwhich is reproduced below. You can see in this example, that we have given an explicit Zig data type\n(`[]const u8`) to our `path` object, and, as a consequence of that, we have forced the `zig` compiler\nto see this `path` object, as a Zig string object. Therefore, we need now to manually convert\nthis `path` object into a C string before we pass it to `fopen()`.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const file = c.fopen(path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n```\nt.zig:10:26: error: expected type '[*c]const u8', found '[]const u8'\n const file = c.fopen(path, \"rb\");\n ^~~~\n```\n\n\nThere are different ways to convert a Zig string object into a C string.\nOne way to solve this problem is to provide the pointer to the underlying array\nof bytes, instead of providing the Zig object directly as input.\nYou can access this pointer by using the `ptr` property of the Zig string object.\n\nThe code example below demonstrates this strategy. Notice that, by giving the\npointer to the underlying array in `path` through the `ptr` property, we get no compile errors as result\nwhile using the `fopen()` C function.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const file = c.fopen(path.ptr, \"rb\");\n // Remainder of the program\n```\n:::\n\n\nThis strategy works because this pointer to the underlying array found in the `ptr` property,\nis semantically identical to a C pointer to an array of bytes, i.e., a C object of type `*unsigned char`.\nThis is why this option also solves the problem of converting the Zig string into a C string.\n\nAnother option is to explicitly convert the Zig string object into a C pointer by using the\nbuilt-in function `@ptrCast()`. With this function we can convert\nan object of type `[]const u8` into an object of type `[*c]const u8`.\nAs I described at the previous section, the `[*c]` portion of the type\nmeans that it's a C pointer. This strategy is not-recommended. But it's\nuseful to demonstrate the use of `@ptrCast()`.\n\nYou may recall of `@as()` and `@ptrCast()` from @sec-type-cast. Just as a recap,\nthe `@as()` built-in function is used to explicitly convert (or cast) a Zig value\nfrom a type \"x\" into a value of type \"y\". But in our case here, we are converting\na pointer object. Everytime a pointer is involved in some \"type casting operation\" in Zig,\nthe `@ptrCast()` function is involved.\n\nIn the example below, we are using this function to cast our `path` object\ninto a C pointer to an array of bytes. Then, we pass this C pointer as input\nto the `fopen()` function. Notice that this code example compiles successfully\nwith no errors.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\n const path: []const u8 = \"foo.txt\";\n const c_path: [*c]const u8 = @ptrCast(path);\n const file = c.fopen(c_path, \"rb\");\n // Remainder of the program\n```\n:::\n\n\n\n\n## Creating C objects in Zig {#sec-c-inputs}\n\nCreating C objects, or, in other words, creating instances of C structs in your Zig code\nis actually something quite easy to do. You first need to import the C header file (like I described in @sec-import-c-header) that defines\nthe C struct that you are trying to instantiate in your Zig code. After that, you can just\ncreate a new object in your Zig code, and annotate it with the data type of the C struct.\n\nFor example, suppose we have a C header file called `user.h`, and that this header file is declaring a new struct named `User`.\nThis C header file is exposed below:\n\n```c\n#include \n\ntypedef struct {\n uint64_t id;\n char* name;\n} User;\n```\n\nThis `User` C struct have two distinct fields, or two struct members, named `id` and `name`.\nThe field `id` is an unsigned 64-bit integer value, while the field `name` is just a standard C string.\nNow, suppose that I want to create an instance of this `User` struct in my Zig code.\nI can do that by importing this `user.h` header file into my Zig code, and creating\na new object with type `User`. These steps are reproduced in the code example below.\n\nNotice that I have used the keyword `undefined` in this example. This allows me to\ncreate the `new_user` object without the need to provide an initial value to the object.\nAs consequence, the underlying memory associated with this `new_user` object is uninitialized,\ni.e., the memory is currently populated with \"garbage\" values.\nThus, this expression have the exact same effect of the expression `User new_user;` in C,\nwhich means \"declare a new object named `new_user` of type `User`\".\n\nIt's our responsibility to properly initialize this memory associated with this `new_user` object,\nby assigning valid values to the members (or the fields) of the C struct. In the example below,\nI'm assigning the integer 1 to the member `id`. I am also saving the string `\"pedropark99\"` into the member `name`.\nNotice in this example that I manually add the null character (zero byte) to the end of the allocated array\nfor this string. This null character marks the end of the array in C.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst c = @cImport({\n @cInclude(\"user.h\");\n});\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n\n var new_user: c.User = undefined;\n new_user.id = 1;\n var user_name = try allocator.alloc(u8, 12);\n defer allocator.free(user_name);\n @memcpy(user_name[0..(user_name.len - 1)], \"pedropark99\");\n user_name[user_name.len - 1] = 0;\n new_user.name = user_name.ptr;\n}\n```\n:::\n\n\nSo, in this example above, we are manually initializing each field of the C struct.\nWe could say that, in this instance, we are \"manually instantiating\nthe C struct object\". However, when we use C libraries in our Zig code, we rarely need\nto manually instantiate the C structs like that. Only because C libraries\nusually provide a \"constructor function\" in their public APIs. As consequence, we normally rely on\nthese constructor functions to properly initialize the C structs, and\nthe struct fields for us.\n\nFor example, consider the Harfbuzz C library. This a text shaping C library,\nand it works around a \"buffer object\", or, more specifically, an instance of\nthe C struct `hb_buffer_t`. Therefore, we need to create an instance of\nthis C struct if we want to use this C library. Luckily, this library offers\nthe function `hb_buffer_create()`, which we can use to create such object.\nSo the Zig code necessary to create such object would probably look something like this:\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst c = @cImport({\n @cInclude(\"hb.h\");\n});\nvar buf: c.hb_buffer_t = c.hb_buffer_create();\n// Do stuff with the \"buffer object\"\n```\n:::\n\n\nTherefore, we do not need to manually create an instance of the C struct\n`hb_buffer_t` here, and manually assign valid values to each field in this C struct.\nBecause the constructor function `hb_buffer_create()` is doing this heavy job for us.\n\nSince this `buf` object, and also, the `new_user` object from previous examples, are instances of C structs, these\nobjects are by themselves C compatible values. They are C objects defined in our Zig code. As consequence,\nyou can freely pass these objects as input to any C function that expects to receive this type\nof C struct as input. You do not need to use any special syntax, or, to convert them in\nany special manner to use them in C code. This is how we create and use C objects in our Zig code.\n\n\n\n## Passing C structs across Zig functions {#sec-pass-c-structs}\n\nNow that we have learned how to create/declare C objects in our Zig code, we\nneed to learn how to pass these C objects as inputs to Zig functions.\nAs I described in @sec-c-inputs, we can freely pass these C objects as inputs to C code\nthat we call from our Zig code. But what about passing these C objects to Zig functions?\n\nIn essence, this specific case requires one small adjustment in the Zig function declaration.\nAll you need to do, is to make sure that you pass your C object *by reference* to the function,\ninstead of passing it *by value*. To do that, you have to annotate the data type of the function argument\nthat is receiving this C object as \"a pointer to the C struct\", instead of annotating it as \"an instance of the C struct\".\n\nLet's consider the C struct `User` from the `user.h` C header file that we have used in @sec-c-inputs.\nNow, consider that we want to create a Zig function that sets the value of the `id` field\nin this C struct, like the `set_user_id()` function declared below.\nNotice that the `user` argument in this function is annotated as a pointer (`*`) to a `c.User` object.\n\nTherefore, all you have to do when passing C objects to Zig functions, is to add `*` to the\ndata type of the function argument that is receiving the C object. This will make sure that\nthe C object is passed *by reference* to the function.\n\nBecause we have transformed the function argument into a pointer,\neverytime that you have to access the value pointed by this input pointer inside the function body, for whatever reason (e.g. you want\nto read, update, or delete this value), you have to dereference the pointer with the `.*` syntax that we\nlearned from @sec-pointer. Notice that the `set_user_id()` function is using this syntax to alter\nthe value in the `id` field of the `User` struct pointed by the input pointer.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst std = @import(\"std\");\nconst stdout = std.io.getStdOut().writer();\nconst c = @cImport({\n @cInclude(\"user.h\");\n});\nfn set_user_id(id: u64, user: *c.User) void {\n user.*.id = id;\n}\n\npub fn main() !void {\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n const allocator = gpa.allocator();\n\n var new_user: c.User = undefined;\n new_user.id = 1;\n var user_name = try allocator.alloc(u8, 12);\n defer allocator.free(user_name);\n @memcpy(user_name[0..(user_name.len - 1)], \"pedropark99\");\n user_name[user_name.len - 1] = 0;\n new_user.name = user_name.ptr;\n\n set_user_id(25, &new_user);\n try stdout.print(\"New ID: {any}\\n\", .{new_user.id});\n}\n```\n:::\n\n\n```\nNew ID: 25\n```\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/Chapters/15-vectors/execute-results/epub.json b/_freeze/Chapters/15-vectors/execute-results/epub.json deleted file mode 100644 index 4b0fe519..00000000 --- a/_freeze/Chapters/15-vectors/execute-results/epub.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "hash": "3da767c3f773d387d2d0a42df4405278", - "result": { - "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n# Introducing Vectors and SIMD {#sec-vectors-simd}\n\nIn this chapter, I want to discuss vectors in Zig, which are\nrelated to SIMD operations (i.e., they have no relationship with the `std::vector` class\nfrom C++).\n\n## What is SIMD?\n\nSIMD (*Single Instruction/Multiple Data*) is a group of operations that are widely used\non video/audio editing programs, and also in graphics applications. SIMD is not a new technology,\nbut the massive use of SIMD on normal desktop computers is somewhat recent. In the old days, SIMD\nwas only used on \"supercomputer models\".\n\nMost modern CPU models (from AMD, Intel, etc.) these days (either in a desktop or in a\nnotebook model) have support for SIMD operations. So, if you have a very old CPU model installed in your\ncomputer, then, it's possible that you have no support for SIMD operations in your computer.\n\nWhy have people started using SIMD in their software? The answer is performance.\nBut what does SIMD precisely do to achieve better performance? Well, in essence, SIMD operations are a different\nstrategy to get parallel computing in your program, and therefore, make faster calculations.\n\nThe basic idea behind SIMD is to have a single instruction that operates over multiple data\nat the same time. When you perform a normal scalar operation, like for example, four add instructions,\neach addition is performed separately, one after another. But with SIMD, these four add instructions\nare translated into a single instruction, and, as consequence, the four additions are performed\nin parallel, at the same time.\n\nCurrently, the `zig` compiler allows you to apply the following group of operators on vector objects.\nWhen you apply one of these operators on vector objects, SIMD is used to make the calculations, and,\ntherefore, these operators are applied element-wise and in parallel by default.\n\n- Arithmetic (`+`, `-`, `/`, `*`, `@divFloor()`, `@sqrt()`, `@ceil()`, `@log()`, etc.).\n- Bitwise operators (`>>`, `<<`, `&`, `|`, `~`, etc.).\n- Comparison operators (`<`, `>`, `==`, etc.).\n\n\n## Vectors {#sec-what-vectors}\n\nA SIMD operation is usually performed through a *SIMD intrinsic*, which is just a fancy\nname for a function that performs a SIMD operation. These SIMD intrinsics (or \"SIMD functions\")\nalways operate over a special type of object, which are called \"vectors\". So,\nin order to use SIMD, you have to create a \"vector object\".\n\nA vector object is usually a fixed-sized block of 128 bits (16 bytes).\nAs a consequence, most vectors that you find in the wild are essentially arrays that contains 2 values of 8 bytes each,\nor, 4 values of 4 bytes each, or, 8 values of 2 bytes each, etc.\nHowever, different CPU models may have different extensions (or, \"implementations\") of SIMD,\nwhich may offer more types of vector objects that are bigger in size (256 bits or 512 bits)\nto accomodate more data into a single vector object.\n\nYou can create a new vector object in Zig by using the `@Vector()` built-in function. Inside this function,\nyou specify the vector length (number of elements in the vector), and the data type of the elements\nof the vector. Only primitive data types are supported in these vector objects.\nIn the example below, I'm creating two vector objects (`v1` and `v2`) of 4 elements of type `u32` each.\n\nAlso notice in the example below, that a third vector object (`v3`) is created from the\nsum of the previous two vector objects (`v1` plus `v2`). Therefore,\nmath operations over vector objects take place element-wise by default, because\nthe same operation (in this case, addition) is transformed into a single instruction\nthat is replicated in parallel, across all elements of the vectors.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = @Vector(4, u32){4, 12, 37, 9};\nconst v2 = @Vector(4, u32){10, 22, 5, 12};\nconst v3 = v1 + v2;\ntry stdout.print(\"{any}\\n\", .{v3});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 14, 34, 42, 21 }\n```\n\n\n:::\n:::\n\n\n\nThis is how SIMD introduces more performance in your program. Instead of using a for loop\nto iterate through the elements of `v1` and `v2`, and adding them together, one element at a time,\nwe enjoy the benefits of SIMD, which performs all 4 additions in parallel, at the same time.\n\nTherefore, the `@Vector` structure is essentially the Zig representation of SIMD vector objects.\nThe elements in these vector objects will be operated in parallel, if, and only if your current CPU model\nsupports SIMD operations. If your CPU model does not have support for SIMD, then, the `@Vector` structure will\nlikely produce a similar performance from a \"for loop solution\".\n\n\n### Transforming arrays into vectors\n\nThere are different ways to transform a normal array into a vector object.\nYou can either use implicit conversion (which is when you assign the array to\na vector object directly), or, use slices to create a vector object from a normal array.\n\nIn the example below, we are implicitly converting the array `a1` into a vector object (`v1`)\nof length 4. We first explicitly annotate the data type of the vector object,\nand then, we assign the array object to this vector object.\n\nAlso notice in the example below, that a second vector object (`v2`) is also created\nby taking a slice of the array object (`a1`), and then, storing the pointer to this\nslice (`.*`) into this vector object.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a1 = [4]u32{4, 12, 37, 9};\nconst v1: @Vector(4, u32) = a1;\nconst v2: @Vector(2, u32) = a1[1..3].*;\n_ = v1; _ = v2;\n```\n:::\n\n\n\n\nIt's worth emphasizing that only arrays and slices whose sizes\nare compile-time known can be transformed into vectors. Vectors in general\nare structures that work only with compile-time known sizes. Therefore, if\nyou have an array whose size is runtime known, then, you first need to\ncopy it into an array with a compile-time known size, before transforming it into a vector.\n\n\n\n### The `@splat()` function\n\nYou can use the `@splat()` built-in function to create a vector object that is filled\nwith the same value across all of its elements. This function was created to offer a quick\nand easy way to directly convert a scalar value (a.k.a. a single value, like a single character, or a single integer, etc.)\ninto a vector object.\n\nThus, we can use `@splat()` to convert a single value, like the integer `16` into a vector object\nof length 1. But we can also use this function to convert the same integer `16` into a\nvector object of length 10, that is filled with 10 `16` values. The example below demonstrates\nthis idea.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1: @Vector(10, u32) = @splat(16);\ntry stdout.print(\"{any}\\n\", .{v1});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }\n```\n\n\n:::\n:::\n\n\n\n\n\n### Careful with vectors that are too big\n\nAs I described in @sec-what-vectors, each vector object is usually a small block of 128, 256 or 512 bits.\nThis means that a vector object is usually small in size, and when you try to go in the opposite direction,\nby creating a vector object that is very big in size (i.e., sizes that are close to $2^{20}$),\nyou usually end up with crashes and loud errors from the compiler.\n\nFor example, if you try to compile the program below, you will likely face segmentation faults, or LLVM errors during\nthe build process. Just be careful to not create vector objects that are too big in size.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1: @Vector(1000000, u32) = @splat(16);\n_ = v1;\n```\n:::\n\n\n\n```\nSegmentation fault (core dumped)\n```\n", - "supporting": [ - "15-vectors_files" - ], - "filters": [ - "rmarkdown/pagebreak.lua" - ], - "includes": {}, - "engineDependencies": { - "knitr": [ - "{\"type\":\"list\",\"attributes\":{},\"value\":[]}" - ] - }, - "preserve": null, - "postProcess": false - } -} \ No newline at end of file diff --git a/_freeze/Chapters/15-vectors/execute-results/html.json b/_freeze/Chapters/15-vectors/execute-results/html.json index d68d2db0..3e76e5cf 100644 --- a/_freeze/Chapters/15-vectors/execute-results/html.json +++ b/_freeze/Chapters/15-vectors/execute-results/html.json @@ -2,10 +2,8 @@ "hash": "3da767c3f773d387d2d0a42df4405278", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n\n# Introducing Vectors and SIMD {#sec-vectors-simd}\n\nIn this chapter, I want to discuss vectors in Zig, which are\nrelated to SIMD operations (i.e., they have no relationship with the `std::vector` class\nfrom C++).\n\n## What is SIMD?\n\nSIMD (*Single Instruction/Multiple Data*) is a group of operations that are widely used\non video/audio editing programs, and also in graphics applications. SIMD is not a new technology,\nbut the massive use of SIMD on normal desktop computers is somewhat recent. In the old days, SIMD\nwas only used on \"supercomputer models\".\n\nMost modern CPU models (from AMD, Intel, etc.) these days (either in a desktop or in a\nnotebook model) have support for SIMD operations. So, if you have a very old CPU model installed in your\ncomputer, then, it's possible that you have no support for SIMD operations in your computer.\n\nWhy have people started using SIMD in their software? The answer is performance.\nBut what does SIMD precisely do to achieve better performance? Well, in essence, SIMD operations are a different\nstrategy to get parallel computing in your program, and therefore, make faster calculations.\n\nThe basic idea behind SIMD is to have a single instruction that operates over multiple data\nat the same time. When you perform a normal scalar operation, like for example, four add instructions,\neach addition is performed separately, one after another. But with SIMD, these four add instructions\nare translated into a single instruction, and, as consequence, the four additions are performed\nin parallel, at the same time.\n\nCurrently, the `zig` compiler allows you to apply the following group of operators on vector objects.\nWhen you apply one of these operators on vector objects, SIMD is used to make the calculations, and,\ntherefore, these operators are applied element-wise and in parallel by default.\n\n- Arithmetic (`+`, `-`, `/`, `*`, `@divFloor()`, `@sqrt()`, `@ceil()`, `@log()`, etc.).\n- Bitwise operators (`>>`, `<<`, `&`, `|`, `~`, etc.).\n- Comparison operators (`<`, `>`, `==`, etc.).\n\n\n## Vectors {#sec-what-vectors}\n\nA SIMD operation is usually performed through a *SIMD intrinsic*, which is just a fancy\nname for a function that performs a SIMD operation. These SIMD intrinsics (or \"SIMD functions\")\nalways operate over a special type of object, which are called \"vectors\". So,\nin order to use SIMD, you have to create a \"vector object\".\n\nA vector object is usually a fixed-sized block of 128 bits (16 bytes).\nAs a consequence, most vectors that you find in the wild are essentially arrays that contains 2 values of 8 bytes each,\nor, 4 values of 4 bytes each, or, 8 values of 2 bytes each, etc.\nHowever, different CPU models may have different extensions (or, \"implementations\") of SIMD,\nwhich may offer more types of vector objects that are bigger in size (256 bits or 512 bits)\nto accomodate more data into a single vector object.\n\nYou can create a new vector object in Zig by using the `@Vector()` built-in function. Inside this function,\nyou specify the vector length (number of elements in the vector), and the data type of the elements\nof the vector. Only primitive data types are supported in these vector objects.\nIn the example below, I'm creating two vector objects (`v1` and `v2`) of 4 elements of type `u32` each.\n\nAlso notice in the example below, that a third vector object (`v3`) is created from the\nsum of the previous two vector objects (`v1` plus `v2`). Therefore,\nmath operations over vector objects take place element-wise by default, because\nthe same operation (in this case, addition) is transformed into a single instruction\nthat is replicated in parallel, across all elements of the vectors.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = @Vector(4, u32){4, 12, 37, 9};\nconst v2 = @Vector(4, u32){10, 22, 5, 12};\nconst v3 = v1 + v2;\ntry stdout.print(\"{any}\\n\", .{v3});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 14, 34, 42, 21 }\n```\n\n\n:::\n:::\n\n\n\n\nThis is how SIMD introduces more performance in your program. Instead of using a for loop\nto iterate through the elements of `v1` and `v2`, and adding them together, one element at a time,\nwe enjoy the benefits of SIMD, which performs all 4 additions in parallel, at the same time.\n\nTherefore, the `@Vector` structure is essentially the Zig representation of SIMD vector objects.\nThe elements in these vector objects will be operated in parallel, if, and only if your current CPU model\nsupports SIMD operations. If your CPU model does not have support for SIMD, then, the `@Vector` structure will\nlikely produce a similar performance from a \"for loop solution\".\n\n\n### Transforming arrays into vectors\n\nThere are different ways to transform a normal array into a vector object.\nYou can either use implicit conversion (which is when you assign the array to\na vector object directly), or, use slices to create a vector object from a normal array.\n\nIn the example below, we are implicitly converting the array `a1` into a vector object (`v1`)\nof length 4. We first explicitly annotate the data type of the vector object,\nand then, we assign the array object to this vector object.\n\nAlso notice in the example below, that a second vector object (`v2`) is also created\nby taking a slice of the array object (`a1`), and then, storing the pointer to this\nslice (`.*`) into this vector object.\n\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a1 = [4]u32{4, 12, 37, 9};\nconst v1: @Vector(4, u32) = a1;\nconst v2: @Vector(2, u32) = a1[1..3].*;\n_ = v1; _ = v2;\n```\n:::\n\n\n\n\n\nIt's worth emphasizing that only arrays and slices whose sizes\nare compile-time known can be transformed into vectors. Vectors in general\nare structures that work only with compile-time known sizes. Therefore, if\nyou have an array whose size is runtime known, then, you first need to\ncopy it into an array with a compile-time known size, before transforming it into a vector.\n\n\n\n### The `@splat()` function\n\nYou can use the `@splat()` built-in function to create a vector object that is filled\nwith the same value across all of its elements. This function was created to offer a quick\nand easy way to directly convert a scalar value (a.k.a. a single value, like a single character, or a single integer, etc.)\ninto a vector object.\n\nThus, we can use `@splat()` to convert a single value, like the integer `16` into a vector object\nof length 1. But we can also use this function to convert the same integer `16` into a\nvector object of length 10, that is filled with 10 `16` values. The example below demonstrates\nthis idea.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1: @Vector(10, u32) = @splat(16);\ntry stdout.print(\"{any}\\n\", .{v1});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }\n```\n\n\n:::\n:::\n\n\n\n\n\n\n### Careful with vectors that are too big\n\nAs I described in @sec-what-vectors, each vector object is usually a small block of 128, 256 or 512 bits.\nThis means that a vector object is usually small in size, and when you try to go in the opposite direction,\nby creating a vector object that is very big in size (i.e., sizes that are close to $2^{20}$),\nyou usually end up with crashes and loud errors from the compiler.\n\nFor example, if you try to compile the program below, you will likely face segmentation faults, or LLVM errors during\nthe build process. Just be careful to not create vector objects that are too big in size.\n\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1: @Vector(1000000, u32) = @splat(16);\n_ = v1;\n```\n:::\n\n\n\n\n```\nSegmentation fault (core dumped)\n```\n", - "supporting": [ - "15-vectors_files" - ], + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"../Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n# Introducing Vectors and SIMD {#sec-vectors-simd}\n\nIn this chapter, I want to discuss vectors in Zig, which are\nrelated to SIMD operations (i.e., they have no relationship with the `std::vector` class\nfrom C++).\n\n## What is SIMD?\n\nSIMD (*Single Instruction/Multiple Data*) is a group of operations that are widely used\non video/audio editing programs, and also in graphics applications. SIMD is not a new technology,\nbut the massive use of SIMD on normal desktop computers is somewhat recent. In the old days, SIMD\nwas only used on \"supercomputer models\".\n\nMost modern CPU models (from AMD, Intel, etc.) these days (either in a desktop or in a\nnotebook model) have support for SIMD operations. So, if you have a very old CPU model installed in your\ncomputer, then, it's possible that you have no support for SIMD operations in your computer.\n\nWhy have people started using SIMD in their software? The answer is performance.\nBut what does SIMD precisely do to achieve better performance? Well, in essence, SIMD operations are a different\nstrategy to get parallel computing in your program, and therefore, make faster calculations.\n\nThe basic idea behind SIMD is to have a single instruction that operates over multiple data\nat the same time. When you perform a normal scalar operation, like for example, four add instructions,\neach addition is performed separately, one after another. But with SIMD, these four add instructions\nare translated into a single instruction, and, as consequence, the four additions are performed\nin parallel, at the same time.\n\nCurrently, the `zig` compiler allows you to apply the following group of operators on vector objects.\nWhen you apply one of these operators on vector objects, SIMD is used to make the calculations, and,\ntherefore, these operators are applied element-wise and in parallel by default.\n\n- Arithmetic (`+`, `-`, `/`, `*`, `@divFloor()`, `@sqrt()`, `@ceil()`, `@log()`, etc.).\n- Bitwise operators (`>>`, `<<`, `&`, `|`, `~`, etc.).\n- Comparison operators (`<`, `>`, `==`, etc.).\n\n\n## Vectors {#sec-what-vectors}\n\nA SIMD operation is usually performed through a *SIMD intrinsic*, which is just a fancy\nname for a function that performs a SIMD operation. These SIMD intrinsics (or \"SIMD functions\")\nalways operate over a special type of object, which are called \"vectors\". So,\nin order to use SIMD, you have to create a \"vector object\".\n\nA vector object is usually a fixed-sized block of 128 bits (16 bytes).\nAs a consequence, most vectors that you find in the wild are essentially arrays that contains 2 values of 8 bytes each,\nor, 4 values of 4 bytes each, or, 8 values of 2 bytes each, etc.\nHowever, different CPU models may have different extensions (or, \"implementations\") of SIMD,\nwhich may offer more types of vector objects that are bigger in size (256 bits or 512 bits)\nto accomodate more data into a single vector object.\n\nYou can create a new vector object in Zig by using the `@Vector()` built-in function. Inside this function,\nyou specify the vector length (number of elements in the vector), and the data type of the elements\nof the vector. Only primitive data types are supported in these vector objects.\nIn the example below, I'm creating two vector objects (`v1` and `v2`) of 4 elements of type `u32` each.\n\nAlso notice in the example below, that a third vector object (`v3`) is created from the\nsum of the previous two vector objects (`v1` plus `v2`). Therefore,\nmath operations over vector objects take place element-wise by default, because\nthe same operation (in this case, addition) is transformed into a single instruction\nthat is replicated in parallel, across all elements of the vectors.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1 = @Vector(4, u32){4, 12, 37, 9};\nconst v2 = @Vector(4, u32){10, 22, 5, 12};\nconst v3 = v1 + v2;\ntry stdout.print(\"{any}\\n\", .{v3});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 14, 34, 42, 21 }\n```\n\n\n:::\n:::\n\n\nThis is how SIMD introduces more performance in your program. Instead of using a for loop\nto iterate through the elements of `v1` and `v2`, and adding them together, one element at a time,\nwe enjoy the benefits of SIMD, which performs all 4 additions in parallel, at the same time.\n\nTherefore, the `@Vector` structure is essentially the Zig representation of SIMD vector objects.\nThe elements in these vector objects will be operated in parallel, if, and only if your current CPU model\nsupports SIMD operations. If your CPU model does not have support for SIMD, then, the `@Vector` structure will\nlikely produce a similar performance from a \"for loop solution\".\n\n\n### Transforming arrays into vectors\n\nThere are different ways to transform a normal array into a vector object.\nYou can either use implicit conversion (which is when you assign the array to\na vector object directly), or, use slices to create a vector object from a normal array.\n\nIn the example below, we are implicitly converting the array `a1` into a vector object (`v1`)\nof length 4. We first explicitly annotate the data type of the vector object,\nand then, we assign the array object to this vector object.\n\nAlso notice in the example below, that a second vector object (`v2`) is also created\nby taking a slice of the array object (`a1`), and then, storing the pointer to this\nslice (`.*`) into this vector object.\n\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst a1 = [4]u32{4, 12, 37, 9};\nconst v1: @Vector(4, u32) = a1;\nconst v2: @Vector(2, u32) = a1[1..3].*;\n_ = v1; _ = v2;\n```\n:::\n\n\n\nIt's worth emphasizing that only arrays and slices whose sizes\nare compile-time known can be transformed into vectors. Vectors in general\nare structures that work only with compile-time known sizes. Therefore, if\nyou have an array whose size is runtime known, then, you first need to\ncopy it into an array with a compile-time known size, before transforming it into a vector.\n\n\n\n### The `@splat()` function\n\nYou can use the `@splat()` built-in function to create a vector object that is filled\nwith the same value across all of its elements. This function was created to offer a quick\nand easy way to directly convert a scalar value (a.k.a. a single value, like a single character, or a single integer, etc.)\ninto a vector object.\n\nThus, we can use `@splat()` to convert a single value, like the integer `16` into a vector object\nof length 1. But we can also use this function to convert the same integer `16` into a\nvector object of length 10, that is filled with 10 `16` values. The example below demonstrates\nthis idea.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1: @Vector(10, u32) = @splat(16);\ntry stdout.print(\"{any}\\n\", .{v1});\n```\n\n\n::: {.cell-output .cell-output-stdout}\n\n```\n{ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }\n```\n\n\n:::\n:::\n\n\n\n\n### Careful with vectors that are too big\n\nAs I described in @sec-what-vectors, each vector object is usually a small block of 128, 256 or 512 bits.\nThis means that a vector object is usually small in size, and when you try to go in the opposite direction,\nby creating a vector object that is very big in size (i.e., sizes that are close to $2^{20}$),\nyou usually end up with crashes and loud errors from the compiler.\n\nFor example, if you try to compile the program below, you will likely face segmentation faults, or LLVM errors during\nthe build process. Just be careful to not create vector objects that are too big in size.\n\n\n::: {.cell}\n\n```{.zig .cell-code}\nconst v1: @Vector(1000000, u32) = @splat(16);\n_ = v1;\n```\n:::\n\n\n```\nSegmentation fault (core dumped)\n```\n", + "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" ], diff --git a/_freeze/index/execute-results/epub.json b/_freeze/index/execute-results/epub.json deleted file mode 100644 index 4df3471d..00000000 --- a/_freeze/index/execute-results/epub.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "hash": "0b80ffe49bae68e2641a31569b9e19df", - "result": { - "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy\nof the book, either at Amazon, or at Leanpub:\n\n\n\n\n\n \n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Senior Data Engineer at [DSM-Firmenich](https://www.dsm-firmenich.com)[^dsm], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^dsm]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n\n- System version: Linux, 6.12.21-4-MANJARO, NA, x86_64.\n- Zig version: 0.15.0-dev.635+7dbd21bd5.\n- Quarto version: 1.4.554.\n\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion), glystik (\\@glystik), Michael Lynch (\\@mtlynch), Yashank (\\@stickyburn), _blf_ (\\@bengtfrost)\n", - "supporting": [ - "index_files" - ], - "filters": [ - "rmarkdown/pagebreak.lua" - ], - "includes": {}, - "engineDependencies": { - "knitr": [ - "{\"type\":\"list\",\"attributes\":{},\"value\":[]}" - ] - }, - "preserve": null, - "postProcess": false - } -} \ No newline at end of file diff --git a/_freeze/index/execute-results/html.json b/_freeze/index/execute-results/html.json index f43fa582..affa01a2 100644 --- a/_freeze/index/execute-results/html.json +++ b/_freeze/index/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "0b80ffe49bae68e2641a31569b9e19df", + "hash": "826210be244a6e675fa884a125b3c0f1", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n::: {.content-visible when-format=\"html\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy\nof the book, either at Amazon, or at Leanpub:\n\n\n\n\n\n \n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n \n \n \n \n \n\n\n\n:::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Senior Data Engineer at [DSM-Firmenich](https://www.dsm-firmenich.com)[^dsm], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^dsm]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n- System version: Linux, 6.12.21-4-MANJARO, NA, x86_64.\n- Zig version: 0.15.0-dev.635+7dbd21bd5.\n- Quarto version: 1.4.554.\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion), glystik (\\@glystik), Michael Lynch (\\@mtlynch), Yashank (\\@stickyburn), _blf_ (\\@bengtfrost)\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n:::: {.content-hidden when-format=\"epub\"}\n::: {.content-hidden when-format=\"pdf\"}\n\n# Welcome {.unnumbered}\n\nWelcome! This is the initial page for the \"Open Access\" HTML version of the book \"Introduction to Zig: a project-based book\",\nwritten by [Pedro Duarte Faria](https://pedro-faria.netlify.app/).\nThis is an open book that provides an introduction to the [Zig programming language](https://ziglang.org/),\nwhich is a new general-purpose, and low-level language for building robust and optimal software.\n\n## Support the project! {.unnumbered}\n\nIf you like this project, and you want to support it, you can buy a PDF, eBook or a physical copy\nof the book, either at Amazon, or at Leanpub:\n\n\n\n\n\n \n\n\n\n\n\n\n \n\n\n\n\n\n### Sending donations directly\n\nYou can also donate some amount directly to the author of the project via:\n\n- PayPal Donation.\n- Revolut.\n\nThese are good ways to support directly the author of the project, which helps to foster\nmore contents like this, and it makes possible for the author to keep writing helpful tools and\nmaterials for the community.\n\n### PayPal\n\n\n \n \n \n \n \n \n\n\n\n### Revolut\n\nYou can send money via Swift Payment with the following bank and Swift details:\n\n```\nRecipient: Pedro Duarte Faria\nBIC/SWIFT Code: REVOSGS2\nAccount number: 6124512226\nName and address of the bank: Revolut Technologies Singapore Pte. Ltd, 6 Battery Road, Floor 6-01, 049909, Singapore, Singapore\nCorresponding BIC: CHASGB2L\n```\n\nIf you do have a Revolut account, you can scan the following QR code:\n\n\n \n \n \n \n \n\n\n\n:::\n::::\n\n\n## About this book {.unnumbered}\n\nThis an open (i.e., open-source), technical and introductory book for the [Zig programming language](https://ziglang.org/),\nwhich is a new general purpose, and low-level programming language for building optimal and robust software.\n\nOfficial repository of the book: .\n\nThis book is designed for both beginners and experienced developers. It explores the exciting world of Zig through small\nand simple projects (in a similar style to the famous \"Python Crash Course\" book from Eric Matthes).\nSome of these projects are: a Base64 encoder/decoder, a HTTP Server and an image filter.\n\nAs you work through the book, you will learn:\n\n- The syntax of the language, and how it compares to C, C++ and Rust.\n- Data structures, memory allocators, filesystem and I/O.\n- Optionals as a new paradigm to handle nullability.\n- How to test and debug a Zig application.\n- Errors as values, and how to handle them.\n- How to build C and Zig code with the build system that is embedded into the language.\n- Zig interoperability with C.\n- Parallelism with threads and SIMD.\n- And more.\n\n\n## About the author {.unnumbered}\n\nPedro Duarte Faria has a bachelor's degree in Economics from the Federal University of Ouro Preto - Brazil.\nCurrently, he is a Senior Data Engineer at [DSM-Firmenich](https://www.dsm-firmenich.com)[^dsm], and\na Databricks Certified Associate Developer for Apache Spark 3.0.\n\n[^dsm]: \n\n\nThe author has more than 4 years of experience in the data industry, developing data products, pipelines,\nreports and analysis for research institutions and some of the largest companies in the\nBrazilian financial sector, such as the BMG Bank, Sodexo and Pan Bank.\n\nBut Pedro is also a passionate software developer who loves to learn and teach about programming.\nAlthough Pedro uses many different languages in his work, he is specialized in the R programming language, and have given several\nlectures and courses about it, inside graduate centers (such as PPEA-UFOP^[]),\nin addition to federal and state organizations (such as FJP-MG^[]).\n\n\nPersonal Website: \n\nLinkedin: \n\nMastodon: [\\@pedropark99\\@fosstodon.org](https://fosstodon.org/@pedropark99)\n\nTwitter (X): [\\@PedroPark9](https://twitter.com/PedroPark9)\n\n## License {.unnumbered}\n\nCopyright © 2025 Pedro Duarte Faria. This book is licensed by the [CC-BY 4.0 Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/)[^cc-license].\n\n[^cc-license]: \n\n![](Figures/creative-commoms-88x31.png){width=88px}\n\n\n## Book compilation metadata {.unnumbered}\n\nThis book was compiled using the following versions of [Zig](https://ziglang.org) and [Quarto](https://quarto.org):\n\n\n- System version: Linux, 6.12.21-4-MANJARO, NA, x86_64.\n- Zig version: 0.15.0-dev.635+7dbd21bd5.\n- Quarto version: 1.4.554.\n\n\n## Book citation {.unnumbered}\n\nYou can use the following BibTex entry to cite this book:\n\n```\n@book{pedro2024,\n author = {Pedro Duarte Faria},\n title = {Introduction to Zig},\n subtitle = {a project-based book},\n month = {October},\n edition = {1},\n year = {2024},\n address = {Belo Horizonte},\n url = {https://github.com/pedropark99/zig-book}\n}\n```\n\n## Corresponding author and maintainer {.unnumbered}\n\nPedro Duarte Faria\n\nContact: [pedropark99\\@gmail.com](mailto:pedropark99@gmail.com)\n\nPersonal website: \n\n\n## Acknowledgments {.unnumbered}\n\nThis book is also a product of many conversations and exchanges that we had\nwith different people from the Zig community. I (Pedro Duarte Faria) am incredibly\ngrateful for these conversations, and also, for some direct contributions that we\nhad. Below we have a list of the people involved (name of the person with their usename in GitHub):\n\n\nCalin Martinconi (\\@martinconic), Steffen Roller (\\@sroller), Chris Boesch (\\@chrboesch), Lv Sihan (\\@Pokryton), saurabh sharma. (\\@esskayesss), slackline (\\@slackline), Markus Kurz (\\@kurz-m), Rubin Simons (\\@rubin55), Chris Boesch (\\@chrboesch), Bruno (\\@PoorlyDefinedBehaviour), Ilia Choly (\\@icholy), Korri Katti (\\@KorryKatti), Vedang Manerikar (\\@vedang), Tommaso Ricci (\\@Zorgatone), Primo Sabatini (\\@primos63), Santiago Fernandez (\\@santif), Hamza Wahed (\\@HamzaWahed), mwilbur (\\@mwilbur), Dima Budaragin (\\@dbud), Jorge Jímenez (\\@jorge-j1m), Alexander (\\@alexwheezy), Maarten Coopens (\\@maarteNNNN), Niklas Johansson (\\@Raphexion), glystik (\\@glystik), Michael Lynch (\\@mtlynch), Yashank (\\@stickyburn), _blf_ (\\@bengtfrost)\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/_freeze/references/execute-results/epub.json b/_freeze/references/execute-results/epub.json deleted file mode 100644 index eb15b841..00000000 --- a/_freeze/references/execute-results/epub.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "hash": "b3fb07f33430db017c1afb683e34205a", - "result": { - "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n::::: {.content-visible when-format=\"html\"}\n\n# References {.unnumbered}\n\n::: {#refs}\n:::\n\n:::::\n", - "supporting": [ - "references_files" - ], - "filters": [ - "rmarkdown/pagebreak.lua" - ], - "includes": {}, - "engineDependencies": { - "knitr": [ - "{\"type\":\"list\",\"attributes\":{},\"value\":[]}" - ] - }, - "preserve": null, - "postProcess": false - } -} \ No newline at end of file diff --git a/_freeze/references/execute-results/html.json b/_freeze/references/execute-results/html.json index ffc66cd5..f3e4a7c4 100644 --- a/_freeze/references/execute-results/html.json +++ b/_freeze/references/execute-results/html.json @@ -2,7 +2,7 @@ "hash": "b3fb07f33430db017c1afb683e34205a", "result": { "engine": "knitr", - "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n\n\n::::: {.content-visible when-format=\"html\"}\n\n# References {.unnumbered}\n\n::: {#refs}\n:::\n\n:::::\n", + "markdown": "---\nengine: knitr\nknitr: true\nsyntax-definition: \"./Assets/zig.xml\"\n---\n\n\n\n\n\n\n::::: {.content-visible when-format=\"html\"}\n\n# References {.unnumbered}\n\n::: {#refs}\n:::\n\n:::::\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/_quarto.yml b/_quarto.yml index 0bcbbafc..e12537fe 100644 --- a/_quarto.yml +++ b/_quarto.yml @@ -42,4 +42,7 @@ format: theme: light: cosmo dark: darkly - + # epub: + # toc: true + # lang: en-US + # date: "today" diff --git a/docs/Chapters/03-structs.html b/docs/Chapters/03-structs.html index 3be7925a..e9a0480d 100644 --- a/docs/Chapters/03-structs.html +++ b/docs/Chapters/03-structs.html @@ -476,7 +476,10 @@

    2.1.3 The defer keyword

    -

    With the defer keyword you can register an expression to be executed when you exit the current scope. Therefore, this keyword has a similar functionality as the on.exit() function from R. Take the foo() function below as an example. When we execute this foo() function, the expression that prints the message “Exiting function …” is getting executed only when the function exits its scope.

    +

    Zig has a defer keyword, which plays a very important role in control flow, and also, in releasing resources. In summary, the defer keyword allows you to register an expression to be executed when you exit the current scope.

    +

    At this point, you might attempt to compare the Zig defer keyword to it’s sibling in the Go language (i.e. Go also has a defer keyword). However, the Go defer keyword behaves slightly different than it’s sibling in Zig. More specifically, the defer keyword in Go always move an expression to be executed at the exit of the current function.

    +

    If you think deeply about this statement, you will notice that the “exit of the current function” is something slightly different than the “exit of the current scope”. So, just be careful when comparing the two keywords together. A single function in Zig might contain many different scopes inside of it, and, therefore, the defer input expression might be executed at different places of the function, depending on which scope you are currently in.

    +

    As a first example, consider the foo() function exposed below. When we execute this foo() function, the expression that prints the message “Exiting function …” is getting executed only when the function exits its scope.

    const std = @import("std");
     const stdout = std.io.getStdOut().writer();
    @@ -988,7 +991,7 @@ 

    try expect(@TypeOf(y) == u32); }

    -
    1/1 file3fc93b4ea641.test_0...OKAll 1 tests passed
    +
    1/1 file26f81ac33a52.test_0...OKAll 1 tests passed
       d.
    @@ -1005,7 +1008,7 @@

    try expect(@TypeOf(y) == f32); }

    -
    1/1 file3fc91795a712.test_0...OKAll 1 tests passed
    +
    1/1 file26f81f277e9b.test_0...OKAll 1 tests passed
       d.
    @@ -1022,7 +1025,7 @@

    try expect(@TypeOf(u32_ptr) == *const u32); }

    -
    1/1 file3fc945f8b4b0.test_0...OKAll 1 tests passed
    +
    1/1 file26f843ae7baf.test_0...OKAll 1 tests passed
       d.
    diff --git a/docs/Chapters/03-unittests.html b/docs/Chapters/03-unittests.html index 817670da..4e62a2cc 100644 --- a/docs/Chapters/03-unittests.html +++ b/docs/Chapters/03-unittests.html @@ -323,7 +323,7 @@

    try expect((a + b) == 4); }
    -
    1/1 file81c21dbf264e.test.testing simple sum...OKA
    +
    1/1 file1ed835512cf8.test.testing simple sum...OKA
       All 1 tests passed.
    @@ -396,7 +396,7 @@

    try expectError(error.OutOfMemory, alloc_error(allocator)); }
    -
    1/1 file81c24fea00d1.test.testing error...OKAll 1 
    +
    1/1 file1ed878d2d839.test.testing error...OKAll 1 
        tests passed.
    @@ -433,8 +433,8 @@

    ); }
    -
    1/1 file81c25513148.test.arrays are equal?...OKAll
    -  l 1 tests passed.
    +
    1/1 file1ed83cbad6df.test.arrays are equal?...OKAl
    +  ll 1 tests passed.

    At last, you might also want to use the expectEqualStrings() function. As the name suggests, you can use this function to test if two strings are equal or not. Just provide the two string objects that you want to compare, as inputs to the function.

    diff --git a/docs/Chapters/05-pointers.html b/docs/Chapters/05-pointers.html index 6a2731b5..d1341251 100644 --- a/docs/Chapters/05-pointers.html +++ b/docs/Chapters/05-pointers.html @@ -450,7 +450,7 @@

    6.4 Optionals and Optional Pointers

    Let’s talk about optionals and how they relate to pointers in Zig. By default, objects in Zig are non-nullable. This means that, in Zig, you can safely assume that any object in your source code is not null.

    This is a powerful feature of Zig when you compare it to the developer experience in C. Because in C, any object can be null at any point, and, as consequence, a pointer in C might point to a null value. This is a common source of undefined behaviour in C. When programmers work with pointers in C, they have to constantly check if their pointers are pointing to null values or not.

    -

    If for some reason, your Zig code produces a null value somewhere, and, this null value ends up in an object that is non-nullable, a runtime error is always raised by your Zig program. Take the program below as an example. The zig compiler can see the null value at compile time, and, as result, it raises a compile time error. But, if a null value is raised during runtime, a runtime error is also raised by the Zig program, with a “attempt to use null value” message.

    +

    In contrast, when working in Zig, if for some reason, your Zig code produces a null value somewhere, and, this null value ends up in an object that is non-nullable, a runtime error is always raised by your Zig program. Take the program below as an example. The zig compiler can see the null value at compile time, and, as result, it raises a compile time error. But, if a null value is raised during runtime, a runtime error is also raised by the Zig program, with a “attempt to use null value” message.

    var number: u8 = 5;
     number = null;
    @@ -464,7 +464,7 @@

    6.4.1 What are optionals?

    Ok, we know now that all objects are non-nullable by default in Zig. But what if we actually need to use an object that might receive a null value? Here is where optionals come in.

    -

    An optional object in Zig is an object that can be null. To mark an object as optional, we use the ? operator. When you put this ? operator right before the data type of an object, you transform this data type into an optional data type, and the object becomes an optional object.

    +

    An optional object in Zig is rather similar to a std::optional object in C++. It is an object that can either contain a value, or nothing at all (a.k.a. the object can be null). To mark an object in our Zig code as “optional”, we use the ? operator. When you put this ? operator right before the data type of an object, you transform this data type into an optional data type, and the object becomes an optional object.

    Take the snippet below as an example. We are creating a new variable object called num. This object have the data type ?i32, which means that, this object contains either a signed 32-bit integer (i32), or, a null value. Both alternatives are valid values to the num object. That is why, I can actually change the value of this object to null, and, no errors are raised by the zig compiler, as demonstrated below:

    var num: ?i32 = 5;
    diff --git a/docs/Chapters/09-error-handling.html b/docs/Chapters/09-error-handling.html
    index 9ed073b5..49eeddc6 100644
    --- a/docs/Chapters/09-error-handling.html
    +++ b/docs/Chapters/09-error-handling.html
    @@ -469,7 +469,7 @@ 

    ); }

    -
    1/1 file826379a872a1.test.coerce error value...OKA
    +
    1/1 file1f7f62fdbe33.test.coerce error value...OKA
       All 1 tests passed.
    diff --git a/docs/Chapters/10-stack-project.html b/docs/Chapters/10-stack-project.html index c9dddea2..989af503 100644 --- a/docs/Chapters/10-stack-project.html +++ b/docs/Chapters/10-stack-project.html @@ -370,7 +370,7 @@

    _ = twice(5678); }

    -
    1/1 filef044375a1f16.test.test comptime...OKAll 1 
    +
    1/1 file20a25a72e5e3.test.test comptime...OKAll 1 
        tests passed.
    @@ -435,7 +435,7 @@

    try comptime expect(fibonacci(7) == 13); }
    -
    1/1 filef0447cb16f4d.test.fibonacci...OKAll 1 test
    +
    1/1 file20a26d02bee1.test.fibonacci...OKAll 1 test
       ts passed.
    @@ -464,7 +464,7 @@

    _ = x; }
    -
    1/1 filef044524d5e27.test.fibonacci in a block...O
    +
    1/1 file20a238222e11.test.fibonacci in a block...O
       OKAll 1 tests passed.
    diff --git a/docs/index.html b/docs/index.html index 6a8a4913..cad13fc2 100644 --- a/docs/index.html +++ b/docs/index.html @@ -7,7 +7,7 @@ - + Introduction to Zig